CpuTestSimdShImm32.cs 11 KB

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