CpuTestSimdImm.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #define SimdImm
  2. using NUnit.Framework;
  3. using System.Collections.Generic;
  4. using System.Runtime.Intrinsics;
  5. namespace Ryujinx.Tests.Cpu
  6. {
  7. [Category("SimdImm")]
  8. public sealed class CpuTestSimdImm : CpuTest
  9. {
  10. #if SimdImm
  11. #region "Helper methods"
  12. // abcdefgh -> aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
  13. private static ulong ExpandImm8(byte imm8)
  14. {
  15. ulong imm64 = 0ul;
  16. for (int i = 0, j = 0; i < 8; i++, j += 8)
  17. {
  18. if (((imm8 >> i) & 0b1) != 0)
  19. {
  20. imm64 |= 0b11111111ul << j;
  21. }
  22. }
  23. return imm64;
  24. }
  25. // aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh -> abcdefgh
  26. private static byte ShrinkImm64(ulong imm64)
  27. {
  28. byte imm8 = 0;
  29. for (int i = 0, j = 0; i < 8; i++, j += 8)
  30. {
  31. if (((imm64 >> j) & 0b11111111ul) != 0ul) // Note: no format check.
  32. {
  33. imm8 |= (byte)(0b1 << i);
  34. }
  35. }
  36. return imm8;
  37. }
  38. #endregion
  39. #region "ValueSource (Types)"
  40. private static IEnumerable<byte> _8BIT_IMM_()
  41. {
  42. yield return 0x00;
  43. yield return 0x7F;
  44. yield return 0x80;
  45. yield return 0xFF;
  46. for (int cnt = 1; cnt <= RndCntImm8; cnt++)
  47. {
  48. byte imm8 = TestContext.CurrentContext.Random.NextByte();
  49. yield return imm8;
  50. }
  51. }
  52. private static IEnumerable<ulong> _64BIT_IMM_()
  53. {
  54. yield return ExpandImm8(0x00);
  55. yield return ExpandImm8(0x7F);
  56. yield return ExpandImm8(0x80);
  57. yield return ExpandImm8(0xFF);
  58. for (int cnt = 1; cnt <= RndCntImm64; cnt++)
  59. {
  60. byte imm8 = TestContext.CurrentContext.Random.NextByte();
  61. yield return ExpandImm8(imm8);
  62. }
  63. }
  64. #endregion
  65. #region "ValueSource (Opcodes)"
  66. private static uint[] _Movi_V_8bit_()
  67. {
  68. return new uint[]
  69. {
  70. 0x0F00E400u // MOVI V0.8B, #0
  71. };
  72. }
  73. private static uint[] _Movi_Mvni_V_16bit_shifted_imm_()
  74. {
  75. return new uint[]
  76. {
  77. 0x0F008400u, // MOVI V0.4H, #0
  78. 0x2F008400u // MVNI V0.4H, #0
  79. };
  80. }
  81. private static uint[] _Movi_Mvni_V_32bit_shifted_imm_()
  82. {
  83. return new uint[]
  84. {
  85. 0x0F000400u, // MOVI V0.2S, #0
  86. 0x2F000400u // MVNI V0.2S, #0
  87. };
  88. }
  89. private static uint[] _Movi_Mvni_V_32bit_shifting_ones_()
  90. {
  91. return new uint[]
  92. {
  93. 0x0F00C400u, // MOVI V0.2S, #0, MSL #8
  94. 0x2F00C400u // MVNI V0.2S, #0, MSL #8
  95. };
  96. }
  97. private static uint[] _Movi_V_64bit_scalar_()
  98. {
  99. return new uint[]
  100. {
  101. 0x2F00E400u // MOVI D0, #0
  102. };
  103. }
  104. private static uint[] _Movi_V_64bit_vector_()
  105. {
  106. return new uint[]
  107. {
  108. 0x6F00E400u // MOVI V0.2D, #0
  109. };
  110. }
  111. #endregion
  112. private const int RndCntImm8 = 2;
  113. private const int RndCntImm64 = 2;
  114. [Test, Pairwise]
  115. public void Movi_V_8bit([ValueSource("_Movi_V_8bit_")] uint opcodes,
  116. [Values(0u)] uint rd,
  117. [ValueSource("_8BIT_IMM_")] byte imm8,
  118. [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
  119. {
  120. uint abc = (imm8 & 0xE0u) >> 5;
  121. uint defgh = (imm8 & 0x1Fu);
  122. opcodes |= ((rd & 31) << 0);
  123. opcodes |= (abc << 16) | (defgh << 5);
  124. opcodes |= ((q & 1) << 30);
  125. ulong z = TestContext.CurrentContext.Random.NextULong();
  126. Vector128<float> v0 = MakeVectorE1(q == 0u ? z : 0ul);
  127. SingleOpcode(opcodes, v0: v0);
  128. CompareAgainstUnicorn();
  129. }
  130. [Test, Pairwise]
  131. public void Movi_Mvni_V_16bit_shifted_imm([ValueSource("_Movi_Mvni_V_16bit_shifted_imm_")] uint opcodes,
  132. [Values(0u)] uint rd,
  133. [ValueSource("_8BIT_IMM_")] byte imm8,
  134. [Values(0b0u, 0b1u)] uint amount, // <0, 8>
  135. [Values(0b0u, 0b1u)] uint q) // <4H, 8H>
  136. {
  137. uint abc = (imm8 & 0xE0u) >> 5;
  138. uint defgh = (imm8 & 0x1Fu);
  139. opcodes |= ((rd & 31) << 0);
  140. opcodes |= (abc << 16) | (defgh << 5);
  141. opcodes |= ((amount & 1) << 13);
  142. opcodes |= ((q & 1) << 30);
  143. ulong z = TestContext.CurrentContext.Random.NextULong();
  144. Vector128<float> v0 = MakeVectorE1(q == 0u ? z : 0ul);
  145. SingleOpcode(opcodes, v0: v0);
  146. CompareAgainstUnicorn();
  147. }
  148. [Test, Pairwise]
  149. public void Movi_Mvni_V_32bit_shifted_imm([ValueSource("_Movi_Mvni_V_32bit_shifted_imm_")] uint opcodes,
  150. [Values(0u)] uint rd,
  151. [ValueSource("_8BIT_IMM_")] byte imm8,
  152. [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint amount, // <0, 8, 16, 24>
  153. [Values(0b0u, 0b1u)] uint q) // <2S, 4S>
  154. {
  155. uint abc = (imm8 & 0xE0u) >> 5;
  156. uint defgh = (imm8 & 0x1Fu);
  157. opcodes |= ((rd & 31) << 0);
  158. opcodes |= (abc << 16) | (defgh << 5);
  159. opcodes |= ((amount & 3) << 13);
  160. opcodes |= ((q & 1) << 30);
  161. ulong z = TestContext.CurrentContext.Random.NextULong();
  162. Vector128<float> v0 = MakeVectorE1(q == 0u ? z : 0ul);
  163. SingleOpcode(opcodes, v0: v0);
  164. CompareAgainstUnicorn();
  165. }
  166. [Test, Pairwise]
  167. public void Movi_Mvni_V_32bit_shifting_ones([ValueSource("_Movi_Mvni_V_32bit_shifting_ones_")] uint opcodes,
  168. [Values(0u)] uint rd,
  169. [ValueSource("_8BIT_IMM_")] byte imm8,
  170. [Values(0b0u, 0b1u)] uint amount, // <8, 16>
  171. [Values(0b0u, 0b1u)] uint q) // <2S, 4S>
  172. {
  173. uint abc = (imm8 & 0xE0u) >> 5;
  174. uint defgh = (imm8 & 0x1Fu);
  175. opcodes |= ((rd & 31) << 0);
  176. opcodes |= (abc << 16) | (defgh << 5);
  177. opcodes |= ((amount & 1) << 12);
  178. opcodes |= ((q & 1) << 30);
  179. ulong z = TestContext.CurrentContext.Random.NextULong();
  180. Vector128<float> v0 = MakeVectorE1(q == 0u ? z : 0ul);
  181. SingleOpcode(opcodes, v0: v0);
  182. CompareAgainstUnicorn();
  183. }
  184. [Test, Pairwise]
  185. public void Movi_V_64bit_scalar([ValueSource("_Movi_V_64bit_scalar_")] uint opcodes,
  186. [Values(0u)] uint rd,
  187. [ValueSource("_64BIT_IMM_")] ulong imm)
  188. {
  189. byte imm8 = ShrinkImm64(imm);
  190. uint abc = (imm8 & 0xE0u) >> 5;
  191. uint defgh = (imm8 & 0x1Fu);
  192. opcodes |= ((rd & 31) << 0);
  193. opcodes |= (abc << 16) | (defgh << 5);
  194. ulong z = TestContext.CurrentContext.Random.NextULong();
  195. Vector128<float> v0 = MakeVectorE1(z);
  196. SingleOpcode(opcodes, v0: v0);
  197. CompareAgainstUnicorn();
  198. }
  199. [Test, Pairwise]
  200. public void Movi_V_64bit_vector([ValueSource("_Movi_V_64bit_vector_")] uint opcodes,
  201. [Values(0u)] uint rd,
  202. [ValueSource("_64BIT_IMM_")] ulong imm)
  203. {
  204. byte imm8 = ShrinkImm64(imm);
  205. uint abc = (imm8 & 0xE0u) >> 5;
  206. uint defgh = (imm8 & 0x1Fu);
  207. opcodes |= ((rd & 31) << 0);
  208. opcodes |= (abc << 16) | (defgh << 5);
  209. SingleOpcode(opcodes);
  210. CompareAgainstUnicorn();
  211. }
  212. #endif
  213. }
  214. }