CpuTestSimdMov32.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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("VTRN.<size> <Vd>, <Vm>")]
  189. public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm,
  190. [Values(0u, 1u, 2u, 3u)] uint vd,
  191. [Values(0u, 1u, 2u)] uint size,
  192. [Values] bool q)
  193. {
  194. uint opcode = 0xf3b20080u; // VTRN.8 D0, D0
  195. if (vm == vd)
  196. {
  197. return; // Undefined.
  198. }
  199. if (q)
  200. {
  201. opcode |= 1 << 6;
  202. vd <<= 1; vm <<= 1;
  203. }
  204. opcode |= (vm & 0x10) << 1;
  205. opcode |= (vm & 0xf);
  206. opcode |= (vd & 0x10) << 18;
  207. opcode |= (vd & 0xf) << 12;
  208. opcode |= (size & 0x3) << 18;
  209. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  210. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  211. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  212. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  213. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  214. CompareAgainstUnicorn();
  215. }
  216. [Test, Pairwise, Description("VZIP.<size> <Vd>, <Vm>")]
  217. public void Vzip([Values(0u, 1u, 2u, 3u)] uint vm,
  218. [Values(0u, 1u, 2u, 3u)] uint vd,
  219. [Values(0u, 1u, 2u)] uint size,
  220. [Values] bool q)
  221. {
  222. uint opcode = 0xf3b20180u; // VZIP.8 D0, D0
  223. if (vm == vd || (size == 2 && !q))
  224. {
  225. return; // Undefined.
  226. }
  227. if (q)
  228. {
  229. opcode |= 1 << 6;
  230. vd <<= 1; vm <<= 1;
  231. }
  232. opcode |= (vm & 0x10) << 1;
  233. opcode |= (vm & 0xf);
  234. opcode |= (vd & 0x10) << 18;
  235. opcode |= (vd & 0xf) << 12;
  236. opcode |= (size & 0x3) << 18;
  237. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  238. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  239. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  240. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  241. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  242. CompareAgainstUnicorn();
  243. }
  244. [Test, Pairwise, Description("VUZP.<size> <Vd>, <Vm>")]
  245. public void Vuzp([Values(0u, 1u, 2u, 3u)] uint vm,
  246. [Values(0u, 1u, 2u, 3u)] uint vd,
  247. [Values(0u, 1u, 2u)] uint size,
  248. [Values] bool q)
  249. {
  250. uint opcode = 0xf3b20100u; // VUZP.8 d0, d0
  251. if (vm == vd || (size == 2 && !q))
  252. {
  253. return; // Undefined.
  254. }
  255. if (q)
  256. {
  257. opcode |= 1 << 6;
  258. vd <<= 1; vm <<= 1;
  259. }
  260. opcode |= (vm & 0x10) << 1;
  261. opcode |= (vm & 0xf);
  262. opcode |= (vd & 0x10) << 18;
  263. opcode |= (vd & 0xf) << 12;
  264. opcode |= (size & 0x3) << 18;
  265. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  266. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  267. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  268. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  269. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  270. CompareAgainstUnicorn();
  271. }
  272. [Test, Pairwise, Description("VTBL.8 <Dd>, {list}, <Dm>")]
  273. public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid.
  274. [Range(4u, 12u)] uint vn, // Selection.
  275. [Values(0u, 1u)] uint vd, // Destinations.
  276. [Range(0u, 3u)] uint length,
  277. [Values] bool x)
  278. {
  279. uint opcode = 0xf3b00800u; // VTBL.8 D0, {D0}, D0
  280. if (vn + length > 31)
  281. {
  282. return; // Undefined.
  283. }
  284. if (x)
  285. {
  286. opcode |= 1 << 6;
  287. }
  288. opcode |= (vm & 0x10) << 1;
  289. opcode |= (vm & 0xf);
  290. opcode |= (vd & 0x10) << 18;
  291. opcode |= (vd & 0xf) << 12;
  292. opcode |= (vn & 0x10) << 3;
  293. opcode |= (vn & 0xf) << 16;
  294. opcode |= (length & 0x3) << 8;
  295. var rnd = TestContext.CurrentContext.Random;
  296. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  297. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  298. V128 v4 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  299. V128 v5 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  300. byte maxIndex = (byte)(length * 8 - 1);
  301. byte[] b0 = new byte[16];
  302. byte[] b1 = new byte[16];
  303. for (int i=0; i<16; i++)
  304. {
  305. b0[i] = rnd.NextByte(maxIndex);
  306. b1[i] = rnd.NextByte(maxIndex);
  307. }
  308. V128 v0 = new V128(b0);
  309. V128 v1 = new V128(b1);
  310. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5);
  311. CompareAgainstUnicorn();
  312. }
  313. [Test, Pairwise, Description("VEXT.8 {<Vd>,} <Vn>, <Vm>, #<imm>")]
  314. public void Vext([Values(0u, 1u, 2u, 3u)] uint vm,
  315. [Values(0u, 1u, 2u, 3u)] uint vn,
  316. [Values(0u, 1u, 2u, 3u)] uint vd,
  317. [Values(0u, 15u)] uint imm4,
  318. [Values] bool q)
  319. {
  320. uint opcode = 0xf2b00000; // VEXT.32 D0, D0, D0, #0
  321. if (q)
  322. {
  323. opcode |= 1 << 6;
  324. vd <<= 1; vm <<= 1; vn <<= 1;
  325. }
  326. else if (imm4 > 7)
  327. {
  328. return; // Undefined.
  329. }
  330. opcode |= (vm & 0x10) << 1;
  331. opcode |= (vm & 0xf);
  332. opcode |= (vd & 0x10) << 18;
  333. opcode |= (vd & 0xf) << 12;
  334. opcode |= (vn & 0x10) << 3;
  335. opcode |= (vn & 0xf) << 16;
  336. opcode |= (imm4 & 0xf) << 8;
  337. V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  338. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  339. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  340. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  341. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
  342. CompareAgainstUnicorn();
  343. }
  344. [Test, Pairwise, Description("VDUP.<size> <Vd>, <Rt>")]
  345. public void Vdup_GP([Values(0u, 1u, 2u, 3u)] uint vd,
  346. [Values(0u, 1u, 2u, 3u)] uint rt,
  347. [Values(0u, 1u, 2u)] uint size,
  348. [Random(RndCntImm)] uint valueRn,
  349. [Random(RndCntImm)] ulong valueVn1,
  350. [Random(RndCntImm)] ulong valueVn2,
  351. [Values] bool q)
  352. {
  353. uint opcode = 0xee800b10; // VDUP.32 d0, r0
  354. if (q)
  355. {
  356. opcode |= 1 << 21;
  357. vd <<= 1;
  358. }
  359. opcode |= (vd & 0x10) << 3;
  360. opcode |= (vd & 0xf) << 16;
  361. opcode |= (rt & 0xf) << 12;
  362. opcode |= (size & 1) << 5; // E
  363. opcode |= (size & 2) << 21; // B
  364. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  365. SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: v1);
  366. CompareAgainstUnicorn();
  367. }
  368. [Test, Pairwise, Description("VDUP.<size> <Vd>, <Dm[x]>")]
  369. public void Vdup_S([Values(0u, 1u, 2u, 3u)] uint vd,
  370. [Values(0u, 1u, 2u, 3u)] uint vm,
  371. [Values(0u, 1u, 2u)] uint size,
  372. [Range(0u, 7u)] uint index,
  373. [Random(RndCntImm)] ulong valueVn1,
  374. [Random(RndCntImm)] ulong valueVn2,
  375. [Values] bool q)
  376. {
  377. uint opcode = 0xf3b00c00;
  378. if (q)
  379. {
  380. opcode |= 1 << 6;
  381. vd <<= 1;
  382. }
  383. opcode |= (vd & 0x10) << 18;
  384. opcode |= (vd & 0xf) << 12;
  385. opcode |= (vm & 0x10) << 1;
  386. opcode |= (vm & 0xf);
  387. uint imm4 = 0;
  388. switch (size)
  389. {
  390. case 0:
  391. imm4 |= 0b0100 | ((index & 1) << 3);
  392. break;
  393. case 1:
  394. imm4 |= 0b0010 | ((index & 3) << 2);
  395. break;
  396. case 2:
  397. imm4 |= 0b0001 | ((index & 7) << 1);
  398. break;
  399. }
  400. opcode |= imm4 << 16;
  401. V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  402. V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  403. V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
  404. SingleOpcode(opcode, v0: new V128(valueVn1, valueVn2), v1: v1, v2: v2, v3: v3);
  405. CompareAgainstUnicorn();
  406. }
  407. #endif
  408. }
  409. }