CpuTestSimdIns.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #define SimdIns
  2. using NUnit.Framework;
  3. using System.Runtime.Intrinsics;
  4. namespace Ryujinx.Tests.Cpu
  5. {
  6. [Category("SimdIns")]
  7. public sealed class CpuTestSimdIns : CpuTest
  8. {
  9. #if SimdIns
  10. #region "ValueSource"
  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. private static ulong[] _8B4H_()
  32. {
  33. return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
  34. 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
  35. 0x8000800080008000ul, 0xFFFFFFFFFFFFFFFFul };
  36. }
  37. private static ulong[] _8B4H2S_()
  38. {
  39. return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
  40. 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
  41. 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
  42. 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
  43. }
  44. private static uint[] _W_()
  45. {
  46. return new uint[] { 0x00000000u, 0x0000007Fu,
  47. 0x00000080u, 0x000000FFu,
  48. 0x00007FFFu, 0x00008000u,
  49. 0x0000FFFFu, 0x7FFFFFFFu,
  50. 0x80000000u, 0xFFFFFFFFu };
  51. }
  52. private static ulong[] _X_()
  53. {
  54. return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  55. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
  56. }
  57. #endregion
  58. private const int RndCnt = 2;
  59. private const int RndCntIndex = 2;
  60. [Test, Pairwise, Description("DUP <Vd>.<T>, <R><n>")]
  61. public void Dup_Gp_W([Values(0u)] uint rd,
  62. [Values(1u, 31u)] uint rn,
  63. [ValueSource("_W_")] [Random(RndCnt)] uint wn,
  64. [Values(0, 1, 2)] int size, // Q0: <8B, 4H, 2S>
  65. [Values(0b0u, 0b1u)] uint q) // Q1: <16B, 8H, 4S>
  66. {
  67. uint imm5 = (1u << size) & 0x1Fu;
  68. uint opcode = 0x0E000C00; // RESERVED
  69. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  70. opcode |= (imm5 << 16);
  71. opcode |= ((q & 1) << 30);
  72. ulong z = TestContext.CurrentContext.Random.NextULong();
  73. Vector128<float> v0 = MakeVectorE0E1(z, z);
  74. SingleOpcode(opcode, x1: wn, v0: v0);
  75. CompareAgainstUnicorn();
  76. }
  77. [Test, Pairwise, Description("DUP <Vd>.<T>, <R><n>")]
  78. public void Dup_Gp_X([Values(0u)] uint rd,
  79. [Values(1u, 31u)] uint rn,
  80. [ValueSource("_X_")] [Random(RndCnt)] ulong xn)
  81. {
  82. uint opcode = 0x4E080C00; // DUP V0.2D, X0
  83. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  84. ulong z = TestContext.CurrentContext.Random.NextULong();
  85. Vector128<float> v0 = MakeVectorE0E1(z, z);
  86. SingleOpcode(opcode, x1: xn, v0: v0);
  87. CompareAgainstUnicorn();
  88. }
  89. [Test, Pairwise, Description("DUP B0, V1.B[<index>]")]
  90. public void Dup_S_B([ValueSource("_8B_")] [Random(RndCnt)] ulong a,
  91. [Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index)
  92. {
  93. const int size = 0;
  94. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  95. uint opcode = 0x5E000420; // RESERVED
  96. opcode |= (imm5 << 16);
  97. ulong z = TestContext.CurrentContext.Random.NextULong();
  98. Vector128<float> v0 = MakeVectorE0E1(z, z);
  99. Vector128<float> v1 = MakeVectorE0E1(a, a);
  100. SingleOpcode(opcode, v0: v0, v1: v1);
  101. CompareAgainstUnicorn();
  102. }
  103. [Test, Pairwise, Description("DUP H0, V1.H[<index>]")]
  104. public void Dup_S_H([ValueSource("_4H_")] [Random(RndCnt)] ulong a,
  105. [Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index)
  106. {
  107. const int size = 1;
  108. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  109. uint opcode = 0x5E000420; // RESERVED
  110. opcode |= (imm5 << 16);
  111. ulong z = TestContext.CurrentContext.Random.NextULong();
  112. Vector128<float> v0 = MakeVectorE0E1(z, z);
  113. Vector128<float> v1 = MakeVectorE0E1(a, a);
  114. SingleOpcode(opcode, v0: v0, v1: v1);
  115. CompareAgainstUnicorn();
  116. }
  117. [Test, Pairwise, Description("DUP S0, V1.S[<index>]")]
  118. public void Dup_S_S([ValueSource("_2S_")] [Random(RndCnt)] ulong a,
  119. [Range(0u, 3u)] uint index)
  120. {
  121. const int size = 2;
  122. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  123. uint opcode = 0x5E000420; // RESERVED
  124. opcode |= (imm5 << 16);
  125. ulong z = TestContext.CurrentContext.Random.NextULong();
  126. Vector128<float> v0 = MakeVectorE0E1(z, z);
  127. Vector128<float> v1 = MakeVectorE0E1(a, a);
  128. SingleOpcode(opcode, v0: v0, v1: v1);
  129. CompareAgainstUnicorn();
  130. }
  131. [Test, Pairwise, Description("DUP D0, V1.D[<index>]")]
  132. public void Dup_S_D([ValueSource("_1D_")] [Random(RndCnt)] ulong a,
  133. [Range(0u, 1u)] uint index)
  134. {
  135. const int size = 3;
  136. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  137. uint opcode = 0x5E000420; // RESERVED
  138. opcode |= (imm5 << 16);
  139. ulong z = TestContext.CurrentContext.Random.NextULong();
  140. Vector128<float> v0 = MakeVectorE0E1(z, z);
  141. Vector128<float> v1 = MakeVectorE0E1(a, a);
  142. SingleOpcode(opcode, v0: v0, v1: v1);
  143. CompareAgainstUnicorn();
  144. }
  145. [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.B[<index>]")]
  146. public void Dup_V_8B_16B([Values(0u)] uint rd,
  147. [Values(1u, 0u)] uint rn,
  148. [ValueSource("_8B_")] [Random(RndCnt)] ulong z,
  149. [ValueSource("_8B_")] [Random(RndCnt)] ulong a,
  150. [Values(0u, 15u)] [Random(1u, 14u, RndCntIndex)] uint index,
  151. [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
  152. {
  153. const int size = 0;
  154. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  155. uint opcode = 0x0E000400; // RESERVED
  156. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  157. opcode |= (imm5 << 16);
  158. opcode |= ((q & 1) << 30);
  159. Vector128<float> v0 = MakeVectorE0E1(z, z);
  160. Vector128<float> v1 = MakeVectorE0E1(a, a);
  161. SingleOpcode(opcode, v0: v0, v1: v1);
  162. CompareAgainstUnicorn();
  163. }
  164. [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.H[<index>]")]
  165. public void Dup_V_4H_8H([Values(0u)] uint rd,
  166. [Values(1u, 0u)] uint rn,
  167. [ValueSource("_4H_")] [Random(RndCnt)] ulong z,
  168. [ValueSource("_4H_")] [Random(RndCnt)] ulong a,
  169. [Values(0u, 7u)] [Random(1u, 6u, RndCntIndex)] uint index,
  170. [Values(0b0u, 0b1u)] uint q) // <4H, 8H>
  171. {
  172. const int size = 1;
  173. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  174. uint opcode = 0x0E000400; // RESERVED
  175. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  176. opcode |= (imm5 << 16);
  177. opcode |= ((q & 1) << 30);
  178. Vector128<float> v0 = MakeVectorE0E1(z, z);
  179. Vector128<float> v1 = MakeVectorE0E1(a, a);
  180. SingleOpcode(opcode, v0: v0, v1: v1);
  181. CompareAgainstUnicorn();
  182. }
  183. [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.S[<index>]")]
  184. public void Dup_V_2S_4S([Values(0u)] uint rd,
  185. [Values(1u, 0u)] uint rn,
  186. [ValueSource("_2S_")] [Random(RndCnt)] ulong z,
  187. [ValueSource("_2S_")] [Random(RndCnt)] ulong a,
  188. [Range(0u, 3u)] uint index,
  189. [Values(0b0u, 0b1u)] uint q) // <2S, 4S>
  190. {
  191. const int size = 2;
  192. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  193. uint opcode = 0x0E000400; // RESERVED
  194. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  195. opcode |= (imm5 << 16);
  196. opcode |= ((q & 1) << 30);
  197. Vector128<float> v0 = MakeVectorE0E1(z, z);
  198. Vector128<float> v1 = MakeVectorE0E1(a, a);
  199. SingleOpcode(opcode, v0: v0, v1: v1);
  200. CompareAgainstUnicorn();
  201. }
  202. [Test, Pairwise, Description("DUP <Vd>.<T>, <Vn>.D[<index>]")]
  203. public void Dup_V_2D([Values(0u)] uint rd,
  204. [Values(1u, 0u)] uint rn,
  205. [ValueSource("_1D_")] [Random(RndCnt)] ulong z,
  206. [ValueSource("_1D_")] [Random(RndCnt)] ulong a,
  207. [Range(0u, 1u)] uint index,
  208. [Values(0b1u)] uint q) // <2D>
  209. {
  210. const int size = 3;
  211. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  212. uint opcode = 0x0E000400; // RESERVED
  213. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  214. opcode |= (imm5 << 16);
  215. opcode |= ((q & 1) << 30);
  216. Vector128<float> v0 = MakeVectorE0E1(z, z);
  217. Vector128<float> v1 = MakeVectorE0E1(a, a);
  218. SingleOpcode(opcode, v0: v0, v1: v1);
  219. CompareAgainstUnicorn();
  220. }
  221. [Test, Pairwise, Description("SMOV <Wd>, <Vn>.<Ts>[<index>]")]
  222. public void Smov_S_W([Values(0u, 31u)] uint rd,
  223. [Values(1u)] uint rn,
  224. [ValueSource("_8B4H_")] [Random(RndCnt)] ulong a,
  225. [Values(0, 1)] int size, // <B, H>
  226. [Values(0u, 1u, 2u, 3u)] uint index)
  227. {
  228. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  229. uint opcode = 0x0E002C00; // RESERVED
  230. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  231. opcode |= (imm5 << 16);
  232. ulong x0 = (ulong)TestContext.CurrentContext.Random.NextUInt() << 32;
  233. uint w31 = TestContext.CurrentContext.Random.NextUInt();
  234. Vector128<float> v1 = MakeVectorE0(a);
  235. SingleOpcode(opcode, x0: x0, x31: w31, v1: v1);
  236. CompareAgainstUnicorn();
  237. }
  238. [Test, Pairwise, Description("SMOV <Xd>, <Vn>.<Ts>[<index>]")]
  239. public void Smov_S_X([Values(0u, 31u)] uint rd,
  240. [Values(1u)] uint rn,
  241. [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong a,
  242. [Values(0, 1, 2)] int size, // <B, H, S>
  243. [Values(0u, 1u)] uint index)
  244. {
  245. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  246. uint opcode = 0x4E002C00; // RESERVED
  247. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  248. opcode |= (imm5 << 16);
  249. ulong x31 = TestContext.CurrentContext.Random.NextULong();
  250. Vector128<float> v1 = MakeVectorE0(a);
  251. SingleOpcode(opcode, x31: x31, v1: v1);
  252. CompareAgainstUnicorn();
  253. }
  254. [Test, Pairwise, Description("UMOV <Wd>, <Vn>.<Ts>[<index>]")]
  255. public void Umov_S_W([Values(0u, 31u)] uint rd,
  256. [Values(1u)] uint rn,
  257. [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong a,
  258. [Values(0, 1, 2)] int size, // <B, H, S>
  259. [Values(0u, 1u)] uint index)
  260. {
  261. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  262. uint opcode = 0x0E003C00; // RESERVED
  263. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  264. opcode |= (imm5 << 16);
  265. ulong x0 = (ulong)TestContext.CurrentContext.Random.NextUInt() << 32;
  266. uint w31 = TestContext.CurrentContext.Random.NextUInt();
  267. Vector128<float> v1 = MakeVectorE0(a);
  268. SingleOpcode(opcode, x0: x0, x31: w31, v1: v1);
  269. CompareAgainstUnicorn();
  270. }
  271. [Test, Pairwise, Description("UMOV <Xd>, <Vn>.<Ts>[<index>]")]
  272. public void Umov_S_X([Values(0u, 31u)] uint rd,
  273. [Values(1u)] uint rn,
  274. [ValueSource("_1D_")] [Random(RndCnt)] ulong a,
  275. [Values(3)] int size, // <D>
  276. [Values(0u)] uint index)
  277. {
  278. uint imm5 = (index << (size + 1) | 1u << size) & 0x1Fu;
  279. uint opcode = 0x4E003C00; // RESERVED
  280. opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
  281. opcode |= (imm5 << 16);
  282. ulong x31 = TestContext.CurrentContext.Random.NextULong();
  283. Vector128<float> v1 = MakeVectorE0(a);
  284. SingleOpcode(opcode, x31: x31, v1: v1);
  285. CompareAgainstUnicorn();
  286. }
  287. #endif
  288. }
  289. }