CpuTestSimdMov32.cs 20 KB

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