CpuTestSimdCmp.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. using ChocolArm64.State;
  2. using NUnit.Framework;
  3. using System;
  4. using System.Runtime.Intrinsics;
  5. using System.Runtime.Intrinsics.X86;
  6. namespace Ryujinx.Tests.Cpu
  7. {
  8. public class CpuTestSimdCmp : CpuTest
  9. {
  10. #region "ValueSource"
  11. private static float[] _floats_()
  12. {
  13. return new float[] { float.NegativeInfinity, float.MinValue, -1f, -0f,
  14. +0f, +1f, float.MaxValue, float.PositiveInfinity };
  15. }
  16. private static double[] _doubles_()
  17. {
  18. return new double[] { double.NegativeInfinity, double.MinValue, -1d, -0d,
  19. +0d, +1d, double.MaxValue, double.PositiveInfinity };
  20. }
  21. #endregion
  22. [Test, Description("FCMEQ D0, D1, D2 | FCMGE D0, D1, D2 | FCMGT D0, D1, D2")]
  23. public void Fcmeq_Fcmge_Fcmgt_Reg_S_D([ValueSource("_doubles_")] [Random(8)] double A,
  24. [ValueSource("_doubles_")] [Random(8)] double B,
  25. [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
  26. {
  27. uint Opcode = 0x5E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
  28. Vector128<float> V0 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(TestContext.CurrentContext.Random.NextDouble()));
  29. Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A));
  30. Vector128<float> V2 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(B));
  31. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  32. byte[] Exp = default(byte[]);
  33. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  34. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  35. switch (EU)
  36. {
  37. case 0: Exp = (A == B ? Ones : Zeros); break;
  38. case 1: Exp = (A >= B ? Ones : Zeros); break;
  39. case 3: Exp = (A > B ? Ones : Zeros); break;
  40. }
  41. Assert.Multiple(() =>
  42. {
  43. Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  44. Assert.That(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero);
  45. });
  46. }
  47. [Test, Description("FCMEQ S0, S1, S2 | FCMGE S0, S1, S2 | FCMGT S0, S1, S2")]
  48. public void Fcmeq_Fcmge_Fcmgt_Reg_S_S([ValueSource("_floats_")] [Random(8)] float A,
  49. [ValueSource("_floats_")] [Random(8)] float B,
  50. [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
  51. {
  52. uint Opcode = 0x5E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
  53. Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
  54. Vector128<float> V1 = Sse.SetScalarVector128(A);
  55. Vector128<float> V2 = Sse.SetScalarVector128(B);
  56. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  57. byte[] Exp = default(byte[]);
  58. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF};
  59. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00};
  60. switch (EU)
  61. {
  62. case 0: Exp = (A == B ? Ones : Zeros); break;
  63. case 1: Exp = (A >= B ? Ones : Zeros); break;
  64. case 3: Exp = (A > B ? Ones : Zeros); break;
  65. }
  66. Assert.Multiple(() =>
  67. {
  68. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  69. Assert.That(Sse41.Extract(ThreadState.V0, (byte)1), Is.Zero);
  70. Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
  71. Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
  72. });
  73. }
  74. [Test, Description("FCMEQ V0.2D, V1.2D, V2.2D | FCMGE V0.2D, V1.2D, V2.2D | FCMGT V0.2D, V1.2D, V2.2D")]
  75. public void Fcmeq_Fcmge_Fcmgt_Reg_V_2D([ValueSource("_doubles_")] [Random(8)] double A,
  76. [ValueSource("_doubles_")] [Random(8)] double B,
  77. [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
  78. {
  79. uint Opcode = 0x4E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
  80. Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A));
  81. Vector128<float> V2 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(B));
  82. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
  83. byte[] Exp = default(byte[]);
  84. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  85. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  86. switch (EU)
  87. {
  88. case 0: Exp = (A == B ? Ones : Zeros); break;
  89. case 1: Exp = (A >= B ? Ones : Zeros); break;
  90. case 3: Exp = (A > B ? Ones : Zeros); break;
  91. }
  92. Assert.Multiple(() =>
  93. {
  94. Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  95. Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
  96. });
  97. }
  98. [Test, Description("FCMEQ V0.2S, V1.2S, V2.2S | FCMGE V0.2S, V1.2S, V2.2S | FCMGT V0.2S, V1.2S, V2.2S")]
  99. public void Fcmeq_Fcmge_Fcmgt_Reg_V_2S([ValueSource("_floats_")] [Random(8)] float A,
  100. [ValueSource("_floats_")] [Random(8)] float B,
  101. [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
  102. {
  103. uint Opcode = 0x0E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
  104. Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
  105. Vector128<float> V1 = Sse.SetVector128(0, 0, A, A);
  106. Vector128<float> V2 = Sse.SetVector128(0, 0, B, B);
  107. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  108. byte[] Exp = default(byte[]);
  109. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF};
  110. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00};
  111. switch (EU)
  112. {
  113. case 0: Exp = (A == B ? Ones : Zeros); break;
  114. case 1: Exp = (A >= B ? Ones : Zeros); break;
  115. case 3: Exp = (A > B ? Ones : Zeros); break;
  116. }
  117. Assert.Multiple(() =>
  118. {
  119. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  120. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
  121. Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
  122. Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
  123. });
  124. }
  125. [Test, Description("FCMEQ V0.4S, V1.4S, V2.4S | FCMGE V0.4S, V1.4S, V2.4S | FCMGT V0.4S, V1.4S, V2.4S")]
  126. public void Fcmeq_Fcmge_Fcmgt_Reg_V_4S([ValueSource("_floats_")] [Random(8)] float A,
  127. [ValueSource("_floats_")] [Random(8)] float B,
  128. [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
  129. {
  130. uint Opcode = 0x4E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
  131. Vector128<float> V1 = Sse.SetAllVector128(A);
  132. Vector128<float> V2 = Sse.SetAllVector128(B);
  133. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
  134. byte[] Exp = default(byte[]);
  135. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF};
  136. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00};
  137. switch (EU)
  138. {
  139. case 0: Exp = (A == B ? Ones : Zeros); break;
  140. case 1: Exp = (A >= B ? Ones : Zeros); break;
  141. case 3: Exp = (A > B ? Ones : Zeros); break;
  142. }
  143. Assert.Multiple(() =>
  144. {
  145. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  146. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
  147. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)2)), Is.EquivalentTo(Exp));
  148. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)3)), Is.EquivalentTo(Exp));
  149. });
  150. }
  151. [Test, Description("FCMGT D0, D1, #0.0 | FCMGE D0, D1, #0.0 | FCMEQ D0, D1, #0.0 | FCMLE D0, D1, #0.0 | FCMLT D0, D1, #0.0")]
  152. public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_S_D([ValueSource("_doubles_")] [Random(8)] double A,
  153. [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
  154. [Values(0u, 1u)] uint bit13) // "LT"
  155. {
  156. uint Opcode = 0x5EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
  157. Vector128<float> V0 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(TestContext.CurrentContext.Random.NextDouble()));
  158. Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A));
  159. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
  160. double Zero = +0d;
  161. byte[] Exp = default(byte[]);
  162. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  163. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  164. if (bit13 == 0)
  165. {
  166. switch (opU)
  167. {
  168. case 0: Exp = (A > Zero ? Ones : Zeros); break;
  169. case 1: Exp = (A >= Zero ? Ones : Zeros); break;
  170. case 2: Exp = (A == Zero ? Ones : Zeros); break;
  171. case 3: Exp = (Zero >= A ? Ones : Zeros); break;
  172. }
  173. }
  174. else
  175. {
  176. Exp = (Zero > A ? Ones : Zeros);
  177. }
  178. Assert.Multiple(() =>
  179. {
  180. Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  181. Assert.That(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero);
  182. });
  183. }
  184. [Test, Description("FCMGT S0, S1, #0.0 | FCMGE S0, S1, #0.0 | FCMEQ S0, S1, #0.0 | FCMLE S0, S1, #0.0 | FCMLT S0, S1, #0.0")]
  185. public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_S_S([ValueSource("_floats_")] [Random(8)] float A,
  186. [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
  187. [Values(0u, 1u)] uint bit13) // "LT"
  188. {
  189. uint Opcode = 0x5EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
  190. Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
  191. Vector128<float> V1 = Sse.SetScalarVector128(A);
  192. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
  193. float Zero = +0f;
  194. byte[] Exp = default(byte[]);
  195. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF};
  196. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00};
  197. if (bit13 == 0)
  198. {
  199. switch (opU)
  200. {
  201. case 0: Exp = (A > Zero ? Ones : Zeros); break;
  202. case 1: Exp = (A >= Zero ? Ones : Zeros); break;
  203. case 2: Exp = (A == Zero ? Ones : Zeros); break;
  204. case 3: Exp = (Zero >= A ? Ones : Zeros); break;
  205. }
  206. }
  207. else
  208. {
  209. Exp = (Zero > A ? Ones : Zeros);
  210. }
  211. Assert.Multiple(() =>
  212. {
  213. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  214. Assert.That(Sse41.Extract(ThreadState.V0, (byte)1), Is.Zero);
  215. Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
  216. Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
  217. });
  218. }
  219. [Test, Description("FCMGT V0.2D, V1.2D, #0.0 | FCMGE V0.2D, V1.2D, #0.0 | FCMEQ V0.2D, V1.2D, #0.0 | FCMLE V0.2D, V1.2D, #0.0 | FCMLT V0.2D, V1.2D, #0.0")]
  220. public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_2D([ValueSource("_doubles_")] [Random(8)] double A,
  221. [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
  222. [Values(0u, 1u)] uint bit13) // "LT"
  223. {
  224. uint Opcode = 0x4EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
  225. Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A));
  226. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
  227. double Zero = +0d;
  228. byte[] Exp = default(byte[]);
  229. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  230. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  231. if (bit13 == 0)
  232. {
  233. switch (opU)
  234. {
  235. case 0: Exp = (A > Zero ? Ones : Zeros); break;
  236. case 1: Exp = (A >= Zero ? Ones : Zeros); break;
  237. case 2: Exp = (A == Zero ? Ones : Zeros); break;
  238. case 3: Exp = (Zero >= A ? Ones : Zeros); break;
  239. }
  240. }
  241. else
  242. {
  243. Exp = (Zero > A ? Ones : Zeros);
  244. }
  245. Assert.Multiple(() =>
  246. {
  247. Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  248. Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
  249. });
  250. }
  251. [Test, Description("FCMGT V0.2S, V1.2S, #0.0 | FCMGE V0.2S, V1.2S, #0.0 | FCMEQ V0.2S, V1.2S, #0.0 | FCMLE V0.2S, V1.2S, #0.0 | FCMLT V0.2S, V1.2S, #0.0")]
  252. public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_2S([ValueSource("_floats_")] [Random(8)] float A,
  253. [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
  254. [Values(0u, 1u)] uint bit13) // "LT"
  255. {
  256. uint Opcode = 0x0EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
  257. Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
  258. Vector128<float> V1 = Sse.SetVector128(0, 0, A, A);
  259. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
  260. float Zero = +0f;
  261. byte[] Exp = default(byte[]);
  262. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF};
  263. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00};
  264. if (bit13 == 0)
  265. {
  266. switch (opU)
  267. {
  268. case 0: Exp = (A > Zero ? Ones : Zeros); break;
  269. case 1: Exp = (A >= Zero ? Ones : Zeros); break;
  270. case 2: Exp = (A == Zero ? Ones : Zeros); break;
  271. case 3: Exp = (Zero >= A ? Ones : Zeros); break;
  272. }
  273. }
  274. else
  275. {
  276. Exp = (Zero > A ? Ones : Zeros);
  277. }
  278. Assert.Multiple(() =>
  279. {
  280. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  281. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
  282. Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
  283. Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
  284. });
  285. }
  286. [Test, Description("FCMGT V0.4S, V1.4S, #0.0 | FCMGE V0.4S, V1.4S, #0.0 | FCMEQ V0.4S, V1.4S, #0.0 | FCMLE V0.4S, V1.4S, #0.0 | FCMLT V0.4S, V1.4S, #0.0")]
  287. public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_4S([ValueSource("_floats_")] [Random(8)] float A,
  288. [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
  289. [Values(0u, 1u)] uint bit13) // "LT"
  290. {
  291. uint Opcode = 0x4EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
  292. Vector128<float> V1 = Sse.SetAllVector128(A);
  293. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
  294. float Zero = +0f;
  295. byte[] Exp = default(byte[]);
  296. byte[] Ones = new byte[] {0xFF, 0xFF, 0xFF, 0xFF};
  297. byte[] Zeros = new byte[] {0x00, 0x00, 0x00, 0x00};
  298. if (bit13 == 0)
  299. {
  300. switch (opU)
  301. {
  302. case 0: Exp = (A > Zero ? Ones : Zeros); break;
  303. case 1: Exp = (A >= Zero ? Ones : Zeros); break;
  304. case 2: Exp = (A == Zero ? Ones : Zeros); break;
  305. case 3: Exp = (Zero >= A ? Ones : Zeros); break;
  306. }
  307. }
  308. else
  309. {
  310. Exp = (Zero > A ? Ones : Zeros);
  311. }
  312. Assert.Multiple(() =>
  313. {
  314. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
  315. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
  316. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)2)), Is.EquivalentTo(Exp));
  317. Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)3)), Is.EquivalentTo(Exp));
  318. });
  319. }
  320. }
  321. }