暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Sse4_2.cs 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. namespace Unity.Burst.Intrinsics
  5. {
  6. public unsafe static partial class X86
  7. {
  8. /// <summary>
  9. /// SSE 4.2 intrinsics
  10. /// </summary>
  11. public static class Sse4_2
  12. {
  13. /// <summary>
  14. /// Evaluates to true at compile time if SSE 4.2 intrinsics are supported.
  15. /// </summary>
  16. public static bool IsSse42Supported { get { return false; } }
  17. /// <summary>
  18. /// Constants for string comparison intrinsics
  19. /// </summary>
  20. [Flags]
  21. public enum SIDD
  22. {
  23. /// <summary>
  24. /// Compare 8-bit unsigned characters
  25. /// </summary>
  26. UBYTE_OPS = 0x00,
  27. /// <summary>
  28. /// Compare 16-bit unsigned characters
  29. /// </summary>
  30. UWORD_OPS = 0x01,
  31. /// <summary>
  32. /// Compare 8-bit signed characters
  33. /// </summary>
  34. SBYTE_OPS = 0x02,
  35. /// <summary>
  36. /// Compare 16-bit signed characters
  37. /// </summary>
  38. SWORD_OPS = 0x03,
  39. /// <summary>
  40. /// Compare any equal
  41. /// </summary>
  42. CMP_EQUAL_ANY = 0x00,
  43. /// <summary>
  44. /// Compare ranges
  45. /// </summary>
  46. CMP_RANGES = 0x04,
  47. /// <summary>
  48. /// Compare equal each
  49. /// </summary>
  50. CMP_EQUAL_EACH = 0x08,
  51. /// <summary>
  52. /// Compare equal ordered
  53. /// </summary>
  54. CMP_EQUAL_ORDERED = 0x0C,
  55. /// <summary>
  56. /// Normal result polarity
  57. /// </summary>
  58. POSITIVE_POLARITY = 0x00,
  59. /// <summary>
  60. /// Negate results
  61. /// </summary>
  62. NEGATIVE_POLARITY = 0x10,
  63. /// <summary>
  64. /// Normal results only before end of string
  65. /// </summary>
  66. MASKED_POSITIVE_POLARITY = 0x20,
  67. /// <summary>
  68. /// Negate results only before end of string
  69. /// </summary>
  70. MASKED_NEGATIVE_POLARITY = 0x30,
  71. /// <summary>
  72. /// Index only: return least significant bit
  73. /// </summary>
  74. LEAST_SIGNIFICANT = 0x00,
  75. /// <summary>
  76. /// Index only: return most significan bit
  77. /// </summary>
  78. MOST_SIGNIFICANT = 0x40,
  79. /// <summary>
  80. /// mask only: return bit mask
  81. /// </summary>
  82. BIT_MASK = 0x00,
  83. /// <summary>
  84. /// mask only: return byte/word mask
  85. /// </summary>
  86. UNIT_MASK = 0x40,
  87. }
  88. /*
  89. * Intrinsics for text/string processing.
  90. */
  91. private unsafe struct StrBoolArray
  92. {
  93. public fixed ushort Bits[16];
  94. public void SetBit(int aindex, int bindex, bool val)
  95. {
  96. fixed (ushort* b = Bits)
  97. {
  98. if (val)
  99. b[aindex] |= (ushort)(1 << bindex);
  100. else
  101. b[aindex] &= (ushort)(~(1 << bindex));
  102. }
  103. }
  104. public bool GetBit(int aindex, int bindex)
  105. {
  106. fixed (ushort* b = Bits)
  107. {
  108. return (b[aindex] & (1 << bindex)) != 0;
  109. }
  110. }
  111. }
  112. private static v128 cmpistrm_emulation<T>(T* a, T* b, int len, int imm8, int allOnes, T allOnesT) where T : unmanaged, IComparable<T>, IEquatable<T>
  113. {
  114. int intRes2 = ComputeStrCmpIntRes2<T>(a, ComputeStringLength<T>(a, len), b, ComputeStringLength<T>(b, len), len, imm8, allOnes);
  115. return ComputeStrmOutput(len, imm8, allOnesT, intRes2);
  116. }
  117. private static v128 cmpestrm_emulation<T>(T* a, int alen, T* b, int blen, int len, int imm8, int allOnes, T allOnesT) where T : unmanaged, IComparable<T>, IEquatable<T>
  118. {
  119. int intRes2 = ComputeStrCmpIntRes2<T>(a, alen, b, blen, len, imm8, allOnes);
  120. return ComputeStrmOutput(len, imm8, allOnesT, intRes2);
  121. }
  122. private static v128 ComputeStrmOutput<T>(int len, int imm8, T allOnesT, int intRes2) where T : unmanaged, IComparable<T>, IEquatable<T>
  123. {
  124. // output
  125. v128 result = default;
  126. if ((imm8 & (1 << 6)) != 0)
  127. {
  128. // byte / word mask
  129. T* maskDst = (T*)&result.Byte0;
  130. for (int i = 0; i < len; ++i)
  131. {
  132. if ((intRes2 & (1 << i)) != 0)
  133. {
  134. maskDst[i] = allOnesT;
  135. }
  136. else
  137. {
  138. maskDst[i] = default(T);
  139. }
  140. }
  141. }
  142. else
  143. {
  144. // bit mask
  145. result.SInt0 = intRes2;
  146. }
  147. return result;
  148. }
  149. private static int cmpistri_emulation<T>(T* a, T* b, int len, int imm8, int allOnes, T allOnesT) where T : unmanaged, IComparable<T>, IEquatable<T>
  150. {
  151. int intRes2 = ComputeStrCmpIntRes2<T>(a, ComputeStringLength<T>(a, len), b, ComputeStringLength<T>(b, len), len, imm8, allOnes);
  152. return ComputeStriOutput(len, imm8, intRes2);
  153. }
  154. private static int cmpestri_emulation<T>(T* a, int alen, T* b, int blen, int len, int imm8, int allOnes, T allOnesT) where T : unmanaged, IComparable<T>, IEquatable<T>
  155. {
  156. int intRes2 = ComputeStrCmpIntRes2<T>(a, alen, b, blen, len, imm8, allOnes);
  157. return ComputeStriOutput(len, imm8, intRes2);
  158. }
  159. private static int ComputeStriOutput(int len, int imm8, int intRes2)
  160. {
  161. // output
  162. if ((imm8 & (1 << 6)) == 0)
  163. {
  164. int bit = 0;
  165. while (bit < len)
  166. {
  167. if ((intRes2 & (1 << bit)) != 0)
  168. return bit;
  169. ++bit;
  170. }
  171. }
  172. else
  173. {
  174. int bit = len - 1;
  175. while (bit >= 0)
  176. {
  177. if ((intRes2 & (1 << bit)) != 0)
  178. return bit;
  179. --bit;
  180. }
  181. }
  182. return len;
  183. }
  184. private static int ComputeStringLength<T>(T* ptr, int max) where T : unmanaged, IEquatable<T>
  185. {
  186. for (int i = 0; i < max; ++i)
  187. {
  188. if (EqualityComparer<T>.Default.Equals(ptr[i], default(T)))
  189. {
  190. return i;
  191. }
  192. }
  193. return max;
  194. }
  195. private static int ComputeStrCmpIntRes2<T>(T* a, int alen, T* b, int blen, int len, int imm8, int allOnes) where T : unmanaged, IComparable<T>, IEquatable<T>
  196. {
  197. #if !NET_DOTS
  198. bool aInvalid = false;
  199. bool bInvalid = false;
  200. StrBoolArray boolRes = default;
  201. int i, j, intRes2;
  202. for (i = 0; i < len; ++i)
  203. {
  204. T aCh = a[i];
  205. if (i == alen)
  206. aInvalid = true;
  207. bInvalid = false;
  208. for (j = 0; j < len; ++j)
  209. {
  210. T bCh = b[j];
  211. if (j == blen)
  212. bInvalid = true;
  213. bool match;
  214. // override comparisons for invalid characters
  215. switch ((imm8 >> 2) & 3)
  216. {
  217. case 0: // equal any
  218. match = EqualityComparer<T>.Default.Equals(aCh, bCh);
  219. if (!aInvalid && bInvalid)
  220. match = false;
  221. else if (aInvalid && !bInvalid)
  222. match = false;
  223. else if (aInvalid && bInvalid)
  224. match = false;
  225. break;
  226. case 1: // ranges
  227. if (0 == (i & 1))
  228. match = Comparer<T>.Default.Compare(bCh, aCh) >= 0;
  229. else
  230. match = Comparer<T>.Default.Compare(bCh, aCh) <= 0;
  231. if (!aInvalid && bInvalid)
  232. match = false;
  233. else if (aInvalid && !bInvalid)
  234. match = false;
  235. else if (aInvalid && bInvalid)
  236. match = false;
  237. break;
  238. case 2: // equal each
  239. match = EqualityComparer<T>.Default.Equals(aCh, bCh);
  240. if (!aInvalid && bInvalid)
  241. match = false;
  242. else if (aInvalid && !bInvalid)
  243. match = false;
  244. else if (aInvalid && bInvalid)
  245. match = true;
  246. break;
  247. default: // equal ordered
  248. match = EqualityComparer<T>.Default.Equals(aCh, bCh);
  249. if (!aInvalid && bInvalid)
  250. match = false;
  251. else if (aInvalid && !bInvalid)
  252. match = true;
  253. else if (aInvalid && bInvalid)
  254. match = true;
  255. break;
  256. }
  257. boolRes.SetBit(i, j, match);
  258. }
  259. }
  260. int intRes1 = 0;
  261. // aggregate results
  262. switch ((imm8 >> 2) & 3)
  263. {
  264. case 0: // equal any
  265. for (i = 0; i < len; ++i)
  266. {
  267. for (j = 0; j < len; ++j)
  268. {
  269. intRes1 |= (boolRes.GetBit(j, i) ? 1 : 0) << i;
  270. }
  271. }
  272. /*
  273. for (i = 0; i < len; ++i)
  274. {
  275. intRes1 |= boolRes.Bits[i];
  276. }*/
  277. break;
  278. case 1: // ranges
  279. for (i = 0; i < len; ++i)
  280. {
  281. for (j = 0; j < len; j += 2)
  282. {
  283. intRes1 |= ((boolRes.GetBit(j, i) && boolRes.GetBit(j + 1, i)) ? 1 : 0) << i;
  284. }
  285. }
  286. break;
  287. case 2: // equal each
  288. for (i = 0; i < len; ++i)
  289. {
  290. intRes1 |= (boolRes.GetBit(i, i) ? 1 : 0) << i;
  291. }
  292. break;
  293. case 3: // equal ordered
  294. intRes1 = allOnes;
  295. for (i = 0; i < len; ++i)
  296. {
  297. int k = i;
  298. for (j = 0; j < len - i; ++j)
  299. {
  300. if (!boolRes.GetBit(j, k))
  301. intRes1 &= ~(1 << i);
  302. k += 1;
  303. }
  304. }
  305. break;
  306. }
  307. intRes2 = 0;
  308. // optionally negate results
  309. bInvalid = false;
  310. for (i = 0; i < len; ++i)
  311. {
  312. if ((imm8 & (1 << 4)) != 0)
  313. {
  314. if ((imm8 & (1 << 5)) != 0) // only negate valid
  315. {
  316. if (EqualityComparer<T>.Default.Equals(b[i], default(T)))
  317. {
  318. bInvalid = true;
  319. }
  320. if (bInvalid) // invalid, don't negate
  321. intRes2 |= intRes1 & (1 << i);
  322. else // valid, negate
  323. intRes2 |= (~intRes1) & (1 << i);
  324. }
  325. else // negate all
  326. intRes2 |= (~intRes1) & (1 << i);
  327. }
  328. else // don't negate
  329. intRes2 |= intRes1 & (1 << i);
  330. }
  331. return intRes2;
  332. #else
  333. throw new NotImplementedException("dots runtime C# lacks comparer");
  334. #endif
  335. }
  336. /// <summary>
  337. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and store the generated mask in dst.
  338. /// </summary>
  339. /// <param name="a">Vector a</param>
  340. /// <param name="b">Vector b</param>
  341. /// <param name="imm8">Control</param>
  342. /// <returns>Vector</returns>
  343. [DebuggerStepThrough]
  344. public static v128 cmpistrm(v128 a, v128 b, int imm8)
  345. {
  346. v128 c;
  347. if (0 == (imm8 & 1))
  348. if (0 == (imm8 & 2))
  349. c = cmpistrm_emulation(&a.Byte0, &b.Byte0, 16, imm8, 0xffff, (byte)0xff);
  350. else
  351. c = cmpistrm_emulation(&a.SByte0, &b.SByte0, 16, imm8, 0xffff, (sbyte)-1);
  352. else
  353. if (0 == (imm8 & 2))
  354. c = cmpistrm_emulation(&a.UShort0, &b.UShort0, 8, imm8, 0xff, (ushort)0xffff);
  355. else
  356. c = cmpistrm_emulation(&a.SShort0, &b.SShort0, 8, imm8, 0xff, (short)-1);
  357. return c;
  358. }
  359. /// <summary>
  360. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and store the generated index in dst.
  361. /// </summary>
  362. /// <param name="a">Vector a</param>
  363. /// <param name="b">Vector b</param>
  364. /// <param name="imm8">Control</param>
  365. /// <returns>Index</returns>
  366. [DebuggerStepThrough]
  367. public static int cmpistri(v128 a, v128 b, int imm8)
  368. {
  369. if (0 == (imm8 & 1))
  370. if (0 == (imm8 & 2))
  371. return cmpistri_emulation(&a.Byte0, &b.Byte0, 16, imm8, 0xffff, (byte)0xff);
  372. else
  373. return cmpistri_emulation(&a.SByte0, &b.SByte0, 16, imm8, 0xffff, (sbyte)-1);
  374. else
  375. if (0 == (imm8 & 2))
  376. return cmpistri_emulation(&a.UShort0, &b.UShort0, 8, imm8, 0xff, (ushort)0xffff);
  377. else
  378. return cmpistri_emulation(&a.SShort0, &b.SShort0, 8, imm8, 0xff, (short)-1);
  379. }
  380. /// <summary>
  381. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and store the generated mask in dst.
  382. /// </summary>
  383. /// <param name="a">Vector a</param>
  384. /// <param name="b">Vector b</param>
  385. /// <param name="la">Length a</param>
  386. /// <param name="lb">Length b</param>
  387. /// <param name="imm8">Control</param>
  388. /// <returns>Vector</returns>
  389. [DebuggerStepThrough]
  390. public static v128 cmpestrm(v128 a, int la, v128 b, int lb, int imm8)
  391. {
  392. v128 c;
  393. if (0 == (imm8 & 1))
  394. if (0 == (imm8 & 2))
  395. c = cmpestrm_emulation(&a.Byte0, la, &b.Byte0, lb, 16, imm8, 0xffff, (byte)0xff);
  396. else
  397. c = cmpestrm_emulation(&a.SByte0, la, &b.SByte0, lb, 16, imm8, 0xffff, (sbyte)-1);
  398. else
  399. if (0 == (imm8 & 2))
  400. c = cmpestrm_emulation(&a.UShort0, la, &b.UShort0, lb, 8, imm8, 0xff, (ushort)0xffff);
  401. else
  402. c = cmpestrm_emulation(&a.SShort0, la, &b.SShort0, lb, 8, imm8, 0xff, (short)-1);
  403. return c;
  404. }
  405. /// <summary>
  406. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and store the generated index in dst.
  407. /// </summary>
  408. /// <param name="a">Vector a</param>
  409. /// <param name="b">Vector b</param>
  410. /// <param name="la">Length a</param>
  411. /// <param name="lb">Length b</param>
  412. /// <param name="imm8">Control</param>
  413. /// <returns>Index</returns>
  414. [DebuggerStepThrough]
  415. public static int cmpestri(v128 a, int la, v128 b, int lb, int imm8)
  416. {
  417. if (0 == (imm8 & 1))
  418. if (0 == (imm8 & 2))
  419. return cmpestri_emulation(&a.Byte0, la, &b.Byte0, lb, 16, imm8, 0xffff, (byte)0xff);
  420. else
  421. return cmpestri_emulation(&a.SByte0, la, &b.SByte0, lb, 16, imm8, 0xffff, (sbyte)-1);
  422. else
  423. if (0 == (imm8 & 2))
  424. return cmpestri_emulation(&a.UShort0, la, &b.UShort0, lb, 8, imm8, 0xff, (ushort)0xffff);
  425. else
  426. return cmpestri_emulation(&a.SShort0, la, &b.SShort0, lb, 8, imm8, 0xff, (short)-1);
  427. }
  428. /*
  429. * Intrinsics for text/string processing and reading values of EFlags.
  430. */
  431. /// <summary>
  432. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and returns 1 if any character in b was null, and 0 otherwise.
  433. /// </summary>
  434. /// <param name="a">Vector a</param>
  435. /// <param name="b">Vector b</param>
  436. /// <param name="imm8">Control</param>
  437. /// <returns>Boolean value</returns>
  438. [DebuggerStepThrough]
  439. public static int cmpistrz(v128 a, v128 b, int imm8)
  440. {
  441. if (0 == (imm8 & 1))
  442. return ComputeStringLength<byte>(&b.Byte0, 16) < 16 ? 1 : 0;
  443. else
  444. return ComputeStringLength<ushort>(&b.UShort0, 8) < 8 ? 1 : 0;
  445. }
  446. /// <summary>
  447. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and returns 1 if the resulting mask was non-zero, and 0 otherwise.
  448. /// </summary>
  449. /// <param name="a">Vector a</param>
  450. /// <param name="b">Vector b</param>
  451. /// <param name="imm8">Control</param>
  452. /// <returns>Boolean value</returns>
  453. [DebuggerStepThrough]
  454. public static int cmpistrc(v128 a, v128 b, int imm8)
  455. {
  456. v128 q = cmpistrm(a, b, imm8);
  457. return q.SInt0 == 0 && q.SInt1 == 0 && q.SInt2 == 0 && q.SInt3 == 0 ? 0 : 1;
  458. }
  459. /// <summary>
  460. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and returns 1 if any character in a was null, and 0 otherwise.
  461. /// </summary>
  462. /// <param name="a">Vector a</param>
  463. /// <param name="b">Vector b</param>
  464. /// <param name="imm8">Control</param>
  465. /// <returns>Boolean value</returns>
  466. [DebuggerStepThrough]
  467. public static int cmpistrs(v128 a, v128 b, int imm8)
  468. {
  469. if (0 == (imm8 & 1))
  470. return ComputeStringLength<byte>(&a.Byte0, 16) < 16 ? 1 : 0;
  471. else
  472. return ComputeStringLength<ushort>(&a.UShort0, 8) < 8 ? 1 : 0;
  473. }
  474. /// <summary>
  475. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and returns bit 0 of the resulting bit mask.
  476. /// </summary>
  477. /// <param name="a">Vector a</param>
  478. /// <param name="b">Vector b</param>
  479. /// <param name="imm8">Control</param>
  480. /// <returns>Bit 0</returns>
  481. [DebuggerStepThrough]
  482. public static int cmpistro(v128 a, v128 b, int imm8)
  483. {
  484. int intRes2;
  485. if (0 == (imm8 & 1))
  486. {
  487. int al = ComputeStringLength<byte>(&a.Byte0, 16);
  488. int bl = ComputeStringLength<byte>(&b.Byte0, 16);
  489. if (0 == (imm8 & 2))
  490. intRes2 = ComputeStrCmpIntRes2<byte>(&a.Byte0, al, &b.Byte0, bl, 16, imm8, 0xffff);
  491. else
  492. intRes2 = ComputeStrCmpIntRes2<sbyte>(&a.SByte0, al, &b.SByte0, bl, 16, imm8, 0xffff);
  493. }
  494. else
  495. {
  496. int al = ComputeStringLength<ushort>(&a.UShort0, 8);
  497. int bl = ComputeStringLength<ushort>(&b.UShort0, 8);
  498. if (0 == (imm8 & 2))
  499. intRes2 = ComputeStrCmpIntRes2<ushort>(&a.UShort0, al, &b.UShort0, bl, 8, imm8, 0xff);
  500. else
  501. intRes2 = ComputeStrCmpIntRes2<short>(&a.SShort0, al, &b.SShort0, bl, 8, imm8, 0xff);
  502. }
  503. return intRes2 & 1;
  504. }
  505. /// <summary>
  506. /// Compare packed strings with implicit lengths in a and b using the control in imm8, and returns 1 if b did not contain a null character and the resulting mask was zero, and 0 otherwise.
  507. /// </summary>
  508. /// <param name="a">Vector a</param>
  509. /// <param name="b">Vector b</param>
  510. /// <param name="imm8">Control</param>
  511. /// <returns>Boolean value</returns>
  512. [DebuggerStepThrough]
  513. public static int cmpistra(v128 a, v128 b, int imm8)
  514. {
  515. return ((~cmpistrc(a, b, imm8)) & (~cmpistrz(a, b, imm8))) & 1;
  516. }
  517. /// <summary>
  518. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and returns 1 if any character in b was null, and 0 otherwise.
  519. /// </summary>
  520. /// <param name="a">Vector a</param>
  521. /// <param name="b">Vector b</param>
  522. /// <param name="la">Length a</param>
  523. /// <param name="lb">Length b</param>
  524. /// <param name="imm8">Control</param>
  525. /// <returns>Boolean value</returns>
  526. [DebuggerStepThrough]
  527. public static int cmpestrz(v128 a, int la, v128 b, int lb, int imm8)
  528. {
  529. int size = (imm8 & 1) == 1 ? 16 : 8;
  530. int upperBound = (128 / size) - 1;
  531. return lb <= upperBound ? 1 : 0;
  532. }
  533. /// <summary>
  534. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and returns 1 if the resulting mask was non-zero, and 0 otherwise.
  535. /// </summary>
  536. /// <param name="a">Vector a</param>
  537. /// <param name="b">Vector b</param>
  538. /// <param name="la">Length a</param>
  539. /// <param name="lb">Length b</param>
  540. /// <param name="imm8">Control</param>
  541. /// <returns>Boolean value</returns>
  542. [DebuggerStepThrough]
  543. public static int cmpestrc(v128 a, int la, v128 b, int lb, int imm8)
  544. {
  545. int intRes2;
  546. if (0 == (imm8 & 1))
  547. {
  548. if (0 == (imm8 & 2))
  549. intRes2 = ComputeStrCmpIntRes2<byte>(&a.Byte0, la, &b.Byte0, lb, 16, imm8, 0xffff);
  550. else
  551. intRes2 = ComputeStrCmpIntRes2<sbyte>(&a.SByte0, la, &b.SByte0, lb, 16, imm8, 0xffff);
  552. }
  553. else
  554. {
  555. if (0 == (imm8 & 2))
  556. intRes2 = ComputeStrCmpIntRes2<ushort>(&a.UShort0, la, &b.UShort0, lb, 8, imm8, 0xff);
  557. else
  558. intRes2 = ComputeStrCmpIntRes2<short>(&a.SShort0, la, &b.SShort0, lb, 8, imm8, 0xff);
  559. }
  560. return intRes2 != 0 ? 1 : 0;
  561. }
  562. /// <summary>
  563. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and returns 1 if any character in a was null, and 0 otherwise.
  564. /// </summary>
  565. /// <param name="a">Vector a</param>
  566. /// <param name="b">Vector b</param>
  567. /// <param name="la">Length a</param>
  568. /// <param name="lb">Length b</param>
  569. /// <param name="imm8">Control</param>
  570. /// <returns>Boolean value</returns>
  571. [DebuggerStepThrough]
  572. public static int cmpestrs(v128 a, int la, v128 b, int lb, int imm8)
  573. {
  574. int size = (imm8 & 1) == 1 ? 16 : 8;
  575. int upperBound = (128 / size) - 1;
  576. return la <= upperBound ? 1 : 0;
  577. }
  578. /// <summary>
  579. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and returns bit 0 of the resulting bit mask.
  580. /// </summary>
  581. /// <param name="a">Vector a</param>
  582. /// <param name="b">Vector b</param>
  583. /// <param name="la">Length a</param>
  584. /// <param name="lb">Length b</param>
  585. /// <param name="imm8">Control</param>
  586. /// <returns>Bit 0</returns>
  587. [DebuggerStepThrough]
  588. public static int cmpestro(v128 a, int la, v128 b, int lb, int imm8)
  589. {
  590. int intRes2;
  591. if (0 == (imm8 & 1))
  592. {
  593. if (0 == (imm8 & 2))
  594. intRes2 = ComputeStrCmpIntRes2<byte>(&a.Byte0, la, &b.Byte0, lb, 16, imm8, 0xffff);
  595. else
  596. intRes2 = ComputeStrCmpIntRes2<sbyte>(&a.SByte0, la, &b.SByte0, lb, 16, imm8, 0xffff);
  597. }
  598. else
  599. {
  600. if (0 == (imm8 & 2))
  601. intRes2 = ComputeStrCmpIntRes2<ushort>(&a.UShort0, la, &b.UShort0, lb, 8, imm8, 0xff);
  602. else
  603. intRes2 = ComputeStrCmpIntRes2<short>(&a.SShort0, la, &b.SShort0, lb, 8, imm8, 0xff);
  604. }
  605. return intRes2 & 1;
  606. }
  607. /// <summary>
  608. /// Compare packed strings in a and b with lengths la and lb using the control in imm8, and returns 1 if b did not contain a null character and the resulting mask was zero, and 0 otherwise.
  609. /// </summary>
  610. /// <param name="a">Vector a</param>
  611. /// <param name="b">Vector b</param>
  612. /// <param name="la">Length a</param>
  613. /// <param name="lb">Length b</param>
  614. /// <param name="imm8">Control</param>
  615. /// <returns>Boolean value</returns>
  616. [DebuggerStepThrough]
  617. public static int cmpestra(v128 a, int la, v128 b, int lb, int imm8)
  618. {
  619. return ((~cmpestrc(a, la, b, lb, imm8)) & (~cmpestrz(a, la, b, lb, imm8))) & 1;
  620. }
  621. /// <summary>
  622. /// Compare packed 64-bit integers in a and b for greater-than, and store the results in dst.
  623. /// </summary>
  624. /// <param name="val1">Vector a</param>
  625. /// <param name="val2">Vector b</param>
  626. /// <returns>Vector</returns>
  627. [DebuggerStepThrough]
  628. public static v128 cmpgt_epi64(v128 val1, v128 val2)
  629. {
  630. v128 result = default;
  631. result.SLong0 = val1.SLong0 > val2.SLong0 ? -1 : 0;
  632. result.SLong1 = val1.SLong1 > val2.SLong1 ? -1 : 0;
  633. return result;
  634. }
  635. /*
  636. * Accumulate CRC32 (polynomial 0x11EDC6F41) value
  637. */
  638. private static readonly uint[] crctab = new uint[]
  639. {
  640. 0x00000000U,0xF26B8303U,0xE13B70F7U,0x1350F3F4U,0xC79A971FU,0x35F1141CU,0x26A1E7E8U,0xD4CA64EBU,
  641. 0x8AD958CFU,0x78B2DBCCU,0x6BE22838U,0x9989AB3BU,0x4D43CFD0U,0xBF284CD3U,0xAC78BF27U,0x5E133C24U,
  642. 0x105EC76FU,0xE235446CU,0xF165B798U,0x030E349BU,0xD7C45070U,0x25AFD373U,0x36FF2087U,0xC494A384U,
  643. 0x9A879FA0U,0x68EC1CA3U,0x7BBCEF57U,0x89D76C54U,0x5D1D08BFU,0xAF768BBCU,0xBC267848U,0x4E4DFB4BU,
  644. 0x20BD8EDEU,0xD2D60DDDU,0xC186FE29U,0x33ED7D2AU,0xE72719C1U,0x154C9AC2U,0x061C6936U,0xF477EA35U,
  645. 0xAA64D611U,0x580F5512U,0x4B5FA6E6U,0xB93425E5U,0x6DFE410EU,0x9F95C20DU,0x8CC531F9U,0x7EAEB2FAU,
  646. 0x30E349B1U,0xC288CAB2U,0xD1D83946U,0x23B3BA45U,0xF779DEAEU,0x05125DADU,0x1642AE59U,0xE4292D5AU,
  647. 0xBA3A117EU,0x4851927DU,0x5B016189U,0xA96AE28AU,0x7DA08661U,0x8FCB0562U,0x9C9BF696U,0x6EF07595U,
  648. 0x417B1DBCU,0xB3109EBFU,0xA0406D4BU,0x522BEE48U,0x86E18AA3U,0x748A09A0U,0x67DAFA54U,0x95B17957U,
  649. 0xCBA24573U,0x39C9C670U,0x2A993584U,0xD8F2B687U,0x0C38D26CU,0xFE53516FU,0xED03A29BU,0x1F682198U,
  650. 0x5125DAD3U,0xA34E59D0U,0xB01EAA24U,0x42752927U,0x96BF4DCCU,0x64D4CECFU,0x77843D3BU,0x85EFBE38U,
  651. 0xDBFC821CU,0x2997011FU,0x3AC7F2EBU,0xC8AC71E8U,0x1C661503U,0xEE0D9600U,0xFD5D65F4U,0x0F36E6F7U,
  652. 0x61C69362U,0x93AD1061U,0x80FDE395U,0x72966096U,0xA65C047DU,0x5437877EU,0x4767748AU,0xB50CF789U,
  653. 0xEB1FCBADU,0x197448AEU,0x0A24BB5AU,0xF84F3859U,0x2C855CB2U,0xDEEEDFB1U,0xCDBE2C45U,0x3FD5AF46U,
  654. 0x7198540DU,0x83F3D70EU,0x90A324FAU,0x62C8A7F9U,0xB602C312U,0x44694011U,0x5739B3E5U,0xA55230E6U,
  655. 0xFB410CC2U,0x092A8FC1U,0x1A7A7C35U,0xE811FF36U,0x3CDB9BDDU,0xCEB018DEU,0xDDE0EB2AU,0x2F8B6829U,
  656. 0x82F63B78U,0x709DB87BU,0x63CD4B8FU,0x91A6C88CU,0x456CAC67U,0xB7072F64U,0xA457DC90U,0x563C5F93U,
  657. 0x082F63B7U,0xFA44E0B4U,0xE9141340U,0x1B7F9043U,0xCFB5F4A8U,0x3DDE77ABU,0x2E8E845FU,0xDCE5075CU,
  658. 0x92A8FC17U,0x60C37F14U,0x73938CE0U,0x81F80FE3U,0x55326B08U,0xA759E80BU,0xB4091BFFU,0x466298FCU,
  659. 0x1871A4D8U,0xEA1A27DBU,0xF94AD42FU,0x0B21572CU,0xDFEB33C7U,0x2D80B0C4U,0x3ED04330U,0xCCBBC033U,
  660. 0xA24BB5A6U,0x502036A5U,0x4370C551U,0xB11B4652U,0x65D122B9U,0x97BAA1BAU,0x84EA524EU,0x7681D14DU,
  661. 0x2892ED69U,0xDAF96E6AU,0xC9A99D9EU,0x3BC21E9DU,0xEF087A76U,0x1D63F975U,0x0E330A81U,0xFC588982U,
  662. 0xB21572C9U,0x407EF1CAU,0x532E023EU,0xA145813DU,0x758FE5D6U,0x87E466D5U,0x94B49521U,0x66DF1622U,
  663. 0x38CC2A06U,0xCAA7A905U,0xD9F75AF1U,0x2B9CD9F2U,0xFF56BD19U,0x0D3D3E1AU,0x1E6DCDEEU,0xEC064EEDU,
  664. 0xC38D26C4U,0x31E6A5C7U,0x22B65633U,0xD0DDD530U,0x0417B1DBU,0xF67C32D8U,0xE52CC12CU,0x1747422FU,
  665. 0x49547E0BU,0xBB3FFD08U,0xA86F0EFCU,0x5A048DFFU,0x8ECEE914U,0x7CA56A17U,0x6FF599E3U,0x9D9E1AE0U,
  666. 0xD3D3E1ABU,0x21B862A8U,0x32E8915CU,0xC083125FU,0x144976B4U,0xE622F5B7U,0xF5720643U,0x07198540U,
  667. 0x590AB964U,0xAB613A67U,0xB831C993U,0x4A5A4A90U,0x9E902E7BU,0x6CFBAD78U,0x7FAB5E8CU,0x8DC0DD8FU,
  668. 0xE330A81AU,0x115B2B19U,0x020BD8EDU,0xF0605BEEU,0x24AA3F05U,0xD6C1BC06U,0xC5914FF2U,0x37FACCF1U,
  669. 0x69E9F0D5U,0x9B8273D6U,0x88D28022U,0x7AB90321U,0xAE7367CAU,0x5C18E4C9U,0x4F48173DU,0xBD23943EU,
  670. 0xF36E6F75U,0x0105EC76U,0x12551F82U,0xE03E9C81U,0x34F4F86AU,0xC69F7B69U,0xD5CF889DU,0x27A40B9EU,
  671. 0x79B737BAU,0x8BDCB4B9U,0x988C474DU,0x6AE7C44EU,0xBE2DA0A5U,0x4C4623A6U,0x5F16D052U,0xAD7D5351U,
  672. };
  673. /// <summary>
  674. /// Starting with the initial value in crc, accumulates a CRC32 value for unsigned 32-bit integer v, and stores the result in dst.
  675. /// </summary>
  676. /// <param name="crc">Initial value</param>
  677. /// <param name="v">Unsigned 32-bit integer</param>
  678. /// <returns>Result</returns>
  679. [DebuggerStepThrough]
  680. public static uint crc32_u32(uint crc, uint v)
  681. {
  682. crc = crc32_u8(crc, (byte)v); v >>= 8;
  683. crc = crc32_u8(crc, (byte)v); v >>= 8;
  684. crc = crc32_u8(crc, (byte)v); v >>= 8;
  685. crc = crc32_u8(crc, (byte)v);
  686. return crc;
  687. }
  688. /// <summary>
  689. /// Starting with the initial value in crc, accumulates a CRC32 value for unsigned 8-bit integer v, and stores the result in dst.
  690. /// </summary>
  691. /// <param name="crc">Initial value</param>
  692. /// <param name="v">Unsigned 8-bit integer</param>
  693. /// <returns>Result</returns>
  694. [DebuggerStepThrough]
  695. public static uint crc32_u8(uint crc, byte v)
  696. {
  697. crc = (crc >> 8) ^ crctab[(crc ^ v) & 0xff];
  698. return crc;
  699. }
  700. /// <summary>
  701. /// Starting with the initial value in crc, accumulates a CRC32 value for unsigned 16-bit integer v, and stores the result in dst.
  702. /// </summary>
  703. /// <param name="crc">Initial value</param>
  704. /// <param name="v">Unsigned 16-bit integer</param>
  705. /// <returns>Result</returns>
  706. [DebuggerStepThrough]
  707. public static uint crc32_u16(uint crc, ushort v)
  708. {
  709. crc = crc32_u8(crc, (byte)v); v >>= 8;
  710. crc = crc32_u8(crc, (byte)v);
  711. return crc;
  712. }
  713. /// <summary>
  714. /// Starting with the initial value in crc, accumulates a CRC32 value for unsigned 64-bit integer v, and stores the result in dst.
  715. /// </summary>
  716. /// <param name="crc_ul">Initial value</param>
  717. /// <param name="v">Signed 64-bit integer</param>
  718. /// <returns>Result</returns>
  719. [DebuggerStepThrough]
  720. [Obsolete("Use the ulong version of this intrinsic instead.")]
  721. public static ulong crc32_u64(ulong crc_ul, long v)
  722. {
  723. return crc32_u64(crc_ul, (ulong)v);
  724. }
  725. /// <summary>
  726. /// Starting with the initial value in crc, accumulates a CRC32 value for unsigned 64-bit integer v, and stores the result in dst.
  727. /// </summary>
  728. /// <param name="crc_ul">Initial value</param>
  729. /// <param name="v">Unsigned 64-bit integer</param>
  730. /// <returns>Result</returns>
  731. [DebuggerStepThrough]
  732. public static ulong crc32_u64(ulong crc_ul, ulong v)
  733. {
  734. uint crc = (uint)crc_ul;
  735. crc = crc32_u8(crc, (byte)v); v >>= 8;
  736. crc = crc32_u8(crc, (byte)v); v >>= 8;
  737. crc = crc32_u8(crc, (byte)v); v >>= 8;
  738. crc = crc32_u8(crc, (byte)v); v >>= 8;
  739. crc = crc32_u8(crc, (byte)v); v >>= 8;
  740. crc = crc32_u8(crc, (byte)v); v >>= 8;
  741. crc = crc32_u8(crc, (byte)v); v >>= 8;
  742. crc = crc32_u8(crc, (byte)v);
  743. return crc;
  744. }
  745. }
  746. }
  747. }