CpuTestMisc.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. using ChocolArm64.State;
  2. using NUnit.Framework;
  3. using System.Runtime.Intrinsics.X86;
  4. namespace Ryujinx.Tests.Cpu
  5. {
  6. [Category("Misc"), Explicit]
  7. public sealed class CpuTestMisc : CpuTest
  8. {
  9. [TestCase(0xFFFFFFFDu)] // Roots.
  10. [TestCase(0x00000005u)]
  11. public void Misc1(uint A)
  12. {
  13. // ((A + 3) * (A - 5)) / ((A + 5) * (A - 3)) = 0
  14. /*
  15. ADD W2, W0, 3
  16. SUB W1, W0, #5
  17. MUL W2, W2, W1
  18. ADD W1, W0, 5
  19. SUB W0, W0, #3
  20. MUL W0, W1, W0
  21. SDIV W0, W2, W0
  22. BRK #0
  23. RET
  24. */
  25. SetThreadState(X0: A);
  26. Opcode(0x11000C02);
  27. Opcode(0x51001401);
  28. Opcode(0x1B017C42);
  29. Opcode(0x11001401);
  30. Opcode(0x51000C00);
  31. Opcode(0x1B007C20);
  32. Opcode(0x1AC00C40);
  33. Opcode(0xD4200000);
  34. Opcode(0xD65F03C0);
  35. ExecuteOpcodes();
  36. Assert.That(GetThreadState().X0, Is.Zero);
  37. }
  38. [TestCase(-20f, -5f)] // 18 integer solutions.
  39. [TestCase(-12f, -6f)]
  40. [TestCase(-12f, 3f)]
  41. [TestCase( -8f, -8f)]
  42. [TestCase( -6f, -12f)]
  43. [TestCase( -5f, -20f)]
  44. [TestCase( -4f, 2f)]
  45. [TestCase( -3f, 12f)]
  46. [TestCase( -2f, 4f)]
  47. [TestCase( 2f, -4f)]
  48. [TestCase( 3f, -12f)]
  49. [TestCase( 4f, -2f)]
  50. [TestCase( 5f, 20f)]
  51. [TestCase( 6f, 12f)]
  52. [TestCase( 8f, 8f)]
  53. [TestCase( 12f, -3f)]
  54. [TestCase( 12f, 6f)]
  55. [TestCase( 20f, 5f)]
  56. public void Misc2(float A, float B)
  57. {
  58. // 1 / ((1 / A + 1 / B) ^ 2) = 16
  59. /*
  60. FMOV S2, 1.0e+0
  61. FDIV S0, S2, S0
  62. FDIV S1, S2, S1
  63. FADD S0, S0, S1
  64. FDIV S0, S2, S0
  65. FMUL S0, S0, S0
  66. BRK #0
  67. RET
  68. */
  69. SetThreadState(
  70. V0: Sse.SetScalarVector128(A),
  71. V1: Sse.SetScalarVector128(B));
  72. Opcode(0x1E2E1002);
  73. Opcode(0x1E201840);
  74. Opcode(0x1E211841);
  75. Opcode(0x1E212800);
  76. Opcode(0x1E201840);
  77. Opcode(0x1E200800);
  78. Opcode(0xD4200000);
  79. Opcode(0xD65F03C0);
  80. ExecuteOpcodes();
  81. Assert.That(Sse41.Extract(GetThreadState().V0, 0), Is.EqualTo(16f));
  82. }
  83. [TestCase(-20d, -5d)] // 18 integer solutions.
  84. [TestCase(-12d, -6d)]
  85. [TestCase(-12d, 3d)]
  86. [TestCase( -8d, -8d)]
  87. [TestCase( -6d, -12d)]
  88. [TestCase( -5d, -20d)]
  89. [TestCase( -4d, 2d)]
  90. [TestCase( -3d, 12d)]
  91. [TestCase( -2d, 4d)]
  92. [TestCase( 2d, -4d)]
  93. [TestCase( 3d, -12d)]
  94. [TestCase( 4d, -2d)]
  95. [TestCase( 5d, 20d)]
  96. [TestCase( 6d, 12d)]
  97. [TestCase( 8d, 8d)]
  98. [TestCase( 12d, -3d)]
  99. [TestCase( 12d, 6d)]
  100. [TestCase( 20d, 5d)]
  101. public void Misc3(double A, double B)
  102. {
  103. // 1 / ((1 / A + 1 / B) ^ 2) = 16
  104. /*
  105. FMOV D2, 1.0e+0
  106. FDIV D0, D2, D0
  107. FDIV D1, D2, D1
  108. FADD D0, D0, D1
  109. FDIV D0, D2, D0
  110. FMUL D0, D0, D0
  111. BRK #0
  112. RET
  113. */
  114. SetThreadState(
  115. V0: Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A)),
  116. V1: Sse.StaticCast<double, float>(Sse2.SetScalarVector128(B)));
  117. Opcode(0x1E6E1002);
  118. Opcode(0x1E601840);
  119. Opcode(0x1E611841);
  120. Opcode(0x1E612800);
  121. Opcode(0x1E601840);
  122. Opcode(0x1E600800);
  123. Opcode(0xD4200000);
  124. Opcode(0xD65F03C0);
  125. ExecuteOpcodes();
  126. Assert.That(VectorExtractDouble(GetThreadState().V0, 0), Is.EqualTo(16d));
  127. }
  128. [Test]
  129. public void MiscF([Range(0u, 92u, 1u)] uint A)
  130. {
  131. ulong F_n(uint n)
  132. {
  133. ulong a = 0, b = 1, c;
  134. if (n == 0)
  135. {
  136. return a;
  137. }
  138. for (uint i = 2; i <= n; i++)
  139. {
  140. c = a + b;
  141. a = b;
  142. b = c;
  143. }
  144. return b;
  145. }
  146. /*
  147. 0x0000000000000000: MOV W4, W0
  148. 0x0000000000000004: CBZ W0, #0x3C
  149. 0x0000000000000008: CMP W0, #1
  150. 0x000000000000000C: B.LS #0x48
  151. 0x0000000000000010: MOVZ W2, #0x2
  152. 0x0000000000000014: MOVZ X1, #0x1
  153. 0x0000000000000018: MOVZ X3, #0
  154. 0x000000000000001C: ADD X0, X3, X1
  155. 0x0000000000000020: ADD W2, W2, #1
  156. 0x0000000000000024: MOV X3, X1
  157. 0x0000000000000028: MOV X1, X0
  158. 0x000000000000002C: CMP W4, W2
  159. 0x0000000000000030: B.HS #0x1C
  160. 0x0000000000000034: BRK #0
  161. 0x0000000000000038: RET
  162. 0x000000000000003C: MOVZ X0, #0
  163. 0x0000000000000040: BRK #0
  164. 0x0000000000000044: RET
  165. 0x0000000000000048: MOVZ X0, #0x1
  166. 0x000000000000004C: BRK #0
  167. 0x0000000000000050: RET
  168. */
  169. SetThreadState(X0: A);
  170. Opcode(0x2A0003E4);
  171. Opcode(0x340001C0);
  172. Opcode(0x7100041F);
  173. Opcode(0x540001E9);
  174. Opcode(0x52800042);
  175. Opcode(0xD2800021);
  176. Opcode(0xD2800003);
  177. Opcode(0x8B010060);
  178. Opcode(0x11000442);
  179. Opcode(0xAA0103E3);
  180. Opcode(0xAA0003E1);
  181. Opcode(0x6B02009F);
  182. Opcode(0x54FFFF62);
  183. Opcode(0xD4200000);
  184. Opcode(0xD65F03C0);
  185. Opcode(0xD2800000);
  186. Opcode(0xD4200000);
  187. Opcode(0xD65F03C0);
  188. Opcode(0xD2800020);
  189. Opcode(0xD4200000);
  190. Opcode(0xD65F03C0);
  191. ExecuteOpcodes();
  192. Assert.That(GetThreadState().X0, Is.EqualTo(F_n(A)));
  193. }
  194. [Test]
  195. public void MiscR()
  196. {
  197. const ulong Result = 5;
  198. /*
  199. 0x0000000000000000: MOV X0, #2
  200. 0x0000000000000004: MOV X1, #3
  201. 0x0000000000000008: ADD X0, X0, X1
  202. 0x000000000000000C: BRK #0
  203. 0x0000000000000010: RET
  204. */
  205. Opcode(0xD2800040);
  206. Opcode(0xD2800061);
  207. Opcode(0x8B010000);
  208. Opcode(0xD4200000);
  209. Opcode(0xD65F03C0);
  210. ExecuteOpcodes();
  211. Assert.That(GetThreadState().X0, Is.EqualTo(Result));
  212. Reset();
  213. /*
  214. 0x0000000000000000: MOV X0, #3
  215. 0x0000000000000004: MOV X1, #2
  216. 0x0000000000000008: ADD X0, X0, X1
  217. 0x000000000000000C: BRK #0
  218. 0x0000000000000010: RET
  219. */
  220. Opcode(0xD2800060);
  221. Opcode(0xD2800041);
  222. Opcode(0x8B010000);
  223. Opcode(0xD4200000);
  224. Opcode(0xD65F03C0);
  225. ExecuteOpcodes();
  226. Assert.That(GetThreadState().X0, Is.EqualTo(Result));
  227. }
  228. [TestCase( 0ul)]
  229. [TestCase( 1ul)]
  230. [TestCase( 2ul)]
  231. [TestCase(42ul)]
  232. public void SanityCheck(ulong A)
  233. {
  234. uint Opcode = 0xD503201F; // NOP
  235. AThreadState ThreadState = SingleOpcode(Opcode, X0: A);
  236. Assert.That(ThreadState.X0, Is.EqualTo(A));
  237. }
  238. }
  239. }