CpuTest.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using ChocolArm64;
  2. using ChocolArm64.Memory;
  3. using ChocolArm64.State;
  4. using NUnit.Framework;
  5. using System;
  6. using System.Runtime.InteropServices;
  7. using System.Runtime.Intrinsics;
  8. using System.Runtime.Intrinsics.X86;
  9. using System.Threading;
  10. namespace Ryujinx.Tests.Cpu
  11. {
  12. [TestFixture]
  13. public class CpuTest
  14. {
  15. protected long Position { get; private set; }
  16. private long Size;
  17. private long EntryPoint;
  18. private IntPtr RamPointer;
  19. private AMemory Memory;
  20. private AThread Thread;
  21. [SetUp]
  22. public void Setup()
  23. {
  24. Position = 0x0;
  25. Size = 0x1000;
  26. EntryPoint = Position;
  27. ATranslator Translator = new ATranslator();
  28. RamPointer = Marshal.AllocHGlobal(new IntPtr(Size));
  29. Memory = new AMemory(RamPointer);
  30. Memory.Map(Position, 0, Size);
  31. Thread = new AThread(Translator, Memory, EntryPoint);
  32. }
  33. [TearDown]
  34. public void Teardown()
  35. {
  36. Marshal.FreeHGlobal(RamPointer);
  37. Memory = null;
  38. Thread = null;
  39. }
  40. protected void Reset()
  41. {
  42. Teardown();
  43. Setup();
  44. }
  45. protected void Opcode(uint Opcode)
  46. {
  47. Thread.Memory.WriteUInt32(Position, Opcode);
  48. Position += 4;
  49. }
  50. protected void SetThreadState(ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X3 = 0, ulong X31 = 0,
  51. Vector128<float> V0 = default(Vector128<float>),
  52. Vector128<float> V1 = default(Vector128<float>),
  53. Vector128<float> V2 = default(Vector128<float>),
  54. bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false,
  55. int Fpcr = 0x0, int Fpsr = 0x0)
  56. {
  57. Thread.ThreadState.X0 = X0;
  58. Thread.ThreadState.X1 = X1;
  59. Thread.ThreadState.X2 = X2;
  60. Thread.ThreadState.X3 = X3;
  61. Thread.ThreadState.X31 = X31;
  62. Thread.ThreadState.V0 = V0;
  63. Thread.ThreadState.V1 = V1;
  64. Thread.ThreadState.V2 = V2;
  65. Thread.ThreadState.Overflow = Overflow;
  66. Thread.ThreadState.Carry = Carry;
  67. Thread.ThreadState.Zero = Zero;
  68. Thread.ThreadState.Negative = Negative;
  69. Thread.ThreadState.Fpcr = Fpcr;
  70. Thread.ThreadState.Fpsr = Fpsr;
  71. }
  72. protected void ExecuteOpcodes()
  73. {
  74. using (ManualResetEvent Wait = new ManualResetEvent(false))
  75. {
  76. Thread.ThreadState.Break += (sender, e) => Thread.StopExecution();
  77. Thread.WorkFinished += (sender, e) => Wait.Set();
  78. Thread.Execute();
  79. Wait.WaitOne();
  80. }
  81. }
  82. protected AThreadState GetThreadState()
  83. {
  84. return Thread.ThreadState;
  85. }
  86. protected AThreadState SingleOpcode(uint Opcode,
  87. ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X3 = 0, ulong X31 = 0,
  88. Vector128<float> V0 = default(Vector128<float>),
  89. Vector128<float> V1 = default(Vector128<float>),
  90. Vector128<float> V2 = default(Vector128<float>),
  91. bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false,
  92. int Fpcr = 0x0, int Fpsr = 0x0)
  93. {
  94. this.Opcode(Opcode);
  95. this.Opcode(0xD4200000); // BRK #0
  96. this.Opcode(0xD65F03C0); // RET
  97. SetThreadState(X0, X1, X2, X3, X31, V0, V1, V2, Overflow, Carry, Zero, Negative, Fpcr, Fpsr);
  98. ExecuteOpcodes();
  99. return GetThreadState();
  100. }
  101. protected static Vector128<float> MakeVectorE0(double E0)
  102. {
  103. return Sse.StaticCast<long, float>(Sse2.SetVector128(0, BitConverter.DoubleToInt64Bits(E0)));
  104. }
  105. protected static Vector128<float> MakeVectorE0E1(double E0, double E1)
  106. {
  107. return Sse.StaticCast<long, float>(Sse2.SetVector128(BitConverter.DoubleToInt64Bits(E1),
  108. BitConverter.DoubleToInt64Bits(E0)));
  109. }
  110. protected static Vector128<float> MakeVectorE1(double E1)
  111. {
  112. return Sse.StaticCast<long, float>(Sse2.SetVector128(BitConverter.DoubleToInt64Bits(E1), 0));
  113. }
  114. protected static double VectorExtractDouble(Vector128<float> Vector, byte Index)
  115. {
  116. long Value = Sse41.Extract(Sse.StaticCast<float, long>(Vector), Index);
  117. return BitConverter.Int64BitsToDouble(Value);
  118. }
  119. protected static Vector128<float> MakeVectorE0(ulong E0)
  120. {
  121. return Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, E0));
  122. }
  123. protected static Vector128<float> MakeVectorE0E1(ulong E0, ulong E1)
  124. {
  125. return Sse.StaticCast<ulong, float>(Sse2.SetVector128(E1, E0));
  126. }
  127. protected static Vector128<float> MakeVectorE1(ulong E1)
  128. {
  129. return Sse.StaticCast<ulong, float>(Sse2.SetVector128(E1, 0));
  130. }
  131. protected static ulong GetVectorE0(Vector128<float> Vector)
  132. {
  133. return Sse41.Extract(Sse.StaticCast<float, ulong>(Vector), (byte)0);
  134. }
  135. protected static ulong GetVectorE1(Vector128<float> Vector)
  136. {
  137. return Sse41.Extract(Sse.StaticCast<float, ulong>(Vector), (byte)1);
  138. }
  139. }
  140. }