CpuTestSimdCvt32.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #define SimdCvt32
  2. using ARMeilleure.State;
  3. using NUnit.Framework;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace Ryujinx.Tests.Cpu
  7. {
  8. [Category("SimdCvt32")]
  9. public sealed class CpuTestSimdCvt32 : CpuTest32
  10. {
  11. #if SimdCvt32
  12. #region "ValueSource (Opcodes)"
  13. private static uint[] _Vrint_AMNP_V_F32_()
  14. {
  15. return new uint[]
  16. {
  17. 0xf3ba0500u, // VRINTA.F32 Q0, Q0
  18. 0xf3ba0680u, // VRINTM.F32 Q0, Q0
  19. 0xf3ba0400u, // VRINTN.F32 Q0, Q0
  20. 0xf3ba0780u // VRINTP.F32 Q0, Q0
  21. };
  22. }
  23. #endregion
  24. #region "ValueSource (Types)"
  25. private static uint[] _1S_()
  26. {
  27. return new uint[] { 0x00000000u, 0x7FFFFFFFu,
  28. 0x80000000u, 0xFFFFFFFFu };
  29. }
  30. private static IEnumerable<ulong> _1S_F_()
  31. {
  32. yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue)
  33. yield return 0x0000000080800000ul; // -Min Normal
  34. yield return 0x00000000807FFFFFul; // -Max Subnormal
  35. yield return 0x0000000080000001ul; // -Min Subnormal (-float.Epsilon)
  36. yield return 0x000000007F7FFFFFul; // +Max Normal (float.MaxValue)
  37. yield return 0x0000000000800000ul; // +Min Normal
  38. yield return 0x00000000007FFFFFul; // +Max Subnormal
  39. yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon)
  40. if (!NoZeros)
  41. {
  42. yield return 0x0000000080000000ul; // -Zero
  43. yield return 0x0000000000000000ul; // +Zero
  44. }
  45. if (!NoInfs)
  46. {
  47. yield return 0x00000000FF800000ul; // -Infinity
  48. yield return 0x000000007F800000ul; // +Infinity
  49. }
  50. if (!NoNaNs)
  51. {
  52. yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
  53. yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload)
  54. yield return 0x000000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN)
  55. yield return 0x000000007FBFFFFFul; // +SNaN (all ones payload)
  56. }
  57. for (int cnt = 1; cnt <= RndCnt; cnt++)
  58. {
  59. ulong grbg = TestContext.CurrentContext.Random.NextUInt();
  60. ulong rnd1 = GenNormalS();
  61. ulong rnd2 = GenSubnormalS();
  62. yield return (grbg << 32) | rnd1;
  63. yield return (grbg << 32) | rnd2;
  64. }
  65. }
  66. private static IEnumerable<ulong> _2S_F_()
  67. {
  68. yield return 0xFF7FFFFFFF7FFFFFul; // -Max Normal (float.MinValue)
  69. yield return 0x8080000080800000ul; // -Min Normal
  70. yield return 0x807FFFFF807FFFFFul; // -Max Subnormal
  71. yield return 0x8000000180000001ul; // -Min Subnormal (-float.Epsilon)
  72. yield return 0x7F7FFFFF7F7FFFFFul; // +Max Normal (float.MaxValue)
  73. yield return 0x0080000000800000ul; // +Min Normal
  74. yield return 0x007FFFFF007FFFFFul; // +Max Subnormal
  75. yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon)
  76. if (!NoZeros)
  77. {
  78. yield return 0x8000000080000000ul; // -Zero
  79. yield return 0x0000000000000000ul; // +Zero
  80. }
  81. if (!NoInfs)
  82. {
  83. yield return 0xFF800000FF800000ul; // -Infinity
  84. yield return 0x7F8000007F800000ul; // +Infinity
  85. }
  86. if (!NoNaNs)
  87. {
  88. yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN)
  89. yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload)
  90. yield return 0x7FC000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN)
  91. yield return 0x7FBFFFFF7FBFFFFFul; // +SNaN (all ones payload)
  92. }
  93. for (int cnt = 1; cnt <= RndCnt; cnt++)
  94. {
  95. ulong rnd1 = GenNormalS();
  96. ulong rnd2 = GenSubnormalS();
  97. yield return (rnd1 << 32) | rnd1;
  98. yield return (rnd2 << 32) | rnd2;
  99. }
  100. }
  101. private static IEnumerable<ulong> _1D_F_()
  102. {
  103. yield return 0xFFEFFFFFFFFFFFFFul; // -Max Normal (double.MinValue)
  104. yield return 0x8010000000000000ul; // -Min Normal
  105. yield return 0x800FFFFFFFFFFFFFul; // -Max Subnormal
  106. yield return 0x8000000000000001ul; // -Min Subnormal (-double.Epsilon)
  107. yield return 0x7FEFFFFFFFFFFFFFul; // +Max Normal (double.MaxValue)
  108. yield return 0x0010000000000000ul; // +Min Normal
  109. yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal
  110. yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon)
  111. if (!NoZeros)
  112. {
  113. yield return 0x8000000000000000ul; // -Zero
  114. yield return 0x0000000000000000ul; // +Zero
  115. }
  116. if (!NoInfs)
  117. {
  118. yield return 0xFFF0000000000000ul; // -Infinity
  119. yield return 0x7FF0000000000000ul; // +Infinity
  120. }
  121. if (!NoNaNs)
  122. {
  123. yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN)
  124. yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload)
  125. yield return 0x7FF8000000000000ul; // +QNaN (all zeros payload) (-double.NaN) (DefaultNaN)
  126. yield return 0x7FF7FFFFFFFFFFFFul; // +SNaN (all ones payload)
  127. }
  128. for (int cnt = 1; cnt <= RndCnt; cnt++)
  129. {
  130. ulong rnd1 = GenNormalD();
  131. ulong rnd2 = GenSubnormalD();
  132. yield return rnd1;
  133. yield return rnd2;
  134. }
  135. }
  136. #endregion
  137. private const int RndCnt = 2;
  138. private static readonly bool NoZeros = false;
  139. private static readonly bool NoInfs = false;
  140. private static readonly bool NoNaNs = false;
  141. [Explicit]
  142. [Test, Pairwise, Description("VCVT.<dt>.F32 <Sd>, <Sm>")]
  143. public void Vcvt_F32_I32([Values(0u, 1u, 2u, 3u)] uint rd,
  144. [Values(0u, 1u, 2u, 3u)] uint rm,
  145. [ValueSource(nameof(_1S_F_))] ulong s0,
  146. [ValueSource(nameof(_1S_F_))] ulong s1,
  147. [ValueSource(nameof(_1S_F_))] ulong s2,
  148. [ValueSource(nameof(_1S_F_))] ulong s3,
  149. [Values] bool unsigned) // <U32, S32>
  150. {
  151. uint opcode = 0xeebc0ac0u; // VCVT.U32.F32 S0, S0
  152. if (!unsigned)
  153. {
  154. opcode |= 1 << 16; // opc2<0>
  155. }
  156. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  157. opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
  158. V128 v0 = MakeVectorE0E1E2E3((uint)s0, (uint)s1, (uint)s2, (uint)s3);
  159. SingleOpcode(opcode, v0: v0);
  160. CompareAgainstUnicorn();
  161. }
  162. [Explicit]
  163. [Test, Pairwise, Description("VCVT.<dt>.F64 <Sd>, <Dm>")]
  164. public void Vcvt_F64_I32([Values(0u, 1u, 2u, 3u)] uint rd,
  165. [Values(0u, 1u)] uint rm,
  166. [ValueSource(nameof(_1D_F_))] ulong d0,
  167. [ValueSource(nameof(_1D_F_))] ulong d1,
  168. [Values] bool unsigned) // <U32, S32>
  169. {
  170. uint opcode = 0xeebc0bc0u; // VCVT.U32.F64 S0, D0
  171. if (!unsigned)
  172. {
  173. opcode |= 1 << 16; // opc2<0>
  174. }
  175. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  176. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  177. V128 v0 = MakeVectorE0E1(d0, d1);
  178. SingleOpcode(opcode, v0: v0);
  179. CompareAgainstUnicorn();
  180. }
  181. [Explicit]
  182. [Test, Pairwise, Description("VCVT.F32.<dt> <Sd>, <Sm>")]
  183. public void Vcvt_I32_F32([Values(0u, 1u, 2u, 3u)] uint rd,
  184. [Values(0u, 1u, 2u, 3u)] uint rm,
  185. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s0,
  186. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s1,
  187. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s2,
  188. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s3,
  189. [Values] bool unsigned, // <U32, S32>
  190. [Values(RMode.Rn)] RMode rMode)
  191. {
  192. uint opcode = 0xeeb80a40u; // VCVT.F32.U32 S0, S0
  193. if (!unsigned)
  194. {
  195. opcode |= 1 << 7; // op
  196. }
  197. opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
  198. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  199. V128 v0 = MakeVectorE0E1E2E3(s0, s1, s2, s3);
  200. int fpscr = (int)rMode << (int)Fpcr.RMode;
  201. SingleOpcode(opcode, v0: v0, fpscr: fpscr);
  202. CompareAgainstUnicorn();
  203. }
  204. [Explicit]
  205. [Test, Pairwise, Description("VCVT.F64.<dt> <Dd>, <Sm>")]
  206. public void Vcvt_I32_F64([Values(0u, 1u)] uint rd,
  207. [Values(0u, 1u, 2u, 3u)] uint rm,
  208. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s0,
  209. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s1,
  210. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s2,
  211. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s3,
  212. [Values] bool unsigned, // <U32, S32>
  213. [Values(RMode.Rn)] RMode rMode)
  214. {
  215. uint opcode = 0xeeb80b40u; // VCVT.F64.U32 D0, S0
  216. if (!unsigned)
  217. {
  218. opcode |= 1 << 7; // op
  219. }
  220. opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
  221. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  222. V128 v0 = MakeVectorE0E1E2E3(s0, s1, s2, s3);
  223. int fpscr = (int)rMode << (int)Fpcr.RMode;
  224. SingleOpcode(opcode, v0: v0, fpscr: fpscr);
  225. CompareAgainstUnicorn();
  226. }
  227. [Test, Pairwise] [Explicit]
  228. public void Vrint_AMNP_V_F32([ValueSource(nameof(_Vrint_AMNP_V_F32_))] uint opcode,
  229. [Values(0u, 1u, 2u, 3u)] uint rd,
  230. [Values(0u, 1u, 2u, 3u)] uint rm,
  231. [ValueSource(nameof(_2S_F_))] ulong d0,
  232. [ValueSource(nameof(_2S_F_))] ulong d1,
  233. [ValueSource(nameof(_2S_F_))] ulong d2,
  234. [ValueSource(nameof(_2S_F_))] ulong d3,
  235. [Values] bool q)
  236. {
  237. if (q)
  238. {
  239. opcode |= 1 << 6;
  240. rd >>= 1; rd <<= 1;
  241. rm >>= 1; rm <<= 1;
  242. }
  243. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  244. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  245. V128 v0 = MakeVectorE0E1(d0, d1);
  246. V128 v1 = MakeVectorE0E1(d2, d3);
  247. SingleOpcode(opcode, v0: v0, v1: v1);
  248. CompareAgainstUnicorn();
  249. }
  250. [Test, Pairwise, Description("VRINTX.F<size> <Sd>, <Sm>")]
  251. public void Vrintx_S([Values(0u, 1u)] uint rd,
  252. [Values(0u, 1u)] uint rm,
  253. [Values(2u, 3u)] uint size,
  254. [ValueSource(nameof(_1D_F_))] ulong s0,
  255. [ValueSource(nameof(_1D_F_))] ulong s1,
  256. [ValueSource(nameof(_1D_F_))] ulong s2,
  257. [Values(RMode.Rn, RMode.Rm, RMode.Rp)] RMode rMode)
  258. {
  259. uint opcode = 0xEB70A40;
  260. V128 v0, v1, v2;
  261. if (size == 2)
  262. {
  263. opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
  264. opcode |= ((rd & 0x1e) >> 11) | ((rm & 0x1) << 22);
  265. v0 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s0), (uint)BitConverter.SingleToInt32Bits(s0));
  266. v1 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s1), (uint)BitConverter.SingleToInt32Bits(s0));
  267. v2 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s2), (uint)BitConverter.SingleToInt32Bits(s1));
  268. }
  269. else
  270. {
  271. opcode |= ((rm & 0xf) << 0) | ((rd & 0x10) << 1);
  272. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  273. v0 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s0), (uint)BitConverter.DoubleToInt64Bits(s0));
  274. v1 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s1), (uint)BitConverter.DoubleToInt64Bits(s0));
  275. v2 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s2), (uint)BitConverter.DoubleToInt64Bits(s1));
  276. }
  277. opcode |= ((size & 3) << 8);
  278. int fpscr = (int)rMode << (int)Fpcr.RMode;
  279. SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr);
  280. CompareAgainstUnicorn();
  281. }
  282. [Explicit]
  283. [Test, Pairwise, Description("VCVT<top>.F16.F32 <Sd>, <Dm>")]
  284. public void Vcvt_F32_F16([Values(0u, 1u, 2u, 3u)] uint rd,
  285. [Values(0u, 1u, 2u, 3u)] uint rm,
  286. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s0,
  287. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s1,
  288. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s2,
  289. [ValueSource(nameof(_1S_))] [Random(RndCnt)] uint s3,
  290. [Values] bool top)
  291. {
  292. uint opcode = 0xeeb30a40; // VCVTB.F16.F32 S0, D0
  293. if (top)
  294. {
  295. opcode |= 1 << 7;
  296. }
  297. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  298. opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
  299. V128 v0 = MakeVectorE0E1E2E3(s0, s1, s2, s3);
  300. SingleOpcode(opcode, v0: v0);
  301. CompareAgainstUnicorn();
  302. }
  303. [Explicit]
  304. [Test, Pairwise, Description("VCVT<top>.F16.F64 <Sd>, <Dm>")]
  305. public void Vcvt_F64_F16([Values(0u, 1u, 2u, 3u)] uint rd,
  306. [Values(0u, 1u)] uint rm,
  307. [ValueSource(nameof(_1D_F_))] ulong d0,
  308. [ValueSource(nameof(_1D_F_))] ulong d1,
  309. [Values] bool top)
  310. {
  311. uint opcode = 0xeeb30b40; // VCVTB.F16.F64 S0, D0
  312. if (top)
  313. {
  314. opcode |= 1 << 7;
  315. }
  316. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  317. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  318. V128 v0 = MakeVectorE0E1(d0, d1);
  319. SingleOpcode(opcode, v0: v0);
  320. CompareAgainstUnicorn();
  321. }
  322. [Explicit]
  323. [Test, Pairwise, Description("VCVT<top>.F<size>.F16 <Vd>, <Sm>")]
  324. public void Vcvt_F16_Fx([Values(0u, 1u, 2u, 3u)] uint rd,
  325. [Values(0u, 1u, 2u, 3u)] uint rm,
  326. [ValueSource(nameof(_1D_F_))] ulong d0,
  327. [ValueSource(nameof(_1D_F_))] ulong d1,
  328. [Values] bool top,
  329. [Values] bool sz)
  330. {
  331. uint opcode = 0xeeb20a40; // VCVTB.F32.F16 S0, S0
  332. if (top)
  333. {
  334. opcode |= 1 << 7;
  335. }
  336. if (sz)
  337. {
  338. opcode |= 1 << 8;
  339. opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
  340. }
  341. else
  342. {
  343. opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
  344. }
  345. opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
  346. V128 v0 = MakeVectorE0E1(d0, d1);
  347. SingleOpcode(opcode, v0: v0);
  348. CompareAgainstUnicorn();
  349. }
  350. #endif
  351. }
  352. }