CpuTestSimdMov32.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. #define SimdMov32
  2. using ARMeilleure.State;
  3. using NUnit.Framework;
  4. namespace Ryujinx.Tests.Cpu
  5. {
  6. [Category("SimdMov32")]
  7. public sealed class CpuTestSimdMov32 : CpuTest32
  8. {
  9. #if SimdMov32
  10. private const int RndCntImm = 2;
  11. [Test, Pairwise, Description("VMOV.I<size> <Dd/Qd>, #<imm>")]
  12. public void Movi_V([Range(0u, 10u)] uint variant,
  13. [Values(0u, 1u, 2u, 3u)] uint vd,
  14. [Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm,
  15. [Values] bool q)
  16. {
  17. uint[] variants =
  18. {
  19. // I32
  20. 0b0000_0,
  21. 0b0010_0,
  22. 0b0100_0,
  23. 0b0110_0,
  24. // I16
  25. 0b1000_0,
  26. 0b1010_0,
  27. // DT
  28. 0b1100_0,
  29. 0b1101_0,
  30. 0b1110_0,
  31. 0b1111_0,
  32. 0b1110_1
  33. };
  34. uint opcode = 0xf2800010u; // VMOV.I32 D0, #0
  35. uint cmodeOp = variants[variant];
  36. if (q)
  37. {
  38. vd <<= 1;
  39. }
  40. opcode |= ((cmodeOp & 1) << 5) | ((cmodeOp & 0x1e) << 7);
  41. opcode |= (q ? 1u : 0u) << 6;
  42. opcode |= (imm & 0xf) | ((imm & 0x70) << 12) | ((imm & 0x80) << 16);
  43. opcode |= (vd & 0x10) << 18;
  44. opcode |= (vd & 0xf) << 12;
  45. SingleOpcode(opcode);
  46. CompareAgainstUnicorn();
  47. }
  48. [Test, Pairwise, Description("VMOV.F<size> <Sd>, #<imm>")]
  49. public void Movi_S([Range(2u, 3u)] uint size,
  50. [Values(0u, 1u, 2u, 3u)] uint vd,
  51. [Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm)
  52. {
  53. uint opcode = 0xeeb00800u;
  54. opcode |= (size & 3) << 8;
  55. opcode |= (imm & 0xf) | ((imm & 0xf0) << 12);
  56. if (size == 2)
  57. {
  58. opcode |= ((vd & 0x1) << 22);
  59. opcode |= ((vd & 0x1e) << 11);
  60. }
  61. else
  62. {
  63. opcode |= ((vd & 0x10) << 18);
  64. opcode |= ((vd & 0xf) << 12);
  65. }
  66. SingleOpcode(opcode);
  67. CompareAgainstUnicorn();
  68. }
  69. [Test, Pairwise, Description("VMOV <Rd>, <Sd>")]
  70. public void Mov_GP([Values(0u, 1u, 2u, 3u)] uint vn,
  71. [Values(0u, 1u, 2u, 3u)] uint rt,
  72. [Random(RndCntImm)] uint valueRn,
  73. [Random(RndCntImm)] ulong valueVn1,
  74. [Random(RndCntImm)] ulong valueVn2,
  75. [Values] bool op)
  76. {
  77. uint opcode = 0xee000a10u; // VMOV S0, R0
  78. opcode |= (vn & 1) << 7;
  79. opcode |= (vn & 0x1e) << 15;
  80. opcode |= (rt & 0xf) << 12;
  81. if (op) opcode |= 1 << 20;
  82. SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2));
  83. CompareAgainstUnicorn();
  84. }
  85. [Test, Pairwise, Description("VMOV.<size> <Rt>, <Dn[x]>")]
  86. public void Mov_GP_Elem([Range(0u, 7u)] uint vn,
  87. [Values(0u, 1u, 2u, 3u)] uint rt,
  88. [Range(0u, 2u)] uint size,
  89. [Range(0u, 7u)] uint index,
  90. [Random(1)] uint valueRn,
  91. [Random(1)] ulong valueVn1,
  92. [Random(1)] ulong valueVn2,
  93. [Values] bool op,
  94. [Values] bool u)
  95. {
  96. uint opcode = 0xee000b10u; // VMOV.32 D0[0], R0
  97. uint opEncode = 0b01000;
  98. switch (size)
  99. {
  100. case 0:
  101. opEncode = (0b1000) | index & 7;
  102. break;
  103. case 1:
  104. opEncode = (0b0001) | ((index & 3) << 1);
  105. break;
  106. case 2:
  107. opEncode = (index & 1) << 2;
  108. break;
  109. }
  110. opcode |= ((opEncode >> 2) << 21) | ((opEncode & 3) << 5);
  111. opcode |= (vn & 0x10) << 3;
  112. opcode |= (vn & 0xf) << 16;
  113. opcode |= (rt & 0xf) << 12;
  114. if (op)
  115. {
  116. opcode |= 1 << 20;
  117. if (u && size != 2)
  118. {
  119. opcode |= 1 << 23;
  120. }
  121. }
  122. SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: new V128(valueVn2, valueVn1));
  123. CompareAgainstUnicorn();
  124. }
  125. [Test, Pairwise, Description("(VMOV <Rt>, <Rt2>, <Dm>), (VMOV <Dm>, <Rt>, <Rt2>)")]
  126. public void Mov_GP_D([Values(0u, 1u, 2u, 3u)] uint vm,
  127. [Values(0u, 1u, 2u, 3u)] uint rt,
  128. [Values(0u, 1u, 2u, 3u)] uint rt2,
  129. [Random(RndCntImm)] uint valueRt1,
  130. [Random(RndCntImm)] uint valueRt2,
  131. [Random(RndCntImm)] ulong valueVn1,
  132. [Random(RndCntImm)] ulong valueVn2,
  133. [Values] bool op)
  134. {
  135. uint opcode = 0xec400b10u; // VMOV D0, R0, R0
  136. opcode |= (vm & 0x10) << 1;
  137. opcode |= (vm & 0xf);
  138. opcode |= (rt & 0xf) << 12;
  139. opcode |= (rt2 & 0xf) << 16;
  140. if (op)
  141. {
  142. opcode |= 1 << 20;
  143. }
  144. SingleOpcode(opcode, r0: valueRt1, r1: valueRt2, r2: valueRt1, r3: valueRt2, v0: new V128(valueVn1, valueVn2));
  145. CompareAgainstUnicorn();
  146. }
  147. [Test, Pairwise, Description("(VMOV <Rt>, <Rt2>, <Sm>, <Sm1>), (VMOV <Sm>, <Sm1>, <Rt>, <Rt2>)")]
  148. public void Mov_GP_2([Range(0u, 7u)] uint vm,
  149. [Values(0u, 1u, 2u, 3u)] uint rt,
  150. [Values(0u, 1u, 2u, 3u)] uint rt2,
  151. [Random(RndCntImm)] uint valueRt1,
  152. [Random(RndCntImm)] uint valueRt2,
  153. [Random(RndCntImm)] ulong valueVn1,
  154. [Random(RndCntImm)] ulong valueVn2,
  155. [Values] bool op)
  156. {
  157. uint opcode = 0xec400a10u; // VMOV S0, S1, R0, R0
  158. opcode |= (vm & 1) << 5;
  159. opcode |= (vm & 0x1e) >> 1;
  160. opcode |= (rt & 0xf) << 12;
  161. opcode |= (rt2 & 0xf) << 16;
  162. if (op)
  163. {
  164. opcode |= 1 << 20;
  165. }
  166. SingleOpcode(opcode, r0: valueRt1, r1: valueRt2, r2: valueRt1, r3: valueRt2, v0: new V128(valueVn1, valueVn2), v1: new V128(valueVn2, valueVn1));
  167. CompareAgainstUnicorn();
  168. }
  169. [Test, Pairwise, Description("VMOVN.<size> <Dt>, <Qm>")]
  170. public void Movn_V([Range(0u, 1u, 2u)] uint size,
  171. [Values(0u, 1u, 2u, 3u)] uint vd,
  172. [Values(0u, 2u, 4u, 8u)] uint vm)
  173. {
  174. uint opcode = 0xf3b20200u; // VMOVN.I16 D0, Q0
  175. opcode |= (size & 0x3) << 18;
  176. opcode |= ((vm & 0x10) << 1);
  177. opcode |= ((vm & 0xf) << 0);
  178. opcode |= ((vd & 0x10) << 18);
  179. opcode |= ((vd & 0xf) << 12);
  180. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  181. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  182. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  183. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  184. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  185. CompareAgainstUnicorn();
  186. }
  187. [Test, Pairwise, Description("VMOVL.<size> <Qd>, <Dm>")]
  188. public void Vmovl([Values(0u, 1u, 2u, 3u)] uint vm,
  189. [Values(0u, 2u, 4u, 6u)] uint vd,
  190. [Values(1u, 2u, 4u)] uint imm3H,
  191. [Values] bool u)
  192. {
  193. // This is not VMOVL because imm3H = 0, but once
  194. // we shift in the imm3H value it turns into VMOVL.
  195. uint opcode = 0xf2800a10u; // VMOV.I16 D0, #0
  196. opcode |= (vm & 0x10) << 1;
  197. opcode |= (vm & 0xf);
  198. opcode |= (vd & 0x10) << 18;
  199. opcode |= (vd & 0xf) << 12;
  200. opcode |= (imm3H & 0x7) << 19;
  201. if (u)
  202. {
  203. opcode |= 1 << 24;
  204. }
  205. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  206. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  207. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  208. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  209. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  210. CompareAgainstUnicorn();
  211. }
  212. [Test, Pairwise, Description("VMVN.<size> <Vt>, <Vm>")]
  213. public void Vmvn([Range(0u, 1u, 2u)] uint size,
  214. [Values(0u, 1u, 2u, 3u)] uint vd,
  215. [Values(0u, 2u, 4u, 8u)] uint vm,
  216. [Values] bool q)
  217. {
  218. uint opcode = 0xf3b00580u; // VMVN D0, D0
  219. if (q)
  220. {
  221. opcode |= 1 << 6;
  222. vm <<= 1;
  223. vd <<= 1;
  224. }
  225. opcode |= (size & 0x3) << 18;
  226. opcode |= (vm & 0x10) << 1;
  227. opcode |= (vm & 0xf) << 0;
  228. opcode |= (vd & 0x10) << 18;
  229. opcode |= (vd & 0xf) << 12;
  230. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  231. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  232. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  233. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  234. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  235. CompareAgainstUnicorn();
  236. }
  237. [Test, Pairwise, Description("VMVN.I<size> <Dd/Qd>, #<imm>")]
  238. public void Mvni_V([Range(0u, 7u)] uint variant,
  239. [Values(0u, 1u, 2u, 3u)] uint vd,
  240. [Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm,
  241. [Values] bool q)
  242. {
  243. uint[] variants =
  244. {
  245. // I32
  246. 0b0000,
  247. 0b0010,
  248. 0b0100,
  249. 0b0110,
  250. // I16
  251. 0b1000,
  252. 0b1010,
  253. // I32
  254. 0b1100,
  255. 0b1101,
  256. };
  257. uint opcode = 0xf2800030u; // VMVN.I32 D0, #0
  258. uint cmodeOp = variants[variant];
  259. if (q)
  260. {
  261. vd <<= 1;
  262. }
  263. opcode |= (cmodeOp & 0xf) << 8;
  264. opcode |= (q ? 1u : 0u) << 6;
  265. opcode |= (imm & 0xf) | ((imm & 0x70) << 12) | ((imm & 0x80) << 16);
  266. opcode |= (vd & 0x10) << 18;
  267. opcode |= (vd & 0xf) << 12;
  268. SingleOpcode(opcode);
  269. CompareAgainstUnicorn();
  270. }
  271. [Test, Pairwise, Description("VTRN.<size> <Vd>, <Vm>")]
  272. public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm,
  273. [Values(0u, 1u, 2u, 3u)] uint vd,
  274. [Values(0u, 1u, 2u)] uint size,
  275. [Values] bool q)
  276. {
  277. uint opcode = 0xf3b20080u; // VTRN.8 D0, D0
  278. if (vm == vd)
  279. {
  280. return; // Undefined.
  281. }
  282. if (q)
  283. {
  284. opcode |= 1 << 6;
  285. vd <<= 1; vm <<= 1;
  286. }
  287. opcode |= (vm & 0x10) << 1;
  288. opcode |= (vm & 0xf);
  289. opcode |= (vd & 0x10) << 18;
  290. opcode |= (vd & 0xf) << 12;
  291. opcode |= (size & 0x3) << 18;
  292. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  293. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  294. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  295. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  296. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  297. CompareAgainstUnicorn();
  298. }
  299. [Test, Pairwise, Description("VZIP.<size> <Vd>, <Vm>")]
  300. public void Vzip([Values(0u, 1u, 2u, 3u)] uint vm,
  301. [Values(0u, 1u, 2u, 3u)] uint vd,
  302. [Values(0u, 1u, 2u)] uint size,
  303. [Values] bool q)
  304. {
  305. uint opcode = 0xf3b20180u; // VZIP.8 D0, D0
  306. if (vm == vd || (size == 2 && !q))
  307. {
  308. return; // Undefined.
  309. }
  310. if (q)
  311. {
  312. opcode |= 1 << 6;
  313. vd <<= 1; vm <<= 1;
  314. }
  315. opcode |= (vm & 0x10) << 1;
  316. opcode |= (vm & 0xf);
  317. opcode |= (vd & 0x10) << 18;
  318. opcode |= (vd & 0xf) << 12;
  319. opcode |= (size & 0x3) << 18;
  320. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  321. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  322. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  323. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  324. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  325. CompareAgainstUnicorn();
  326. }
  327. [Test, Pairwise, Description("VUZP.<size> <Vd>, <Vm>")]
  328. public void Vuzp([Values(0u, 1u, 2u, 3u)] uint vm,
  329. [Values(0u, 1u, 2u, 3u)] uint vd,
  330. [Values(0u, 1u, 2u)] uint size,
  331. [Values] bool q)
  332. {
  333. uint opcode = 0xf3b20100u; // VUZP.8 d0, d0
  334. if (vm == vd || (size == 2 && !q))
  335. {
  336. return; // Undefined.
  337. }
  338. if (q)
  339. {
  340. opcode |= 1 << 6;
  341. vd <<= 1; vm <<= 1;
  342. }
  343. opcode |= (vm & 0x10) << 1;
  344. opcode |= (vm & 0xf);
  345. opcode |= (vd & 0x10) << 18;
  346. opcode |= (vd & 0xf) << 12;
  347. opcode |= (size & 0x3) << 18;
  348. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  349. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  350. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  351. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  352. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  353. CompareAgainstUnicorn();
  354. }
  355. [Test, Pairwise, Description("VTBL.8 <Dd>, {list}, <Dm>")]
  356. public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid.
  357. [Range(4u, 12u)] uint vn, // Selection.
  358. [Values(0u, 1u)] uint vd, // Destinations.
  359. [Range(0u, 3u)] uint length,
  360. [Values] bool x)
  361. {
  362. uint opcode = 0xf3b00800u; // VTBL.8 D0, {D0}, D0
  363. if (vn + length > 31)
  364. {
  365. return; // Undefined.
  366. }
  367. if (x)
  368. {
  369. opcode |= 1 << 6;
  370. }
  371. opcode |= (vm & 0x10) << 1;
  372. opcode |= (vm & 0xf);
  373. opcode |= (vd & 0x10) << 18;
  374. opcode |= (vd & 0xf) << 12;
  375. opcode |= (vn & 0x10) << 3;
  376. opcode |= (vn & 0xf) << 16;
  377. opcode |= (length & 0x3) << 8;
  378. var rnd = TestContext.CurrentContext.Random;
  379. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  380. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  381. V128 v4 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  382. V128 v5 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  383. byte maxIndex = (byte)(length * 8 - 1);
  384. byte[] b0 = new byte[16];
  385. byte[] b1 = new byte[16];
  386. for (int i=0; i<16; i++)
  387. {
  388. b0[i] = rnd.NextByte(maxIndex);
  389. b1[i] = rnd.NextByte(maxIndex);
  390. }
  391. V128 v0 = new V128(b0);
  392. V128 v1 = new V128(b1);
  393. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5);
  394. CompareAgainstUnicorn();
  395. }
  396. [Test, Pairwise, Description("VEXT.8 {<Vd>,} <Vn>, <Vm>, #<imm>")]
  397. public void Vext([Values(0u, 1u, 2u, 3u)] uint vm,
  398. [Values(0u, 1u, 2u, 3u)] uint vn,
  399. [Values(0u, 1u, 2u, 3u)] uint vd,
  400. [Values(0u, 15u)] uint imm4,
  401. [Values] bool q)
  402. {
  403. uint opcode = 0xf2b00000; // VEXT.32 D0, D0, D0, #0
  404. if (q)
  405. {
  406. opcode |= 1 << 6;
  407. vd <<= 1; vm <<= 1; vn <<= 1;
  408. }
  409. else if (imm4 > 7)
  410. {
  411. return; // Undefined.
  412. }
  413. opcode |= (vm & 0x10) << 1;
  414. opcode |= (vm & 0xf);
  415. opcode |= (vd & 0x10) << 18;
  416. opcode |= (vd & 0xf) << 12;
  417. opcode |= (vn & 0x10) << 3;
  418. opcode |= (vn & 0xf) << 16;
  419. opcode |= (imm4 & 0xf) << 8;
  420. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  421. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  422. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  423. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  424. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  425. CompareAgainstUnicorn();
  426. }
  427. [Test, Pairwise, Description("VDUP.<size> <Vd>, <Rt>")]
  428. public void Vdup_GP([Values(0u, 1u, 2u, 3u)] uint vd,
  429. [Values(0u, 1u, 2u, 3u)] uint rt,
  430. [Values(0u, 1u, 2u)] uint size,
  431. [Random(RndCntImm)] uint valueRn,
  432. [Random(RndCntImm)] ulong valueVn1,
  433. [Random(RndCntImm)] ulong valueVn2,
  434. [Values] bool q)
  435. {
  436. uint opcode = 0xee800b10; // VDUP.32 d0, r0
  437. if (q)
  438. {
  439. opcode |= 1 << 21;
  440. vd <<= 1;
  441. }
  442. opcode |= (vd & 0x10) << 3;
  443. opcode |= (vd & 0xf) << 16;
  444. opcode |= (rt & 0xf) << 12;
  445. opcode |= (size & 1) << 5; // E
  446. opcode |= (size & 2) << 21; // B
  447. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  448. SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: v1);
  449. CompareAgainstUnicorn();
  450. }
  451. [Test, Pairwise, Description("VDUP.<size> <Vd>, <Dm[x]>")]
  452. public void Vdup_S([Values(0u, 1u, 2u, 3u)] uint vd,
  453. [Values(0u, 1u, 2u, 3u)] uint vm,
  454. [Values(0u, 1u, 2u)] uint size,
  455. [Range(0u, 7u)] uint index,
  456. [Random(RndCntImm)] ulong valueVn1,
  457. [Random(RndCntImm)] ulong valueVn2,
  458. [Values] bool q)
  459. {
  460. uint opcode = 0xf3b00c00;
  461. if (q)
  462. {
  463. opcode |= 1 << 6;
  464. vd <<= 1;
  465. }
  466. opcode |= (vd & 0x10) << 18;
  467. opcode |= (vd & 0xf) << 12;
  468. opcode |= (vm & 0x10) << 1;
  469. opcode |= (vm & 0xf);
  470. uint imm4 = 0;
  471. switch (size)
  472. {
  473. case 0:
  474. imm4 |= 0b0100 | ((index & 1) << 3);
  475. break;
  476. case 1:
  477. imm4 |= 0b0010 | ((index & 3) << 2);
  478. break;
  479. case 2:
  480. imm4 |= 0b0001 | ((index & 7) << 1);
  481. break;
  482. }
  483. opcode |= imm4 << 16;
  484. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  485. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  486. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  487. SingleOpcode(opcode, v0: new V128(valueVn1, valueVn2), v1: v1, v2: v2, v3: v3);
  488. CompareAgainstUnicorn();
  489. }
  490. #endif
  491. }
  492. }