CpuTestMisc.cs 7.6 KB

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