CpuTestSimdReg32.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. #define SimdReg32
  2. using ARMeilleure.State;
  3. using NUnit.Framework;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace Ryujinx.Tests.Cpu
  7. {
  8. [Category("SimdReg32")]
  9. public sealed class CpuTestSimdReg32 : CpuTest32
  10. {
  11. #if SimdReg32
  12. #region "ValueSource (Opcodes)"
  13. private static uint[] _V_Add_Sub_Wide_I_()
  14. {
  15. return new uint[]
  16. {
  17. 0xf2800100u, // VADDW.S8 Q0, Q0, D0
  18. 0xf2800300u // VSUBW.S8 Q0, Q0, D0
  19. };
  20. }
  21. private static uint[] _Vp_Add_Max_Min_F_()
  22. {
  23. return new uint[]
  24. {
  25. 0xf3000d00u, // VPADD.F32 D0, D0, D0
  26. 0xf3000f00u, // VPMAX.F32 D0, D0, D0
  27. 0xf3200f00u // VPMIN.F32 D0, D0, D0
  28. };
  29. }
  30. // VPADD does not have an unsigned flag, so we check the opcode before setting it.
  31. private static uint VpaddI8 = 0xf2000b10u; // VPADD.I8 D0, D0, D0
  32. private static uint[] _Vp_Add_Max_Min_I_()
  33. {
  34. return new uint[]
  35. {
  36. VpaddI8,
  37. 0xf2000a00u, // VPMAX.S8 D0, D0, D0
  38. 0xf2000a10u // VPMIN.S8 D0, D0, D0
  39. };
  40. }
  41. #endregion
  42. #region "ValueSource (Types)"
  43. private static ulong[] _8B4H2S1D_()
  44. {
  45. return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
  46. 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
  47. 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
  48. 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
  49. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
  50. }
  51. private static IEnumerable<ulong> _1S_F_()
  52. {
  53. yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
  54. yield return 0x0000000080800000ul; // -Min Normal
  55. yield return 0x00000000807FFFFFul; // -Max Subnormal
  56. yield return 0x0000000080000001ul; // -Min Subnormal (-float.Epsilon)
  57. yield return 0x000000007F7FFFFFul; // +Max Normal (float.MaxValue)
  58. yield return 0x0000000000800000ul; // +Min Normal
  59. yield return 0x00000000007FFFFFul; // +Max Subnormal
  60. yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
  61. if (!NoZeros)
  62. {
  63. yield return 0x0000000080000000ul; // -Zero
  64. yield return 0x0000000000000000ul; // +Zero
  65. }
  66. if (!NoInfs)
  67. {
  68. yield return 0x00000000FF800000ul; // -Infinity
  69. yield return 0x000000007F800000ul; // +Infinity
  70. }
  71. if (!NoNaNs)
  72. {
  73. yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
  74. yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
  75. yield return 0x000000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN)
  76. yield return 0x000000007FBFFFFFul; // +SNaN (all ones payload)
  77. }
  78. for (int cnt = 1; cnt <= RndCnt; cnt++)
  79. {
  80. ulong grbg = TestContext.CurrentContext.Random.NextUInt();
  81. ulong rnd1 = GenNormalS();
  82. ulong rnd2 = GenSubnormalS();
  83. yield return (grbg << 32) | rnd1;
  84. yield return (grbg << 32) | rnd2;
  85. }
  86. }
  87. private static IEnumerable<ulong> _2S_F_()
  88. {
  89. yield return 0xFF7FFFFFFF7FFFFFul; // -Max Normal (float.MinValue)
  90. yield return 0x8080000080800000ul; // -Min Normal
  91. yield return 0x807FFFFF807FFFFFul; // -Max Subnormal
  92. yield return 0x8000000180000001ul; // -Min Subnormal (-float.Epsilon)
  93. yield return 0x7F7FFFFF7F7FFFFFul; // +Max Normal (float.MaxValue)
  94. yield return 0x0080000000800000ul; // +Min Normal
  95. yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
  96. yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
  97. if (!NoZeros)
  98. {
  99. yield return 0x8000000080000000ul; // -Zero
  100. yield return 0x0000000000000000ul; // +Zero
  101. }
  102. if (!NoInfs)
  103. {
  104. yield return 0xFF800000FF800000ul; // -Infinity
  105. yield return 0x7F8000007F800000ul; // +Infinity
  106. }
  107. if (!NoNaNs)
  108. {
  109. yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
  110. yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
  111. yield return 0x7FC000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN)
  112. yield return 0x7FBFFFFF7FBFFFFFul; // +SNaN (all ones payload)
  113. }
  114. for (int cnt = 1; cnt <= RndCnt; cnt++)
  115. {
  116. ulong rnd1 = GenNormalS();
  117. ulong rnd2 = GenSubnormalS();
  118. yield return (rnd1 << 32) | rnd1;
  119. yield return (rnd2 << 32) | rnd2;
  120. }
  121. }
  122. private static IEnumerable<ulong> _1D_F_()
  123. {
  124. yield return 0xFFEFFFFFFFFFFFFFul; // -Max Normal (double.MinValue)
  125. yield return 0x8010000000000000ul; // -Min Normal
  126. yield return 0x800FFFFFFFFFFFFFul; // -Max Subnormal
  127. yield return 0x8000000000000001ul; // -Min Subnormal (-double.Epsilon)
  128. yield return 0x7FEFFFFFFFFFFFFFul; // +Max Normal (double.MaxValue)
  129. yield return 0x0010000000000000ul; // +Min Normal
  130. yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
  131. yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
  132. if (!NoZeros)
  133. {
  134. yield return 0x8000000000000000ul; // -Zero
  135. yield return 0x0000000000000000ul; // +Zero
  136. }
  137. if (!NoInfs)
  138. {
  139. yield return 0xFFF0000000000000ul; // -Infinity
  140. yield return 0x7FF0000000000000ul; // +Infinity
  141. }
  142. if (!NoNaNs)
  143. {
  144. yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
  145. yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
  146. yield return 0x7FF8000000000000ul; // +QNaN (all zeros payload) (-double.NaN) (DefaultNaN)
  147. yield return 0x7FF7FFFFFFFFFFFFul; // +SNaN (all ones payload)
  148. }
  149. for (int cnt = 1; cnt <= RndCnt; cnt++)
  150. {
  151. ulong rnd1 = GenNormalD();
  152. ulong rnd2 = GenSubnormalD();
  153. yield return rnd1;
  154. yield return rnd2;
  155. }
  156. }
  157. #endregion
  158. private const int RndCnt = 2;
  159. private static readonly bool NoZeros = false;
  160. private static readonly bool NoInfs = true;
  161. private static readonly bool NoNaNs = true;
  162. [Explicit]
  163. [Test, Pairwise, Description("VADD.f32 V0, V0, V0")]
  164. public void Vadd_f32([Values(0u)] uint rd,
  165. [Values(0u, 1u)] uint rn,
  166. [Values(0u, 2u)] uint rm,
  167. [ValueSource("_2S_F_")] ulong z0,
  168. [ValueSource("_2S_F_")] ulong z1,
  169. [ValueSource("_2S_F_")] ulong a0,
  170. [ValueSource("_2S_F_")] ulong a1,
  171. [ValueSource("_2S_F_")] ulong b0,
  172. [ValueSource("_2S_F_")] ulong b1,
  173. [Values] bool q)
  174. {
  175. uint opcode = 0xf2000d00u; // VADD.F32 D0, D0, D0
  176. if (q)
  177. {
  178. opcode |= 1 << 6;
  179. rm <<= 1;
  180. rn <<= 1;
  181. rd <<= 1;
  182. }
  183. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  184. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  185. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  186. V128 v0 = MakeVectorE0E1(z0, z1);
  187. V128 v1 = MakeVectorE0E1(a0, a1);
  188. V128 v2 = MakeVectorE0E1(b0, b1);
  189. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  190. CompareAgainstUnicorn();
  191. }
  192. [Test, Pairwise]
  193. public void V_Add_Sub_Wide_I([ValueSource("_V_Add_Sub_Wide_I_")] uint opcode,
  194. [Range(0u, 5u)] uint rd,
  195. [Range(0u, 5u)] uint rn,
  196. [Range(0u, 5u)] uint rm,
  197. [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z,
  198. [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a,
  199. [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b,
  200. [Values(0u, 1u, 2u)] uint size, // <SU8, SU16, SU32>
  201. [Values] bool u) // <S, U>
  202. {
  203. if (u)
  204. {
  205. opcode |= 1 << 24;
  206. }
  207. rd >>= 1; rd <<= 1;
  208. rn >>= 1; rn <<= 1;
  209. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  210. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  211. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  212. opcode |= (size & 0x3) << 20;
  213. V128 v0 = MakeVectorE0E1(z, ~z);
  214. V128 v1 = MakeVectorE0E1(a, ~a);
  215. V128 v2 = MakeVectorE0E1(b, ~b);
  216. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  217. CompareAgainstUnicorn();
  218. }
  219. [Test, Pairwise, Description("VCMP.f<size> Vd, Vm")]
  220. public void Vcmp([Values(2u, 3u)] uint size,
  221. [ValueSource("_1S_F_")] ulong a,
  222. [ValueSource("_1S_F_")] ulong b,
  223. [Values] bool e)
  224. {
  225. uint opcode = 0xeeb40840u;
  226. uint rm = 1;
  227. uint rd = 2;
  228. if (size == 3)
  229. {
  230. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  231. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  232. }
  233. else
  234. {
  235. opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
  236. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  237. }
  238. opcode |= ((size & 3) << 8);
  239. if (e)
  240. {
  241. opcode |= 1 << 7;
  242. }
  243. V128 v1 = MakeVectorE0(a);
  244. V128 v2 = MakeVectorE0(b);
  245. int fpscr = (int)(TestContext.CurrentContext.Random.NextUInt(0xf) << 28);
  246. SingleOpcode(opcode, v1: v1, v2: v2, fpscr: fpscr);
  247. CompareAgainstUnicorn(fpsrMask: Fpsr.Nzcv);
  248. }
  249. [Test, Pairwise, Description("VFMA.F<size> <Vd>, <Vn>, <Vm>")]
  250. public void Vfma([Values(0u, 1u)] uint rd,
  251. [Values(0u, 1u)] uint rn,
  252. [Values(0u, 1u)] uint rm,
  253. [Values(0u, 1u)] uint Q,
  254. [ValueSource("_2S_F_")] ulong z,
  255. [ValueSource("_2S_F_")] ulong a,
  256. [ValueSource("_2S_F_")] ulong b )
  257. {
  258. uint opcode = 0xf2000c10;
  259. V128 v0;
  260. V128 v1;
  261. V128 v2;
  262. uint c = (uint) BitConverter.SingleToInt32Bits(z);
  263. uint d = (uint) BitConverter.SingleToInt32Bits(a);
  264. uint e = (uint) BitConverter.SingleToInt32Bits(b);
  265. if (Q == 0)
  266. {
  267. opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1);
  268. opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11);
  269. opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) >> 15);
  270. v0 = MakeVectorE0E1(c, c);
  271. v1 = MakeVectorE0E1(d, c);
  272. v2 = MakeVectorE0E1(e, c);
  273. }
  274. else
  275. {
  276. rd = rn = rm = 0; // Needed, as these values cannot be odd values if Q == 1.
  277. opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0);
  278. opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
  279. opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
  280. v0 = MakeVectorE0E1E2E3(c, c, d, e);
  281. v1 = MakeVectorE0E1E2E3(d, c, e, c);
  282. v2 = MakeVectorE0E1E2E3(e, c, d, c);
  283. }
  284. opcode |= ((Q & 1) << 6);
  285. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  286. CompareAgainstUnicorn();
  287. }
  288. [Test, Pairwise, Description("VFNMA.F<size> <Vd>, <Vn>, <Vm>")]
  289. public void Vfnma([Values(0u, 1u)] uint rd,
  290. [Values(0u, 1u)] uint rn,
  291. [Values(0u, 1u)] uint rm,
  292. [Values(2u, 3u)] uint size,
  293. [ValueSource("_2S_F_")] ulong z,
  294. [ValueSource("_2S_F_")] ulong a,
  295. [ValueSource("_2S_F_")] ulong b)
  296. {
  297. uint opcode = 0xe900840;
  298. if (size == 2)
  299. {
  300. opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1);
  301. opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11);
  302. opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) >> 15);
  303. }
  304. else
  305. {
  306. opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0);
  307. opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
  308. opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
  309. }
  310. opcode |= ((size & 3) << 8);
  311. V128 v0 = MakeVectorE0E1(z, z);
  312. V128 v1 = MakeVectorE0E1(a, z);
  313. V128 v2 = MakeVectorE0E1(b, z);
  314. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  315. CompareAgainstUnicorn();
  316. }
  317. [Test, Pairwise, Description("VFNMS.F<size> <Vd>, <Vn>, <Vm>")]
  318. public void Vfnms([Values(0u, 1u)] uint rd,
  319. [Values(0u, 1u)] uint rn,
  320. [Values(0u, 1u)] uint rm,
  321. [Values(2u, 3u)] uint size,
  322. [ValueSource("_2S_F_")] ulong z,
  323. [ValueSource("_2S_F_")] ulong a,
  324. [ValueSource("_2S_F_")] ulong b)
  325. {
  326. uint opcode = 0xee900a00;
  327. if (size == 2)
  328. {
  329. opcode |= (((rm & 0x1) << 5) | (rm & 0x1e) >> 1);
  330. opcode |= (((rd & 0x1) << 22) | (rd & 0x1e) << 11);
  331. opcode |= (((rn & 0x1) << 7) | (rn & 0x1e) >> 15);
  332. }
  333. else
  334. {
  335. opcode |= (((rm & 0x10) << 1) | (rm & 0xf) << 0);
  336. opcode |= (((rd & 0x10) << 18) | (rd & 0xf) << 12);
  337. opcode |= (((rn & 0x10) << 3) | (rn & 0xf) << 16);
  338. }
  339. opcode |= ((size & 3) << 8);
  340. V128 v0 = MakeVectorE0E1(z, z);
  341. V128 v1 = MakeVectorE0E1(a, z);
  342. V128 v2 = MakeVectorE0E1(b, z);
  343. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  344. CompareAgainstUnicorn();
  345. }
  346. [Test, Pairwise, Description("VMLSL.<type><size> <Vd>, <Vn>, <Vm>")]
  347. public void Vmlsl_I([Values(0u)] uint rd,
  348. [Values(1u, 0u)] uint rn,
  349. [Values(2u, 0u)] uint rm,
  350. [Values(0u, 1u, 2u)] uint size,
  351. [Random(RndCnt)] ulong z,
  352. [Random(RndCnt)] ulong a,
  353. [Random(RndCnt)] ulong b,
  354. [Values] bool u)
  355. {
  356. uint opcode = 0xf2800a00u; // VMLSL.S8 Q0, D0, D0
  357. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  358. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  359. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  360. opcode |= size << 20;
  361. if (u)
  362. {
  363. opcode |= 1 << 24;
  364. }
  365. V128 v0 = MakeVectorE0E1(z, z);
  366. V128 v1 = MakeVectorE0E1(a, z);
  367. V128 v2 = MakeVectorE0E1(b, z);
  368. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  369. CompareAgainstUnicorn();
  370. }
  371. [Test, Pairwise, Description("VMULL.<size> <Vd>, <Vn>, <Vm>")]
  372. public void Vmull_I([Values(0u)] uint rd,
  373. [Values(1u, 0u)] uint rn,
  374. [Values(2u, 0u)] uint rm,
  375. [Values(0u, 1u, 2u)] uint size,
  376. [Random(RndCnt)] ulong z,
  377. [Random(RndCnt)] ulong a,
  378. [Random(RndCnt)] ulong b,
  379. [Values] bool op,
  380. [Values] bool u)
  381. {
  382. uint opcode = 0xf2800c00u; // VMULL.S8 Q0, D0, D0
  383. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  384. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  385. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  386. if (op)
  387. {
  388. opcode |= 1 << 9;
  389. size = 0;
  390. u = false;
  391. }
  392. opcode |= size << 20;
  393. if (u)
  394. {
  395. opcode |= 1 << 24;
  396. }
  397. V128 v0 = MakeVectorE0E1(z, z);
  398. V128 v1 = MakeVectorE0E1(a, z);
  399. V128 v2 = MakeVectorE0E1(b, z);
  400. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  401. CompareAgainstUnicorn();
  402. }
  403. [Test, Pairwise, Description("VSHL.<size> {<Vd>}, <Vm>, <Vn>")]
  404. public void Vshl([Values(0u)] uint rd,
  405. [Values(1u, 0u)] uint rn,
  406. [Values(2u, 0u)] uint rm,
  407. [Values(0u, 1u, 2u, 3u)] uint size,
  408. [Random(RndCnt)] ulong z,
  409. [Random(RndCnt)] ulong a,
  410. [Random(RndCnt)] ulong b,
  411. [Values] bool q,
  412. [Values] bool u)
  413. {
  414. uint opcode = 0xf2000400u; // VSHL.S8 D0, D0, D0
  415. if (q)
  416. {
  417. opcode |= 1 << 6;
  418. rm <<= 1;
  419. rn <<= 1;
  420. rd <<= 1;
  421. }
  422. if (u)
  423. {
  424. opcode |= 1 << 24;
  425. }
  426. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  427. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  428. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  429. opcode |= size << 20;
  430. V128 v0 = MakeVectorE0E1(z, z);
  431. V128 v1 = MakeVectorE0E1(a, z);
  432. V128 v2 = MakeVectorE0E1(b, z);
  433. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  434. CompareAgainstUnicorn();
  435. }
  436. [Explicit]
  437. [Test, Pairwise]
  438. public void Vp_Add_Max_Min_F([ValueSource("_Vp_Add_Max_Min_F_")] uint opcode,
  439. [Values(0u)] uint rd,
  440. [Range(0u, 7u)] uint rn,
  441. [Range(0u, 7u)] uint rm,
  442. [ValueSource("_2S_F_")] ulong z0,
  443. [ValueSource("_2S_F_")] ulong z1,
  444. [ValueSource("_2S_F_")] ulong a0,
  445. [ValueSource("_2S_F_")] ulong a1,
  446. [ValueSource("_2S_F_")] ulong b0,
  447. [ValueSource("_2S_F_")] ulong b1)
  448. {
  449. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  450. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  451. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  452. var rnd = TestContext.CurrentContext.Random;
  453. V128 v0 = MakeVectorE0E1(z0, z1);
  454. V128 v1 = MakeVectorE0E1(a0, a1);
  455. V128 v2 = MakeVectorE0E1(b0, b1);
  456. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  457. CompareAgainstUnicorn();
  458. }
  459. [Test, Pairwise]
  460. public void Vp_Add_Max_Min_I([ValueSource("_Vp_Add_Max_Min_I_")] uint opcode,
  461. [Values(0u)] uint rd,
  462. [Range(0u, 5u)] uint rn,
  463. [Range(0u, 5u)] uint rm,
  464. [Values(0u, 1u, 2u)] uint size,
  465. [Random(RndCnt)] ulong z,
  466. [Random(RndCnt)] ulong a,
  467. [Random(RndCnt)] ulong b,
  468. [Values] bool u)
  469. {
  470. if (u && opcode != VpaddI8)
  471. {
  472. opcode |= 1 << 24;
  473. }
  474. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  475. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  476. opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
  477. opcode |= size << 20;
  478. V128 v0 = MakeVectorE0E1(z, z);
  479. V128 v1 = MakeVectorE0E1(a, z);
  480. V128 v2 = MakeVectorE0E1(b, z);
  481. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  482. CompareAgainstUnicorn();
  483. }
  484. #endif
  485. }
  486. }