CpuTestSimdMov32.cs 22 KB

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