Ei kuvausta
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_1.cs 47KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. using System;
  2. using System.Diagnostics;
  3. namespace Unity.Burst.Intrinsics
  4. {
  5. public unsafe static partial class X86
  6. {
  7. /// <summary>
  8. /// SSE 4.1 intrinsics
  9. /// </summary>
  10. public static class Sse4_1
  11. {
  12. /// <summary>
  13. /// Evaluates to true at compile time if SSE 4.1 intrinsics are supported.
  14. /// </summary>
  15. public static bool IsSse41Supported { get { return false; } }
  16. // _mm_stream_load_si128
  17. /// <summary>
  18. /// Load 128-bits of integer data from memory into dst using a non-temporal memory hint. mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated.
  19. /// </summary>
  20. /// <param name="mem_addr">Memory address</param>
  21. /// <returns>Vector</returns>
  22. [DebuggerStepThrough]
  23. public static v128 stream_load_si128(void* mem_addr)
  24. {
  25. return GenericCSharpLoad(mem_addr);
  26. }
  27. // _mm_blend_pd
  28. /// <summary> Blend packed double-precision (64-bit) floating-point elements from "a" and "b" using control mask "imm8", and store the results in "dst". </summary>
  29. /// <param name="a">Vector a</param>
  30. /// <param name="b">Vector b</param>
  31. /// <param name="imm8">Control mask</param>
  32. /// <returns>Vector</returns>
  33. [DebuggerStepThrough]
  34. public static v128 blend_pd(v128 a, v128 b, int imm8)
  35. {
  36. int j;
  37. v128 dst = default(v128);
  38. double* dptr = &dst.Double0;
  39. double* aptr = &a.Double0;
  40. double* bptr = &b.Double0;
  41. for (j = 0; j <= 1; j++)
  42. {
  43. if (0 != (imm8 & (1 << j)))
  44. {
  45. dptr[j] = bptr[j];
  46. }
  47. else
  48. {
  49. dptr[j] = aptr[j];
  50. }
  51. }
  52. return dst;
  53. }
  54. // _mm_blend_ps
  55. /// <summary> Blend packed single-precision (32-bit) floating-point elements from "a" and "b" using control mask "imm8", and store the results in "dst". </summary>
  56. /// <param name="a">Vector a</param>
  57. /// <param name="b">Vector b</param>
  58. /// <param name="imm8">Control mask</param>
  59. /// <returns>Vector</returns>
  60. [DebuggerStepThrough]
  61. public static v128 blend_ps(v128 a, v128 b, int imm8)
  62. {
  63. int j;
  64. v128 dst = default(v128);
  65. // Use integers, rather than floats, because of a Mono bug.
  66. uint* dptr = &dst.UInt0;
  67. uint* aptr = &a.UInt0;
  68. uint* bptr = &b.UInt0;
  69. for (j = 0; j <= 3; j++)
  70. {
  71. if (0 != (imm8 & (1 << j)))
  72. {
  73. dptr[j] = bptr[j];
  74. }
  75. else
  76. {
  77. dptr[j] = aptr[j];
  78. }
  79. }
  80. return dst;
  81. }
  82. // _mm_blendv_pd
  83. /// <summary> Blend packed double-precision (64-bit) floating-point elements from "a" and "b" using "mask", and store the results in "dst". </summary>
  84. /// <param name="a">Vector a</param>
  85. /// <param name="b">Vector b</param>
  86. /// <param name="mask">Mask</param>
  87. /// <returns>Vector</returns>
  88. [DebuggerStepThrough]
  89. public static v128 blendv_pd(v128 a, v128 b, v128 mask)
  90. {
  91. int j;
  92. v128 dst = default(v128);
  93. double* dptr = &dst.Double0;
  94. double* aptr = &a.Double0;
  95. double* bptr = &b.Double0;
  96. long* mptr = &mask.SLong0;
  97. for (j = 0; j <= 1; j++)
  98. {
  99. if (mptr[j] < 0)
  100. {
  101. dptr[j] = bptr[j];
  102. }
  103. else
  104. {
  105. dptr[j] = aptr[j];
  106. }
  107. }
  108. return dst;
  109. }
  110. // _mm_blendv_ps
  111. /// <summary> Blend packed single-precision (32-bit) floating-point elements from "a" and "b" using "mask", and store the results in "dst". </summary>
  112. /// <param name="a">Vector a</param>
  113. /// <param name="b">Vector b</param>
  114. /// <param name="mask">Mask</param>
  115. /// <returns>Vector</returns>
  116. [DebuggerStepThrough]
  117. public static v128 blendv_ps(v128 a, v128 b, v128 mask)
  118. {
  119. int j;
  120. v128 dst = default(v128);
  121. // Use integers, rather than floats, because of a Mono bug.
  122. uint* dptr = &dst.UInt0;
  123. uint* aptr = &a.UInt0;
  124. uint* bptr = &b.UInt0;
  125. int* mptr = &mask.SInt0;
  126. for (j = 0; j <= 3; j++)
  127. {
  128. if (mptr[j] < 0)
  129. {
  130. dptr[j] = bptr[j];
  131. }
  132. else
  133. {
  134. dptr[j] = aptr[j];
  135. }
  136. }
  137. return dst;
  138. }
  139. // _mm_blendv_epi8
  140. /// <summary> Blend packed 8-bit integers from "a" and "b" using "mask", and store the results in "dst". </summary>
  141. /// <param name="a">Vector a</param>
  142. /// <param name="b">Vector b</param>
  143. /// <param name="mask">Mask</param>
  144. /// <returns>Vector</returns>
  145. [DebuggerStepThrough]
  146. public static v128 blendv_epi8(v128 a, v128 b, v128 mask)
  147. {
  148. int j;
  149. v128 dst = default(v128);
  150. byte* dptr = &dst.Byte0;
  151. byte* aptr = &a.Byte0;
  152. byte* bptr = &b.Byte0;
  153. sbyte* mptr = &mask.SByte0;
  154. for (j = 0; j <= 15; j++)
  155. {
  156. if (mptr[j] < 0)
  157. {
  158. dptr[j] = bptr[j];
  159. }
  160. else
  161. {
  162. dptr[j] = aptr[j];
  163. }
  164. }
  165. return dst;
  166. }
  167. // _mm_blend_epi16
  168. /// <summary> Blend packed 16-bit integers from "a" and "b" using control mask "imm8", and store the results in "dst". </summary>
  169. /// <param name="a">Vector a</param>
  170. /// <param name="b">Vector b</param>
  171. /// <param name="imm8">Control mask</param>
  172. /// <returns>Vector</returns>
  173. [DebuggerStepThrough]
  174. public static v128 blend_epi16(v128 a, v128 b, int imm8)
  175. {
  176. int j;
  177. v128 dst = default(v128);
  178. short* dptr = &dst.SShort0;
  179. short* aptr = &a.SShort0;
  180. short* bptr = &b.SShort0;
  181. for (j = 0; j <= 7; j++)
  182. {
  183. if (0 != ((imm8 >> j) & 1))
  184. {
  185. dptr[j] = bptr[j];
  186. }
  187. else
  188. {
  189. dptr[j] = aptr[j];
  190. }
  191. }
  192. return dst;
  193. }
  194. // _mm_dp_pd
  195. /// <summary> Conditionally multiply the packed double-precision (64-bit) floating-point elements in "a" and "b" using the high 4 bits in "imm8", sum the four products, and conditionally store the sum in "dst" using the low 4 bits of "imm8". </summary>
  196. /// <param name="a">Vector a</param>
  197. /// <param name="b">Vector b</param>
  198. /// <param name="imm8">High 4 bits in imm8</param>
  199. /// <returns>Vector</returns>
  200. [DebuggerStepThrough]
  201. public static v128 dp_pd(v128 a, v128 b, int imm8)
  202. {
  203. double t0 = (imm8 & 0x10) != 0 ? a.Double0 * b.Double0 : 0.0;
  204. double t1 = (imm8 & 0x20) != 0 ? a.Double1 * b.Double1 : 0.0;
  205. double sum = t0 + t1;
  206. v128 dst = default(v128);
  207. dst.Double0 = (imm8 & 1) != 0 ? sum : 0.0;
  208. dst.Double1 = (imm8 & 2) != 0 ? sum : 0.0;
  209. return dst;
  210. }
  211. // _mm_dp_ps
  212. /// <summary> Conditionally multiply the packed single-precision (32-bit) floating-point elements in "a" and "b" using the high 4 bits in "imm8", sum the four products, and conditionally store the sum in "dst" using the low 4 bits of "imm8". </summary>
  213. /// <param name="a">Vector a</param>
  214. /// <param name="b">Vector b</param>
  215. /// <param name="imm8">High 4 bits in imm8</param>
  216. /// <returns>Vector</returns>
  217. [DebuggerStepThrough]
  218. public static v128 dp_ps(v128 a, v128 b, int imm8)
  219. {
  220. float t0 = (imm8 & 0x10) != 0 ? a.Float0 * b.Float0 : 0.0f;
  221. float t1 = (imm8 & 0x20) != 0 ? a.Float1 * b.Float1 : 0.0f;
  222. float t2 = (imm8 & 0x40) != 0 ? a.Float2 * b.Float2 : 0.0f;
  223. float t3 = (imm8 & 0x80) != 0 ? a.Float3 * b.Float3 : 0.0f;
  224. float sum = t0 + t1 + t2 + t3;
  225. v128 dst = default(v128);
  226. dst.Float0 = (imm8 & 1) != 0 ? sum : 0.0f;
  227. dst.Float1 = (imm8 & 2) != 0 ? sum : 0.0f;
  228. dst.Float2 = (imm8 & 4) != 0 ? sum : 0.0f;
  229. dst.Float3 = (imm8 & 8) != 0 ? sum : 0.0f;
  230. return dst;
  231. }
  232. // _mm_extract_ps
  233. /// <summary> Extract a single-precision (32-bit) floating-point element from "a", selected with "imm8", and store the result in "dst". </summary>
  234. /// <param name="a">Vector a</param>
  235. /// <param name="imm8">imm8</param>
  236. /// <returns>Integer</returns>
  237. [DebuggerStepThrough]
  238. public static int extract_ps(v128 a, int imm8)
  239. {
  240. int* iptr = &a.SInt0;
  241. return iptr[imm8 & 0x3];
  242. }
  243. // unity extension
  244. /// <summary> Extract a single-precision (32-bit) floating-point element from "a", selected with "imm8", and store the result in "dst" (as a float).</summary>
  245. /// <param name="a">Vector a</param>
  246. /// <param name="imm8">imm8</param>
  247. /// <returns>Float</returns>
  248. [DebuggerStepThrough]
  249. public static float extractf_ps(v128 a, int imm8)
  250. {
  251. float* fptr = &a.Float0;
  252. return fptr[imm8 & 0x3];
  253. }
  254. // _mm_extract_epi8
  255. /// <summary> Extract an 8-bit integer from "a", selected with "imm8", and store the result in the lower element of "dst". </summary>
  256. /// <param name="a">Vector a</param>
  257. /// <param name="imm8">imm8</param>
  258. /// <returns>Byte</returns>
  259. [DebuggerStepThrough]
  260. public static byte extract_epi8(v128 a, int imm8)
  261. {
  262. byte* bptr = &a.Byte0;
  263. return bptr[imm8 & 0xf];
  264. }
  265. // _mm_extract_epi32
  266. /// <summary> Extract a 32-bit integer from "a", selected with "imm8", and store the result in "dst". </summary>
  267. /// <param name="a">Vector a</param>
  268. /// <param name="imm8">imm8</param>
  269. /// <returns>Integer</returns>
  270. [DebuggerStepThrough]
  271. public static int extract_epi32(v128 a, int imm8)
  272. {
  273. int* iptr = &a.SInt0;
  274. return iptr[imm8 & 0x3];
  275. }
  276. // _mm_extract_epi64
  277. /// <summary> Extract a 64-bit integer from "a", selected with "imm8", and store the result in "dst". </summary>
  278. /// <param name="a">Vector a</param>
  279. /// <param name="imm8">imm8</param>
  280. /// <returns>64-bit integer</returns>
  281. [DebuggerStepThrough]
  282. public static long extract_epi64(v128 a, int imm8)
  283. {
  284. long* lptr = &a.SLong0;
  285. return lptr[imm8 & 0x1];
  286. }
  287. // _mm_insert_ps
  288. /// <summary> Copy "a" to "tmp", then insert a single-precision (32-bit) floating-point element from "b" into "tmp" using the control in "imm8". Store "tmp" to "dst" using the mask in "imm8" (elements are zeroed out when the corresponding bit is set). </summary>
  289. /// <param name="a">Vector a</param>
  290. /// <param name="b">Vector b</param>
  291. /// <param name="imm8">Control mask</param>
  292. /// <returns>Vector</returns>
  293. [DebuggerStepThrough]
  294. public static v128 insert_ps(v128 a, v128 b, int imm8)
  295. {
  296. v128 dst = a;
  297. (&dst.Float0)[(imm8 >> 4) & 3] = (&b.Float0)[(imm8 >> 6) & 3];
  298. for (int i = 0; i < 4; ++i)
  299. {
  300. if (0 != (imm8 & (1 << i)))
  301. (&dst.Float0)[i] = 0.0f;
  302. }
  303. return dst;
  304. }
  305. // _mm_insert_epi8
  306. /// <summary> Copy "a" to "dst", and insert the lower 8-bit integer from "i" into "dst" at the location specified by "imm8". </summary>
  307. /// <param name="a">Vector a</param>
  308. /// <param name="i">lower 8-bit integer</param>
  309. /// <param name="imm8">Location</param>
  310. /// <returns>Vector</returns>
  311. [DebuggerStepThrough]
  312. public static v128 insert_epi8(v128 a, byte i, int imm8)
  313. {
  314. v128 dst = a;
  315. (&dst.Byte0)[imm8 & 0xf] = i;
  316. return dst;
  317. }
  318. // _mm_insert_epi32
  319. /// <summary> Copy "a" to "dst", and insert the 32-bit integer "i" into "dst" at the location specified by "imm8". </summary>
  320. /// <param name="a">Vector a</param>
  321. /// <param name="i">32-bit integer</param>
  322. /// <param name="imm8">Location</param>
  323. /// <returns>Vector</returns>
  324. [DebuggerStepThrough]
  325. public static v128 insert_epi32(v128 a, int i, int imm8)
  326. {
  327. v128 dst = a;
  328. (&dst.SInt0)[imm8 & 0x3] = i;
  329. return dst;
  330. }
  331. // _mm_insert_epi64
  332. /// <summary> Copy "a" to "dst", and insert the 64-bit integer "i" into "dst" at the location specified by "imm8". </summary>
  333. /// <param name="a">Vector a</param>
  334. /// <param name="i">64-bit integer</param>
  335. /// <param name="imm8">Location</param>
  336. /// <returns>Vector</returns>
  337. [DebuggerStepThrough]
  338. public static v128 insert_epi64(v128 a, long i, int imm8)
  339. {
  340. v128 dst = a;
  341. (&dst.SLong0)[imm8 & 0x1] = i;
  342. return dst;
  343. }
  344. // _mm_max_epi8
  345. /// <summary> Compare packed 8-bit integers in "a" and "b", and store packed maximum values in "dst". </summary>
  346. /// <param name="a">Vector a</param>
  347. /// <param name="b">Vector b</param>
  348. /// <returns>Vector</returns>
  349. [DebuggerStepThrough]
  350. public static v128 max_epi8(v128 a, v128 b)
  351. {
  352. v128 dst = default(v128);
  353. sbyte* dptr = &dst.SByte0;
  354. sbyte* aptr = &a.SByte0;
  355. sbyte* bptr = &b.SByte0;
  356. for (int j = 0; j <= 15; j++)
  357. {
  358. dptr[j] = Math.Max(aptr[j], bptr[j]);
  359. }
  360. return dst;
  361. }
  362. // _mm_max_epi32
  363. /// <summary> Compare packed 32-bit integers in "a" and "b", and store packed maximum values in "dst". </summary>
  364. /// <param name="a">Vector a</param>
  365. /// <param name="b">Vector b</param>
  366. /// <returns>Vector</returns>
  367. [DebuggerStepThrough]
  368. public static v128 max_epi32(v128 a, v128 b)
  369. {
  370. v128 dst = default(v128);
  371. int* dptr = &dst.SInt0;
  372. int* aptr = &a.SInt0;
  373. int* bptr = &b.SInt0;
  374. for (int j = 0; j <= 3; j++)
  375. {
  376. dptr[j] = Math.Max(aptr[j], bptr[j]);
  377. }
  378. return dst;
  379. }
  380. // _mm_max_epu32
  381. /// <summary> Compare packed unsigned 32-bit integers in "a" and "b", and store packed maximum values in "dst". </summary>
  382. /// <param name="a">Vector a</param>
  383. /// <param name="b">Vector b</param>
  384. /// <returns>Vector</returns>
  385. [DebuggerStepThrough]
  386. public static v128 max_epu32(v128 a, v128 b)
  387. {
  388. v128 dst = default(v128);
  389. uint* dptr = &dst.UInt0;
  390. uint* aptr = &a.UInt0;
  391. uint* bptr = &b.UInt0;
  392. for (int j = 0; j <= 3; j++)
  393. {
  394. dptr[j] = Math.Max(aptr[j], bptr[j]);
  395. }
  396. return dst;
  397. }
  398. // _mm_max_epu16
  399. /// <summary> Compare packed unsigned 16-bit integers in "a" and "b", and store packed maximum values in "dst". </summary>
  400. /// <param name="a">Vector a</param>
  401. /// <param name="b">Vector b</param>
  402. /// <returns>Vector</returns>
  403. [DebuggerStepThrough]
  404. public static v128 max_epu16(v128 a, v128 b)
  405. {
  406. v128 dst = default(v128);
  407. ushort* dptr = &dst.UShort0;
  408. ushort* aptr = &a.UShort0;
  409. ushort* bptr = &b.UShort0;
  410. for (int j = 0; j <= 7; j++)
  411. {
  412. dptr[j] = Math.Max(aptr[j], bptr[j]);
  413. }
  414. return dst;
  415. }
  416. // _mm_min_epi8
  417. /// <summary> Compare packed 8-bit integers in "a" and "b", and store packed minimum values in "dst". </summary>
  418. /// <param name="a">Vector a</param>
  419. /// <param name="b">Vector b</param>
  420. /// <returns>Vector</returns>
  421. [DebuggerStepThrough]
  422. public static v128 min_epi8(v128 a, v128 b)
  423. {
  424. v128 dst = default(v128);
  425. sbyte* dptr = &dst.SByte0;
  426. sbyte* aptr = &a.SByte0;
  427. sbyte* bptr = &b.SByte0;
  428. for (int j = 0; j <= 15; j++)
  429. {
  430. dptr[j] = Math.Min(aptr[j], bptr[j]);
  431. }
  432. return dst;
  433. }
  434. // _mm_min_epi32
  435. /// <summary> Compare packed 32-bit integers in "a" and "b", and store packed minimum values in "dst". </summary>
  436. /// <param name="a">Vector a</param>
  437. /// <param name="b">Vector b</param>
  438. /// <returns>Vector</returns>
  439. [DebuggerStepThrough]
  440. public static v128 min_epi32(v128 a, v128 b)
  441. {
  442. v128 dst = default(v128);
  443. int* dptr = &dst.SInt0;
  444. int* aptr = &a.SInt0;
  445. int* bptr = &b.SInt0;
  446. for (int j = 0; j <= 3; j++)
  447. {
  448. dptr[j] = Math.Min(aptr[j], bptr[j]);
  449. }
  450. return dst;
  451. }
  452. // _mm_min_epu32
  453. /// <summary> Compare packed unsigned 32-bit integers in "a" and "b", and store packed minimum values in "dst". </summary>
  454. /// <param name="a">Vector a</param>
  455. /// <param name="b">Vector b</param>
  456. /// <returns>Vector</returns>
  457. [DebuggerStepThrough]
  458. public static v128 min_epu32(v128 a, v128 b)
  459. {
  460. v128 dst = default(v128);
  461. uint* dptr = &dst.UInt0;
  462. uint* aptr = &a.UInt0;
  463. uint* bptr = &b.UInt0;
  464. for (int j = 0; j <= 3; j++)
  465. {
  466. dptr[j] = Math.Min(aptr[j], bptr[j]);
  467. }
  468. return dst;
  469. }
  470. // _mm_min_epu16
  471. /// <summary> Compare packed unsigned 16-bit integers in "a" and "b", and store packed minimum values in "dst". </summary>
  472. /// <param name="a">Vector a</param>
  473. /// <param name="b">Vector b</param>
  474. /// <returns>Vector</returns>
  475. [DebuggerStepThrough]
  476. public static v128 min_epu16(v128 a, v128 b)
  477. {
  478. v128 dst = default(v128);
  479. ushort* dptr = &dst.UShort0;
  480. ushort* aptr = &a.UShort0;
  481. ushort* bptr = &b.UShort0;
  482. for (int j = 0; j <= 7; j++)
  483. {
  484. dptr[j] = Math.Min(aptr[j], bptr[j]);
  485. }
  486. return dst;
  487. }
  488. // _mm_packus_epi32
  489. /// <summary> Convert packed 32-bit integers from "a" and "b" to packed 16-bit integers using unsigned saturation, and store the results in "dst". </summary>
  490. /// <param name="a">Vector a</param>
  491. /// <param name="b">Vector b</param>
  492. /// <returns>Vector</returns>
  493. [DebuggerStepThrough]
  494. public static v128 packus_epi32(v128 a, v128 b)
  495. {
  496. v128 dst = default(v128);
  497. dst.UShort0 = Saturate_To_UnsignedInt16(a.SInt0);
  498. dst.UShort1 = Saturate_To_UnsignedInt16(a.SInt1);
  499. dst.UShort2 = Saturate_To_UnsignedInt16(a.SInt2);
  500. dst.UShort3 = Saturate_To_UnsignedInt16(a.SInt3);
  501. dst.UShort4 = Saturate_To_UnsignedInt16(b.SInt0);
  502. dst.UShort5 = Saturate_To_UnsignedInt16(b.SInt1);
  503. dst.UShort6 = Saturate_To_UnsignedInt16(b.SInt2);
  504. dst.UShort7 = Saturate_To_UnsignedInt16(b.SInt3);
  505. return dst;
  506. }
  507. // _mm_cmpeq_epi64
  508. /// <summary> Compare packed 64-bit integers in "a" and "b" for equality, and store the results in "dst". </summary>
  509. /// <param name="a">Vector a</param>
  510. /// <param name="b">Vector b</param>
  511. /// <returns>Vector</returns>
  512. [DebuggerStepThrough]
  513. public static v128 cmpeq_epi64(v128 a, v128 b)
  514. {
  515. v128 dst = default(v128);
  516. dst.SLong0 = a.SLong0 == b.SLong0 ? -1L : 0L;
  517. dst.SLong1 = a.SLong1 == b.SLong1 ? -1L : 0L;
  518. return dst;
  519. }
  520. // _mm_cvtepi8_epi16
  521. /// <summary> Sign extend packed 8-bit integers in "a" to packed 16-bit integers, and store the results in "dst". </summary>
  522. /// <param name="a">Vector a</param>
  523. /// <returns>Vector</returns>
  524. [DebuggerStepThrough]
  525. public static v128 cvtepi8_epi16(v128 a)
  526. {
  527. v128 dst = default(v128);
  528. short* dptr = &dst.SShort0;
  529. sbyte* aptr = &a.SByte0;
  530. for (int j = 0; j <= 7; j++)
  531. {
  532. dptr[j] = aptr[j];
  533. }
  534. return dst;
  535. }
  536. // _mm_cvtepi8_epi32
  537. /// <summary> Sign extend packed 8-bit integers in "a" to packed 32-bit integers, and store the results in "dst". </summary>
  538. /// <param name="a">Vector a</param>
  539. /// <returns>Vector</returns>
  540. [DebuggerStepThrough]
  541. public static v128 cvtepi8_epi32(v128 a)
  542. {
  543. v128 dst = default(v128);
  544. int* dptr = &dst.SInt0;
  545. sbyte* aptr = &a.SByte0;
  546. for (int j = 0; j <= 3; j++)
  547. {
  548. dptr[j] = aptr[j];
  549. }
  550. return dst;
  551. }
  552. // _mm_cvtepi8_epi64
  553. /// <summary> Sign extend packed 8-bit integers in the low 8 bytes of "a" to packed 64-bit integers, and store the results in "dst". </summary>
  554. /// <param name="a">Vector a</param>
  555. /// <returns>Vector</returns>
  556. [DebuggerStepThrough]
  557. public static v128 cvtepi8_epi64(v128 a)
  558. {
  559. v128 dst = default(v128);
  560. long* dptr = &dst.SLong0;
  561. sbyte* aptr = &a.SByte0;
  562. for (int j = 0; j <= 1; j++)
  563. {
  564. dptr[j] = aptr[j];
  565. }
  566. return dst;
  567. }
  568. // _mm_cvtepi16_epi32
  569. /// <summary> Sign extend packed 16-bit integers in "a" to packed 32-bit integers, and store the results in "dst". </summary>
  570. /// <param name="a">Vector a</param>
  571. /// <returns>Vector</returns>
  572. [DebuggerStepThrough]
  573. public static v128 cvtepi16_epi32(v128 a)
  574. {
  575. v128 dst = default(v128);
  576. int* dptr = &dst.SInt0;
  577. short* aptr = &a.SShort0;
  578. for (int j = 0; j <= 3; j++)
  579. {
  580. dptr[j] = aptr[j];
  581. }
  582. return dst;
  583. }
  584. // _mm_cvtepi16_epi64
  585. /// <summary> Sign extend packed 16-bit integers in "a" to packed 64-bit integers, and store the results in "dst". </summary>
  586. /// <param name="a">Vector a</param>
  587. /// <returns>Vector</returns>
  588. [DebuggerStepThrough]
  589. public static v128 cvtepi16_epi64(v128 a)
  590. {
  591. v128 dst = default(v128);
  592. long* dptr = &dst.SLong0;
  593. short* aptr = &a.SShort0;
  594. for (int j = 0; j <= 1; j++)
  595. {
  596. dptr[j] = aptr[j];
  597. }
  598. return dst;
  599. }
  600. // _mm_cvtepi32_epi64
  601. /// <summary> Sign extend packed 32-bit integers in "a" to packed 64-bit integers, and store the results in "dst". </summary>
  602. /// <param name="a">Vector a</param>
  603. /// <returns>Vector</returns>
  604. [DebuggerStepThrough]
  605. public static v128 cvtepi32_epi64(v128 a)
  606. {
  607. v128 dst = default(v128);
  608. long* dptr = &dst.SLong0;
  609. int* aptr = &a.SInt0;
  610. for (int j = 0; j <= 1; j++)
  611. {
  612. dptr[j] = aptr[j];
  613. }
  614. return dst;
  615. }
  616. // _mm_cvtepu8_epi16
  617. /// <summary> Zero extend packed unsigned 8-bit integers in "a" to packed 16-bit integers, and store the results in "dst". </summary>
  618. /// <param name="a">Vector a</param>
  619. /// <returns>Vector</returns>
  620. [DebuggerStepThrough]
  621. public static v128 cvtepu8_epi16(v128 a)
  622. {
  623. v128 dst = default(v128);
  624. short* dptr = &dst.SShort0;
  625. byte* aptr = &a.Byte0;
  626. for (int j = 0; j <= 7; j++)
  627. {
  628. dptr[j] = aptr[j];
  629. }
  630. return dst;
  631. }
  632. // _mm_cvtepu8_epi32
  633. /// <summary> Zero extend packed unsigned 8-bit integers in "a" to packed 32-bit integers, and store the results in "dst". </summary>
  634. /// <param name="a">Vector a</param>
  635. /// <returns>Vector</returns>
  636. [DebuggerStepThrough]
  637. public static v128 cvtepu8_epi32(v128 a)
  638. {
  639. v128 dst = default(v128);
  640. int* dptr = &dst.SInt0;
  641. byte* aptr = &a.Byte0;
  642. for (int j = 0; j <= 3; j++)
  643. {
  644. dptr[j] = aptr[j];
  645. }
  646. return dst;
  647. }
  648. // _mm_cvtepu8_epi64
  649. /// <summary> Zero extend packed unsigned 8-bit integers in the low 8 byte sof "a" to packed 64-bit integers, and store the results in "dst". </summary>
  650. /// <param name="a">Vector a</param>
  651. /// <returns>Vector</returns>
  652. [DebuggerStepThrough]
  653. public static v128 cvtepu8_epi64(v128 a)
  654. {
  655. v128 dst = default(v128);
  656. long* dptr = &dst.SLong0;
  657. byte* aptr = &a.Byte0;
  658. for (int j = 0; j <= 1; j++)
  659. {
  660. dptr[j] = aptr[j];
  661. }
  662. return dst;
  663. }
  664. // _mm_cvtepu16_epi32
  665. /// <summary> Zero extend packed unsigned 16-bit integers in "a" to packed 32-bit integers, and store the results in "dst". </summary>
  666. /// <param name="a">Vector a</param>
  667. /// <returns>Vector</returns>
  668. [DebuggerStepThrough]
  669. public static v128 cvtepu16_epi32(v128 a)
  670. {
  671. v128 dst = default(v128);
  672. int* dptr = &dst.SInt0;
  673. ushort* aptr = &a.UShort0;
  674. for (int j = 0; j <= 3; j++)
  675. {
  676. dptr[j] = aptr[j];
  677. }
  678. return dst;
  679. }
  680. // _mm_cvtepu16_epi64
  681. /// <summary> Zero extend packed unsigned 16-bit integers in "a" to packed 64-bit integers, and store the results in "dst". </summary>
  682. /// <param name="a">Vector a</param>
  683. /// <returns>Vector</returns>
  684. [DebuggerStepThrough]
  685. public static v128 cvtepu16_epi64(v128 a)
  686. {
  687. v128 dst = default(v128);
  688. long* dptr = &dst.SLong0;
  689. ushort* aptr = &a.UShort0;
  690. for (int j = 0; j <= 1; j++)
  691. {
  692. dptr[j] = aptr[j];
  693. }
  694. return dst;
  695. }
  696. // _mm_cvtepu32_epi64
  697. /// <summary> Zero extend packed unsigned 32-bit integers in "a" to packed 64-bit integers, and store the results in "dst". </summary>
  698. /// <param name="a">Vector a</param>
  699. /// <returns>Vector</returns>
  700. [DebuggerStepThrough]
  701. public static v128 cvtepu32_epi64(v128 a)
  702. {
  703. v128 dst = default(v128);
  704. long* dptr = &dst.SLong0;
  705. uint* aptr = &a.UInt0;
  706. for (int j = 0; j <= 1; j++)
  707. {
  708. dptr[j] = aptr[j];
  709. }
  710. return dst;
  711. }
  712. // _mm_mul_epi32
  713. /// <summary> Multiply the low 32-bit integers from each packed 64-bit element in "a" and "b", and store the signed 64-bit results in "dst". </summary>
  714. /// <param name="a">Vector a</param>
  715. /// <param name="b">Vector b</param>
  716. /// <returns>Vector</returns>
  717. [DebuggerStepThrough]
  718. public static v128 mul_epi32(v128 a, v128 b)
  719. {
  720. v128 dst = default(v128);
  721. dst.SLong0 = a.SInt0 * (long)b.SInt0;
  722. dst.SLong1 = a.SInt2 * (long)b.SInt2;
  723. return dst;
  724. }
  725. // _mm_mullo_epi32
  726. /// <summary> Multiply the packed 32-bit integers in "a" and "b", producing intermediate 64-bit integers, and store the low 32 bits of the intermediate integers in "dst". </summary>
  727. /// <param name="a">Vector a</param>
  728. /// <param name="b">Vector b</param>
  729. /// <returns>Vector</returns>
  730. [DebuggerStepThrough]
  731. public static v128 mullo_epi32(v128 a, v128 b)
  732. {
  733. v128 dst = default(v128);
  734. int* dptr = &dst.SInt0;
  735. int* aptr = &a.SInt0;
  736. int* bptr = &b.SInt0;
  737. for (int j = 0; j <= 3; j++)
  738. {
  739. dptr[j] = aptr[j] * bptr[j];
  740. }
  741. return dst;
  742. }
  743. // _mm_testz_si128
  744. /// <summary> Compute the bitwise AND of 128 bits (representing integer data) in "a" and "b", and set "ZF" to 1 if the result is zero, otherwise set "ZF" to 0. Compute the bitwise NOT of "a" and then AND with "b", and set "CF" to 1 if the result is zero, otherwise set "CF" to 0. Return the "ZF" value. </summary>
  745. /// <param name="a">Vector a</param>
  746. /// <param name="b">Vector b</param>
  747. /// <returns>ZF value</returns>
  748. [DebuggerStepThrough]
  749. public static int testz_si128(v128 a, v128 b)
  750. {
  751. return ((a.SLong0 & b.SLong0) == 0 && (a.SLong1 & b.SLong1) == 0) ? 1 : 0;
  752. }
  753. // _mm_testc_si128
  754. /// <summary> Compute the bitwise AND of 128 bits (representing integer data) in "a" and "b", and set "ZF" to 1 if the result is zero, otherwise set "ZF" to 0. Compute the bitwise NOT of "a" and then AND with "b", and set "CF" to 1 if the result is zero, otherwise set "CF" to 0. Return the "CF" value. </summary>
  755. /// <param name="a">Vector a</param>
  756. /// <param name="b">Vector b</param>
  757. /// <returns>CF value</returns>
  758. [DebuggerStepThrough]
  759. public static int testc_si128(v128 a, v128 b)
  760. {
  761. return (((~a.SLong0) & b.SLong0) == 0 && ((~a.SLong1) & b.SLong1) == 0) ? 1 : 0;
  762. }
  763. // _mm_testnzc_si128
  764. /// <summary>Compute the bitwise AND of 128 bits (representing integer data) in "a" and "b", and set "ZF" to 1 if the result is zero, otherwise set "ZF" to 0. Compute the bitwise NOT of "a" and then AND with "b", and set "CF" to 1 if the result is zero, otherwise set "CF" to 0. Return 1 if both the "ZF" and "CF" values are zero, otherwise return 0.</summary>
  765. /// <param name="a">Vector a</param>
  766. /// <param name="b">Vector b</param>
  767. /// <returns>Boolean result</returns>
  768. [DebuggerStepThrough]
  769. public static int testnzc_si128(v128 a, v128 b)
  770. {
  771. int zf = ((a.SLong0 & b.SLong0) == 0 && (a.SLong1 & b.SLong1) == 0) ? 1 : 0;
  772. int cf = (((~a.SLong0) & b.SLong0) == 0 && ((~a.SLong1) & b.SLong1) == 0) ? 1 : 0;
  773. return 1 - (zf | cf);
  774. }
  775. // _mm_test_all_zeros
  776. /// <summary> Compute the bitwise AND of 128 bits (representing integer data) in "a" and "mask", and return 1 if the result is zero, otherwise return 0. </summary>
  777. /// <param name="a">Vector a</param>
  778. /// <param name="mask">Mask</param>
  779. /// <returns>Boolean result</returns>
  780. [DebuggerStepThrough]
  781. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  782. public static int test_all_zeros(v128 a, v128 mask)
  783. {
  784. return testz_si128(a, mask);
  785. }
  786. // _mm_test_mix_ones_zeros
  787. /// <summary>Compute the bitwise AND of 128 bits (representing integer data) in "a" and "mask", and set "ZF" to 1 if the result is zero, otherwise set "ZF" to 0. Compute the bitwise NOT of "a" and then AND with "mask", and set "CF" to 1 if the result is zero, otherwise set "CF" to 0. Return 1 if both the "ZF" and "CF" values are zero, otherwise return 0.</summary>
  788. /// <param name="a">Vector a</param>
  789. /// <param name="mask">Mask</param>
  790. /// <returns>Boolean result</returns>
  791. [DebuggerStepThrough]
  792. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  793. public static int test_mix_ones_zeroes(v128 a, v128 mask)
  794. {
  795. return testnzc_si128(a, mask);
  796. }
  797. // _mm_test_all_ones
  798. /// <summary>Compute the bitwise NOT of "a" and then AND with a 128-bit vector containing all 1's, and return 1 if the result is zero, otherwise return 0.></summary>
  799. /// <param name="a">Vector a</param>
  800. /// <returns>Boolean result</returns>
  801. [DebuggerStepThrough]
  802. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  803. public static int test_all_ones(v128 a)
  804. {
  805. return testc_si128(a, Sse2.cmpeq_epi32(a, a));
  806. }
  807. // Wrapper for C# reference mode to handle FROUND_xxx
  808. private static double RoundDImpl(double d, int roundingMode)
  809. {
  810. switch (roundingMode & 7)
  811. {
  812. case 0: return Math.Round(d);
  813. case 1: return Math.Floor(d);
  814. case 2:
  815. {
  816. double r = Math.Ceiling(d);
  817. if (r == 0.0 && d < 0.0)
  818. {
  819. // Emulate intel's ceil rounding to zero leaving the data at negative zero
  820. return new v128(0x8000_0000_0000_0000).Double0;
  821. }
  822. else
  823. {
  824. return r;
  825. }
  826. }
  827. case 3: return Math.Truncate(d);
  828. default:
  829. switch (MXCSR & MXCSRBits.RoundingControlMask)
  830. {
  831. case MXCSRBits.RoundToNearest: return Math.Round(d);
  832. case MXCSRBits.RoundDown: return Math.Floor(d);
  833. case MXCSRBits.RoundUp: return Math.Ceiling(d);
  834. default: return Math.Truncate(d);
  835. }
  836. }
  837. }
  838. // _mm_round_pd
  839. /// <summary> Round the packed double-precision (64-bit) floating-point elements in "a" using the "rounding" parameter, and store the results as packed double-precision floating-point elements in "dst".</summary>
  840. /// <param name="a">Vector a</param>
  841. /// <param name="rounding">Rounding mode</param>
  842. /// <returns>Vector</returns>
  843. [DebuggerStepThrough]
  844. public static v128 round_pd(v128 a, int rounding)
  845. {
  846. v128 dst = default(v128);
  847. dst.Double0 = RoundDImpl(a.Double0, rounding);
  848. dst.Double1 = RoundDImpl(a.Double1, rounding);
  849. return dst;
  850. }
  851. // _mm_floor_pd
  852. /// <summary> Round the packed double-precision (64-bit) floating-point elements in "a" down to an integer value, and store the results as packed double-precision floating-point elements in "dst". </summary>
  853. /// <param name="a">Vector a</param>
  854. /// <returns>Vector</returns>
  855. [DebuggerStepThrough]
  856. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  857. public static v128 floor_pd(v128 a)
  858. {
  859. return round_pd(a, (int)RoundingMode.FROUND_FLOOR);
  860. }
  861. // _mm_ceil_pd
  862. /// <summary> Round the packed double-precision (64-bit) floating-point elements in "a" up to an integer value, and store the results as packed double-precision floating-point elements in "dst". </summary>
  863. /// <param name="a">Vector a</param>
  864. /// <returns>Vector</returns>
  865. [DebuggerStepThrough]
  866. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  867. public static v128 ceil_pd(v128 a)
  868. {
  869. return round_pd(a, (int)RoundingMode.FROUND_CEIL);
  870. }
  871. // _mm_round_ps
  872. /// <summary> Round the packed single-precision (32-bit) floating-point elements in "a" using the "rounding" parameter, and store the results as packed single-precision floating-point elements in "dst". </summary>
  873. /// <param name="a">Vector a</param>
  874. /// <param name="rounding">Rounding mode</param>
  875. /// <returns>Vector</returns>
  876. [DebuggerStepThrough]
  877. public static v128 round_ps(v128 a, int rounding)
  878. {
  879. v128 dst = default(v128);
  880. dst.Float0 = (float)RoundDImpl(a.Float0, rounding);
  881. dst.Float1 = (float)RoundDImpl(a.Float1, rounding);
  882. dst.Float2 = (float)RoundDImpl(a.Float2, rounding);
  883. dst.Float3 = (float)RoundDImpl(a.Float3, rounding);
  884. return dst;
  885. }
  886. // _mm_floor_ps
  887. /// <summary> Round the packed single-precision (32-bit) floating-point elements in "a" down to an integer value, and store the results as packed single-precision floating-point elements in "dst". </summary>
  888. /// <param name="a">Vector a</param>
  889. /// <returns>Vector</returns>
  890. [DebuggerStepThrough]
  891. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  892. public static v128 floor_ps(v128 a)
  893. {
  894. return round_ps(a, (int)RoundingMode.FROUND_FLOOR);
  895. }
  896. // _mm_ceil_ps
  897. /// <summary> Round the packed single-precision (32-bit) floating-point elements in "a" up to an integer value, and store the results as packed single-precision floating-point elements in "dst". </summary>
  898. /// <param name="a">Vector a</param>
  899. /// <returns>Vector</returns>
  900. [DebuggerStepThrough]
  901. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  902. public static v128 ceil_ps(v128 a)
  903. {
  904. return round_ps(a, (int)RoundingMode.FROUND_CEIL);
  905. }
  906. // _mm_round_sd
  907. /// <summary> Round the lower double-precision (64-bit) floating-point element in "b" using the "rounding" parameter, store the result as a double-precision floating-point element in the lower element of "dst", and copy the upper element from "a" to the upper element of "dst". </summary>
  908. /// <param name="a">Vector a</param>
  909. /// <param name="b">Vector b</param>
  910. /// <param name="rounding">Rounding mode</param>
  911. /// <returns>Vector</returns>
  912. [DebuggerStepThrough]
  913. public static v128 round_sd(v128 a, v128 b, int rounding)
  914. {
  915. v128 dst = default(v128);
  916. dst.Double0 = RoundDImpl(b.Double0, rounding);
  917. dst.Double1 = a.Double1;
  918. return dst;
  919. }
  920. // _mm_floor_sd
  921. /// <summary> Round the lower double-precision (64-bit) floating-point element in "b" down to an integer value, store the result as a double-precision floating-point element in the lower element of "dst", and copy the upper element from "a" to the upper element of "dst". </summary>
  922. /// <param name="a">Vector a</param>
  923. /// <param name="b">Vector b</param>
  924. /// <returns>Vector</returns>
  925. [DebuggerStepThrough]
  926. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  927. public static v128 floor_sd(v128 a, v128 b)
  928. {
  929. return round_sd(a, b, (int)RoundingMode.FROUND_FLOOR);
  930. }
  931. // _mm_ceil_sd
  932. /// <summary> Round the lower double-precision (64-bit) floating-point element in "b" up to an integer value, store the result as a double-precision floating-point element in the lower element of "dst", and copy the upper element from "a" to the upper element of "dst". </summary>
  933. /// <param name="a">Vector a</param>
  934. /// <param name="b">Vector b</param>
  935. /// <returns>Vector</returns>
  936. [DebuggerStepThrough]
  937. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  938. public static v128 ceil_sd(v128 a, v128 b)
  939. {
  940. return round_sd(a, b, (int)RoundingMode.FROUND_CEIL);
  941. }
  942. // _mm_round_ss
  943. /// <summary> Round the lower single-precision (32-bit) floating-point element in "b" using the "rounding" parameter, store the result as a single-precision floating-point element in the lower element of "dst", and copy the upper 3 packed elements from "a" to the upper elements of "dst".</summary>
  944. /// <param name="a">Vector a</param>
  945. /// <param name="b">Vector b</param>
  946. /// <param name="rounding">Rounding mode</param>
  947. /// <returns>Vector</returns>
  948. [DebuggerStepThrough]
  949. public static v128 round_ss(v128 a, v128 b, int rounding)
  950. {
  951. v128 dst = a;
  952. dst.Float0 = (float)RoundDImpl(b.Float0, rounding);
  953. return dst;
  954. }
  955. // _mm_floor_ss
  956. /// <summary> Round the lower single-precision (32-bit) floating-point element in "b" down to an integer value, store the result as a single-precision floating-point element in the lower element of "dst", and copy the upper 3 packed elements from "a" to the upper elements of "dst". </summary>
  957. /// <param name="a">Vector a</param>
  958. /// <param name="b">Vector b</param>
  959. /// <returns>Vector</returns>
  960. [DebuggerStepThrough]
  961. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  962. public static v128 floor_ss(v128 a, v128 b)
  963. {
  964. return round_ss(a, b, (int)RoundingMode.FROUND_FLOOR);
  965. }
  966. // _mm_ceil_ss
  967. /// <summary> Round the lower single-precision (32-bit) floating-point element in "b" up to an integer value, store the result as a single-precision floating-point element in the lower element of "dst", and copy the upper 3 packed elements from "a" to the upper elements of "dst". </summary>
  968. /// <param name="a">Vector a</param>
  969. /// <param name="b">Vector b</param>
  970. /// <returns>Vector</returns>
  971. [DebuggerStepThrough]
  972. [BurstTargetCpu(BurstTargetCpu.X64_SSE4)]
  973. public static v128 ceil_ss(v128 a, v128 b)
  974. {
  975. return round_ss(a, b, (int)RoundingMode.FROUND_CEIL);
  976. }
  977. // _mm_minpos_epu16
  978. /// <summary> Horizontally compute the minimum amongst the packed unsigned 16-bit integers in "a", store the minimum and index in "dst", and zero the remaining bits in "dst". </summary>
  979. /// <param name="a">Vector a</param>
  980. /// <returns>Vector</returns>
  981. [DebuggerStepThrough]
  982. public static v128 minpos_epu16(v128 a)
  983. {
  984. int index = 0;
  985. ushort min = a.UShort0;
  986. ushort* aptr = &a.UShort0;
  987. for (int j = 1; j <= 7; j++)
  988. {
  989. if (aptr[j] < min)
  990. {
  991. index = j;
  992. min = aptr[j];
  993. }
  994. }
  995. v128 dst = default(v128);
  996. dst.UShort0 = min;
  997. dst.UShort1 = (ushort)index;
  998. return dst;
  999. }
  1000. // _mm_mpsadbw_epu8
  1001. /// <summary> Compute the sum of absolute differences (SADs) of quadruplets of unsigned 8-bit integers in "a" compared to those in "b", and store the 16-bit results in "dst".</summary>
  1002. /// <remarks>Eight SADs are performed using one quadruplet from "b" and eight quadruplets from "a". One quadruplet is selected from "b" starting at on the offset specified in "imm8". Eight quadruplets are formed from sequential 8-bit integers selected from "a" starting at the offset specified in "imm8".</remarks>
  1003. /// <param name="a">Vector a</param>
  1004. /// <param name="b">Vector b</param>
  1005. /// <param name="imm8">Offset</param>
  1006. /// <returns>Vector</returns>
  1007. [DebuggerStepThrough]
  1008. public static v128 mpsadbw_epu8(v128 a, v128 b, int imm8)
  1009. {
  1010. v128 dst = default(v128);
  1011. ushort* dptr = &dst.UShort0;
  1012. byte* aptr = &a.Byte0 + ((imm8 >> 2) & 1) * 4;
  1013. byte* bptr = &b.Byte0 + (imm8 & 3) * 4;
  1014. byte b0 = bptr[0];
  1015. byte b1 = bptr[1];
  1016. byte b2 = bptr[2];
  1017. byte b3 = bptr[3];
  1018. for (int j = 0; j <= 7; j++)
  1019. {
  1020. dptr[j] = (ushort)(Math.Abs(aptr[j + 0] - b0) + Math.Abs(aptr[j + 1] - b1) + Math.Abs(aptr[j + 2] - b2) + Math.Abs(aptr[j + 3] - b3));
  1021. }
  1022. return dst;
  1023. }
  1024. /// <summary>Helper macro to create index-parameter value for insert_ps</summary>
  1025. /// <param name="srcField">Source field</param>
  1026. /// <param name="dstField">Destination field</param>
  1027. /// <param name="zeroMask">Zero mask</param>
  1028. /// <returns>Integer</returns>
  1029. [DebuggerStepThrough]
  1030. public static int MK_INSERTPS_NDX(int srcField, int dstField, int zeroMask)
  1031. {
  1032. return (srcField << 6) | (dstField << 4) | zeroMask;
  1033. }
  1034. }
  1035. }
  1036. }