CpuTestSimdShImm32.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #define SimdShImm32
  2. using ARMeilleure.State;
  3. using NUnit.Framework;
  4. namespace Ryujinx.Tests.Cpu
  5. {
  6. [Category("SimdShImm32")]
  7. public sealed class CpuTestSimdShImm32 : CpuTest32
  8. {
  9. #if SimdShImm32
  10. #region "ValueSource (Types)"
  11. private static ulong[] _1D_()
  12. {
  13. return new[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  14. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
  15. }
  16. private static ulong[] _2S_()
  17. {
  18. return new[] { 0x0000000000000000ul, 0x7FFFFFFF7FFFFFFFul, 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
  19. }
  20. private static ulong[] _4H_()
  21. {
  22. return new[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul, 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
  23. }
  24. private static ulong[] _8B_()
  25. {
  26. return new[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful, 0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
  27. }
  28. #endregion
  29. #region "ValueSource (Opcodes)"
  30. private static uint[] _Vshr_Imm_SU8_()
  31. {
  32. return new[]
  33. {
  34. 0xf2880010u, // VSHR.S8 D0, D0, #8
  35. 0xf2880110u, // VSRA.S8 D0, D0, #8
  36. 0xf2880210u, // VRSHR.S8 D0, D0, #8
  37. 0xf2880310u // VRSRA.S8 D0, D0, #8
  38. };
  39. }
  40. private static uint[] _Vshr_Imm_SU16_()
  41. {
  42. return new[]
  43. {
  44. 0xf2900010u, // VSHR.S16 D0, D0, #16
  45. 0xf2900110u, // VSRA.S16 D0, D0, #16
  46. 0xf2900210u, // VRSHR.S16 D0, D0, #16
  47. 0xf2900310u // VRSRA.S16 D0, D0, #16
  48. };
  49. }
  50. private static uint[] _Vshr_Imm_SU32_()
  51. {
  52. return new[]
  53. {
  54. 0xf2a00010u, // VSHR.S32 D0, D0, #32
  55. 0xf2a00110u, // VSRA.S32 D0, D0, #32
  56. 0xf2a00210u, // VRSHR.S32 D0, D0, #32
  57. 0xf2a00310u // VRSRA.S32 D0, D0, #32
  58. };
  59. }
  60. private static uint[] _Vshr_Imm_SU64_()
  61. {
  62. return new[]
  63. {
  64. 0xf2800190u, // VSRA.S64 D0, D0, #64
  65. 0xf2800290u, // VRSHR.S64 D0, D0, #64
  66. 0xf2800090u // VSHR.S64 D0, D0, #64
  67. };
  68. }
  69. private static uint[] _Vqshrn_Vqrshrn_Vrshrn_Imm_()
  70. {
  71. return new[]
  72. {
  73. 0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN)
  74. 0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN)
  75. 0xf2800850u // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN)
  76. };
  77. }
  78. private static uint[] _Vqshrun_Vqrshrun_Imm_()
  79. {
  80. return new[]
  81. {
  82. 0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN)
  83. 0xf3800850u // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN)
  84. };
  85. }
  86. #endregion
  87. private const int RndCnt = 2;
  88. private const int RndCntShiftImm = 2;
  89. [Test, Pairwise]
  90. public void Vshr_Imm_SU8([ValueSource(nameof(_Vshr_Imm_SU8_))] uint opcode,
  91. [Range(0u, 3u)] uint rd,
  92. [Range(0u, 3u)] uint rm,
  93. [ValueSource(nameof(_8B_))] ulong z,
  94. [ValueSource(nameof(_8B_))] ulong b,
  95. [Values(1u, 8u)] uint shiftImm,
  96. [Values] bool u,
  97. [Values] bool q)
  98. {
  99. uint imm6 = 16 - shiftImm;
  100. Vshr_Imm_SU(opcode, rd, rm, z, b, imm6, u, q);
  101. }
  102. [Test, Pairwise]
  103. public void Vshr_Imm_SU16([ValueSource(nameof(_Vshr_Imm_SU16_))] uint opcode,
  104. [Range(0u, 3u)] uint rd,
  105. [Range(0u, 3u)] uint rm,
  106. [ValueSource(nameof(_4H_))] ulong z,
  107. [ValueSource(nameof(_4H_))] ulong b,
  108. [Values(1u, 16u)] uint shiftImm,
  109. [Values] bool u,
  110. [Values] bool q)
  111. {
  112. uint imm6 = 32 - shiftImm;
  113. Vshr_Imm_SU(opcode, rd, rm, z, b, imm6, u, q);
  114. }
  115. [Test, Pairwise]
  116. public void Vshr_Imm_SU32([ValueSource(nameof(_Vshr_Imm_SU32_))] uint opcode,
  117. [Range(0u, 3u)] uint rd,
  118. [Range(0u, 3u)] uint rm,
  119. [ValueSource(nameof(_2S_))] ulong z,
  120. [ValueSource(nameof(_2S_))] ulong b,
  121. [Values(1u, 32u)] uint shiftImm,
  122. [Values] bool u,
  123. [Values] bool q)
  124. {
  125. uint imm6 = 64 - shiftImm;
  126. Vshr_Imm_SU(opcode, rd, rm, z, b, imm6, u, q);
  127. }
  128. [Test, Pairwise]
  129. public void Vshr_Imm_SU64([ValueSource(nameof(_Vshr_Imm_SU64_))] uint opcode,
  130. [Range(0u, 3u)] uint rd,
  131. [Range(0u, 3u)] uint rm,
  132. [ValueSource(nameof(_1D_))] ulong z,
  133. [ValueSource(nameof(_1D_))] ulong b,
  134. [Values(1u, 64u)] uint shiftImm,
  135. [Values] bool u,
  136. [Values] bool q)
  137. {
  138. uint imm6 = 64 - shiftImm;
  139. Vshr_Imm_SU(opcode, rd, rm, z, b, imm6, u, q);
  140. }
  141. private void Vshr_Imm_SU(uint opcode, uint rd, uint rm, ulong z, ulong b, uint imm6, bool u, bool q)
  142. {
  143. if (u)
  144. {
  145. opcode |= 1 << 24;
  146. }
  147. if (q)
  148. {
  149. opcode |= 1 << 6;
  150. rd >>= 1; rd <<= 1;
  151. rm >>= 1; rm <<= 1;
  152. }
  153. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  154. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  155. opcode |= (imm6 & 0x3f) << 16;
  156. V128 v0 = MakeVectorE0E1(z, ~z);
  157. V128 v1 = MakeVectorE0E1(b, ~b);
  158. SingleOpcode(opcode, v0: v0, v1: v1);
  159. CompareAgainstUnicorn();
  160. }
  161. [Test, Pairwise, Description("VSHL.<size> {<Vd>}, <Vm>, #<imm>")]
  162. public void Vshl_Imm([Values(0u)] uint rd,
  163. [Values(2u, 0u)] uint rm,
  164. [Values(0u, 1u, 2u, 3u)] uint size,
  165. [Random(RndCntShiftImm)] uint shiftImm,
  166. [Random(RndCnt)] ulong z,
  167. [Random(RndCnt)] ulong a,
  168. [Random(RndCnt)] ulong b,
  169. [Values] bool q)
  170. {
  171. uint opcode = 0xf2800510u; // VORR.I32 D0, #0 (immediate value changes it into SHL)
  172. if (q)
  173. {
  174. opcode |= 1 << 6;
  175. rm <<= 1;
  176. rd <<= 1;
  177. }
  178. uint imm = 1u << ((int)size + 3);
  179. imm |= shiftImm & (imm - 1);
  180. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  181. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  182. opcode |= ((imm & 0x3f) << 16) | ((imm & 0x40) << 1);
  183. V128 v0 = MakeVectorE0E1(z, z);
  184. V128 v1 = MakeVectorE0E1(a, z);
  185. V128 v2 = MakeVectorE0E1(b, z);
  186. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  187. CompareAgainstUnicorn();
  188. }
  189. [Test, Pairwise, Description("VSHRN.<size> <Vd>, <Vm>, #<imm>")]
  190. public void Vshrn_Imm([Values(0u, 1u)] uint rd,
  191. [Values(2u, 0u)] uint rm,
  192. [Values(0u, 1u, 2u)] uint size,
  193. [Random(RndCntShiftImm)] uint shiftImm,
  194. [Random(RndCnt)] ulong z,
  195. [Random(RndCnt)] ulong a,
  196. [Random(RndCnt)] ulong b)
  197. {
  198. uint opcode = 0xf2800810u; // VMOV.I16 D0, #0 (immediate value changes it into SHRN)
  199. uint imm = 1u << ((int)size + 3);
  200. imm |= shiftImm & (imm - 1);
  201. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  202. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  203. opcode |= ((imm & 0x3f) << 16);
  204. V128 v0 = MakeVectorE0E1(z, z);
  205. V128 v1 = MakeVectorE0E1(a, z);
  206. V128 v2 = MakeVectorE0E1(b, z);
  207. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
  208. CompareAgainstUnicorn();
  209. }
  210. [Test, Pairwise]
  211. public void Vqshrn_Vqrshrn_Vrshrn_Imm([ValueSource(nameof(_Vqshrn_Vqrshrn_Vrshrn_Imm_))] uint opcode,
  212. [Values(0u, 1u)] uint rd,
  213. [Values(2u, 0u)] uint rm,
  214. [Values(0u, 1u, 2u)] uint size,
  215. [Random(RndCntShiftImm)] uint shiftImm,
  216. [Random(RndCnt)] ulong z,
  217. [Random(RndCnt)] ulong a,
  218. [Random(RndCnt)] ulong b,
  219. [Values] bool u)
  220. {
  221. uint imm = 1u << ((int)size + 3);
  222. imm |= shiftImm & (imm - 1);
  223. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  224. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  225. opcode |= ((imm & 0x3f) << 16);
  226. if (u)
  227. {
  228. opcode |= 1u << 24;
  229. }
  230. V128 v0 = MakeVectorE0E1(z, z);
  231. V128 v1 = MakeVectorE0E1(a, z);
  232. V128 v2 = MakeVectorE0E1(b, z);
  233. int fpscr = (int)TestContext.CurrentContext.Random.NextUInt() & (int)Fpsr.Qc;
  234. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr);
  235. CompareAgainstUnicorn(fpsrMask: Fpsr.Qc);
  236. }
  237. [Test, Pairwise]
  238. public void Vqshrun_Vqrshrun_Imm([ValueSource(nameof(_Vqshrun_Vqrshrun_Imm_))] uint opcode,
  239. [Values(0u, 1u)] uint rd,
  240. [Values(2u, 0u)] uint rm,
  241. [Values(0u, 1u, 2u)] uint size,
  242. [Random(RndCntShiftImm)] uint shiftImm,
  243. [Random(RndCnt)] ulong z,
  244. [Random(RndCnt)] ulong a,
  245. [Random(RndCnt)] ulong b)
  246. {
  247. uint imm = 1u << ((int)size + 3);
  248. imm |= shiftImm & (imm - 1);
  249. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  250. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  251. opcode |= ((imm & 0x3f) << 16);
  252. V128 v0 = MakeVectorE0E1(z, z);
  253. V128 v1 = MakeVectorE0E1(a, z);
  254. V128 v2 = MakeVectorE0E1(b, z);
  255. int fpscr = (int)TestContext.CurrentContext.Random.NextUInt() & (int)Fpsr.Qc;
  256. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr);
  257. CompareAgainstUnicorn(fpsrMask: Fpsr.Qc);
  258. }
  259. #endif
  260. }
  261. }