CpuTestSimdIns.cs 14 KB

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