aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Tests/Cpu/CpuTest.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Tests/Cpu/CpuTest.cs')
-rw-r--r--src/Ryujinx.Tests/Cpu/CpuTest.cs219
1 files changed, 117 insertions, 102 deletions
diff --git a/src/Ryujinx.Tests/Cpu/CpuTest.cs b/src/Ryujinx.Tests/Cpu/CpuTest.cs
index ad4ba539..35158c0b 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -14,13 +14,15 @@ namespace Ryujinx.Tests.Cpu
public class CpuTest
{
protected static readonly ulong Size = MemoryBlock.GetPageSize();
+#pragma warning disable CA2211 // Non-constant fields should not be visible
protected static ulong CodeBaseAddress = Size;
protected static ulong DataBaseAddress = CodeBaseAddress + Size;
+#pragma warning restore CA2211
- private static bool Ignore_FpcrFz = false;
- private static bool Ignore_FpcrDn = false;
+ private static readonly bool _ignoreFpcrFz = false;
+ private static readonly bool _ignoreFpcrDn = false;
- private static bool IgnoreAllExcept_FpsrQc = false;
+ private static readonly bool _ignoreAllExceptFpsrQc = false;
private ulong _currAddress;
@@ -84,8 +86,8 @@ namespace Ryujinx.Tests.Cpu
_context.Dispose();
_ram.Dispose();
- _memory = null;
- _context = null;
+ _memory = null;
+ _context = null;
_cpuContext = null;
_unicornEmu = null;
@@ -109,38 +111,38 @@ namespace Ryujinx.Tests.Cpu
protected ExecutionContext GetContext() => _context;
- protected void SetContext(ulong x0 = 0,
- ulong x1 = 0,
- ulong x2 = 0,
- ulong x3 = 0,
- ulong x31 = 0,
- V128 v0 = default,
- V128 v1 = default,
- V128 v2 = default,
- V128 v3 = default,
- V128 v4 = default,
- V128 v5 = default,
- V128 v30 = default,
- V128 v31 = default,
- bool overflow = false,
- bool carry = false,
- bool zero = false,
- bool negative = false,
- int fpcr = 0,
- int fpsr = 0)
+ protected void SetContext(ulong x0 = 0,
+ ulong x1 = 0,
+ ulong x2 = 0,
+ ulong x3 = 0,
+ ulong x31 = 0,
+ V128 v0 = default,
+ V128 v1 = default,
+ V128 v2 = default,
+ V128 v3 = default,
+ V128 v4 = default,
+ V128 v5 = default,
+ V128 v30 = default,
+ V128 v31 = default,
+ bool overflow = false,
+ bool carry = false,
+ bool zero = false,
+ bool negative = false,
+ int fpcr = 0,
+ int fpsr = 0)
{
- _context.SetX(0, x0);
- _context.SetX(1, x1);
- _context.SetX(2, x2);
- _context.SetX(3, x3);
+ _context.SetX(0, x0);
+ _context.SetX(1, x1);
+ _context.SetX(2, x2);
+ _context.SetX(3, x3);
_context.SetX(31, x31);
- _context.SetV(0, v0);
- _context.SetV(1, v1);
- _context.SetV(2, v2);
- _context.SetV(3, v3);
- _context.SetV(4, v4);
- _context.SetV(5, v5);
+ _context.SetV(0, v0);
+ _context.SetV(1, v1);
+ _context.SetV(2, v2);
+ _context.SetV(3, v3);
+ _context.SetV(4, v4);
+ _context.SetV(5, v5);
_context.SetV(30, v30);
_context.SetV(31, v31);
@@ -156,20 +158,20 @@ namespace Ryujinx.Tests.Cpu
_unicornEmu.X[1] = x1;
_unicornEmu.X[2] = x2;
_unicornEmu.X[3] = x3;
- _unicornEmu.SP = x31;
-
- _unicornEmu.Q[0] = V128ToSimdValue(v0);
- _unicornEmu.Q[1] = V128ToSimdValue(v1);
- _unicornEmu.Q[2] = V128ToSimdValue(v2);
- _unicornEmu.Q[3] = V128ToSimdValue(v3);
- _unicornEmu.Q[4] = V128ToSimdValue(v4);
- _unicornEmu.Q[5] = V128ToSimdValue(v5);
+ _unicornEmu.SP = x31;
+
+ _unicornEmu.Q[0] = V128ToSimdValue(v0);
+ _unicornEmu.Q[1] = V128ToSimdValue(v1);
+ _unicornEmu.Q[2] = V128ToSimdValue(v2);
+ _unicornEmu.Q[3] = V128ToSimdValue(v3);
+ _unicornEmu.Q[4] = V128ToSimdValue(v4);
+ _unicornEmu.Q[5] = V128ToSimdValue(v5);
_unicornEmu.Q[30] = V128ToSimdValue(v30);
_unicornEmu.Q[31] = V128ToSimdValue(v31);
_unicornEmu.OverflowFlag = overflow;
- _unicornEmu.CarryFlag = carry;
- _unicornEmu.ZeroFlag = zero;
+ _unicornEmu.CarryFlag = carry;
+ _unicornEmu.ZeroFlag = zero;
_unicornEmu.NegativeFlag = negative;
_unicornEmu.Fpcr = fpcr;
@@ -186,34 +188,34 @@ namespace Ryujinx.Tests.Cpu
}
}
- protected ExecutionContext SingleOpcode(uint opcode,
- ulong x0 = 0,
- ulong x1 = 0,
- ulong x2 = 0,
- ulong x3 = 0,
- ulong x31 = 0,
- V128 v0 = default,
- V128 v1 = default,
- V128 v2 = default,
- V128 v3 = default,
- V128 v4 = default,
- V128 v5 = default,
- V128 v30 = default,
- V128 v31 = default,
- bool overflow = false,
- bool carry = false,
- bool zero = false,
- bool negative = false,
- int fpcr = 0,
- int fpsr = 0,
- bool runUnicorn = true)
+ protected ExecutionContext SingleOpcode(uint opcode,
+ ulong x0 = 0,
+ ulong x1 = 0,
+ ulong x2 = 0,
+ ulong x3 = 0,
+ ulong x31 = 0,
+ V128 v0 = default,
+ V128 v1 = default,
+ V128 v2 = default,
+ V128 v3 = default,
+ V128 v4 = default,
+ V128 v5 = default,
+ V128 v30 = default,
+ V128 v31 = default,
+ bool overflow = false,
+ bool carry = false,
+ bool zero = false,
+ bool negative = false,
+ int fpcr = 0,
+ int fpsr = 0,
+ bool runUnicorn = true)
{
- if (Ignore_FpcrFz)
+ if (_ignoreFpcrFz)
{
fpcr &= ~(1 << (int)Fpcr.Fz);
}
- if (Ignore_FpcrDn)
+ if (_ignoreFpcrDn)
{
fpcr &= ~(1 << (int)Fpcr.Dn);
}
@@ -254,8 +256,8 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Round towards Minus Infinity mode.</summary>
Rm,
/// <summary>Round towards Zero mode.</summary>
- Rz
- };
+ Rz,
+ }
/// <summary>Floating-point Control Register.</summary>
protected enum Fpcr
@@ -263,15 +265,16 @@ namespace Ryujinx.Tests.Cpu
/// <summary>Rounding Mode control field.</summary>
RMode = 22,
/// <summary>Flush-to-zero mode control bit.</summary>
- Fz = 24,
+ Fz = 24,
/// <summary>Default NaN mode control bit.</summary>
- Dn = 25,
+ Dn = 25,
/// <summary>Alternative half-precision control bit.</summary>
- Ahp = 26
+ Ahp = 26,
}
/// <summary>Floating-point Status Register.</summary>
- [Flags] protected enum Fpsr
+ [Flags]
+ protected enum Fpsr
{
None = 0,
@@ -289,10 +292,11 @@ namespace Ryujinx.Tests.Cpu
Idc = 1 << 7,
/// <summary>Cumulative saturation bit.</summary>
- Qc = 1 << 27
+ Qc = 1 << 27,
}
- [Flags] protected enum FpSkips
+ [Flags]
+ protected enum FpSkips
{
None = 0,
@@ -300,7 +304,7 @@ namespace Ryujinx.Tests.Cpu
IfNaND = 2,
IfUnderflow = 4,
- IfOverflow = 8
+ IfOverflow = 8,
}
protected enum FpTolerances
@@ -308,15 +312,15 @@ namespace Ryujinx.Tests.Cpu
None,
UpToOneUlpsS,
- UpToOneUlpsD
+ UpToOneUlpsD,
}
protected void CompareAgainstUnicorn(
- Fpsr fpsrMask = Fpsr.None,
- FpSkips fpSkips = FpSkips.None,
+ Fpsr fpsrMask = Fpsr.None,
+ FpSkips fpSkips = FpSkips.None,
FpTolerances fpTolerances = FpTolerances.None)
{
- if (IgnoreAllExcept_FpsrQc)
+ if (_ignoreAllExceptFpsrQc)
{
fpsrMask &= Fpsr.Qc;
}
@@ -326,6 +330,7 @@ namespace Ryujinx.Tests.Cpu
ManageFpSkips(fpSkips);
}
+#pragma warning disable IDE0055 // Disable formatting
Assert.That(_context.GetX(0), Is.EqualTo(_unicornEmu.X[0]), "X0");
Assert.That(_context.GetX(1), Is.EqualTo(_unicornEmu.X[1]), "X1");
Assert.That(_context.GetX(2), Is.EqualTo(_unicornEmu.X[2]), "X2");
@@ -358,6 +363,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(_context.GetX(29), Is.EqualTo(_unicornEmu.X[29]));
Assert.That(_context.GetX(30), Is.EqualTo(_unicornEmu.X[30]));
Assert.That(_context.GetX(31), Is.EqualTo(_unicornEmu.SP), "X31");
+#pragma warning restore IDE0055
if (fpTolerances == FpTolerances.None)
{
@@ -367,6 +373,8 @@ namespace Ryujinx.Tests.Cpu
{
ManageFpTolerances(fpTolerances);
}
+
+#pragma warning disable IDE0055 // Disable formatting
Assert.That(V128ToSimdValue(_context.GetV(1)), Is.EqualTo(_unicornEmu.Q[1]), "V1");
Assert.That(V128ToSimdValue(_context.GetV(2)), Is.EqualTo(_unicornEmu.Q[2]), "V2");
Assert.That(V128ToSimdValue(_context.GetV(3)), Is.EqualTo(_unicornEmu.Q[3]), "V3");
@@ -409,6 +417,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr), "Fpcr");
Assert.That((int)_context.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask), "Fpsr");
+#pragma warning restore IDE0055
if (_usingMemory)
{
@@ -455,7 +464,7 @@ namespace Ryujinx.Tests.Cpu
private void ManageFpTolerances(FpTolerances fpTolerances)
{
- bool IsNormalOrSubnormalS(float f) => float.IsNormal(f) || float.IsSubnormal(f);
+ bool IsNormalOrSubnormalS(float f) => float.IsNormal(f) || float.IsSubnormal(f);
bool IsNormalOrSubnormalD(double d) => double.IsNormal(d) || double.IsSubnormal(d);
if (!Is.EqualTo(_unicornEmu.Q[0]).ApplyTo(V128ToSimdValue(_context.GetV(0))).IsSuccess)
@@ -467,13 +476,13 @@ namespace Ryujinx.Tests.Cpu
{
Assert.Multiple(() =>
{
- Assert.That (_context.GetV(0).Extract<float>(0),
+ Assert.That(_context.GetV(0).Extract<float>(0),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(0)).Within(1).Ulps, "V0[0]");
- Assert.That (_context.GetV(0).Extract<float>(1),
+ Assert.That(_context.GetV(0).Extract<float>(1),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(1)).Within(1).Ulps, "V0[1]");
- Assert.That (_context.GetV(0).Extract<float>(2),
+ Assert.That(_context.GetV(0).Extract<float>(2),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(2)).Within(1).Ulps, "V0[2]");
- Assert.That (_context.GetV(0).Extract<float>(3),
+ Assert.That(_context.GetV(0).Extract<float>(3),
Is.EqualTo(_unicornEmu.Q[0].GetFloat(3)).Within(1).Ulps, "V0[3]");
});
@@ -492,9 +501,9 @@ namespace Ryujinx.Tests.Cpu
{
Assert.Multiple(() =>
{
- Assert.That (_context.GetV(0).Extract<double>(0),
+ Assert.That(_context.GetV(0).Extract<double>(0),
Is.EqualTo(_unicornEmu.Q[0].GetDouble(0)).Within(1).Ulps, "V0[0]");
- Assert.That (_context.GetV(0).Extract<double>(1),
+ Assert.That(_context.GetV(0).Extract<double>(1),
Is.EqualTo(_unicornEmu.Q[0].GetDouble(1)).Within(1).Ulps, "V0[1]");
});
@@ -513,13 +522,13 @@ namespace Ryujinx.Tests.Cpu
return new SimdValue(value.Extract<ulong>(0), value.Extract<ulong>(1));
}
- protected static V128 MakeVectorScalar(float value) => new V128(value);
- protected static V128 MakeVectorScalar(double value) => new V128(value);
+ protected static V128 MakeVectorScalar(float value) => new(value);
+ protected static V128 MakeVectorScalar(double value) => new(value);
- protected static V128 MakeVectorE0(ulong e0) => new V128(e0, 0);
- protected static V128 MakeVectorE1(ulong e1) => new V128(0, e1);
+ protected static V128 MakeVectorE0(ulong e0) => new(e0, 0);
+ protected static V128 MakeVectorE1(ulong e1) => new(0, e1);
- protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new V128(e0, e1);
+ protected static V128 MakeVectorE0E1(ulong e0, ulong e1) => new(e0, e1);
protected static ulong GetVectorE0(V128 vector) => vector.Extract<ulong>(0);
protected static ulong GetVectorE1(V128 vector) => vector.Extract<ulong>(1);
@@ -528,8 +537,9 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
- do rnd = TestContext.CurrentContext.Random.NextUShort();
- while (( rnd & 0x7C00u) == 0u ||
+ do
+ rnd = TestContext.CurrentContext.Random.NextUShort();
+ while ((rnd & 0x7C00u) == 0u ||
(~rnd & 0x7C00u) == 0u);
return (ushort)rnd;
@@ -539,7 +549,8 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
- do rnd = TestContext.CurrentContext.Random.NextUShort();
+ do
+ rnd = TestContext.CurrentContext.Random.NextUShort();
while ((rnd & 0x03FFu) == 0u);
return (ushort)(rnd & 0x83FFu);
@@ -549,8 +560,9 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
- do rnd = TestContext.CurrentContext.Random.NextUInt();
- while (( rnd & 0x7F800000u) == 0u ||
+ do
+ rnd = TestContext.CurrentContext.Random.NextUInt();
+ while ((rnd & 0x7F800000u) == 0u ||
(~rnd & 0x7F800000u) == 0u);
return rnd;
@@ -560,7 +572,8 @@ namespace Ryujinx.Tests.Cpu
{
uint rnd;
- do rnd = TestContext.CurrentContext.Random.NextUInt();
+ do
+ rnd = TestContext.CurrentContext.Random.NextUInt();
while ((rnd & 0x007FFFFFu) == 0u);
return rnd & 0x807FFFFFu;
@@ -570,8 +583,9 @@ namespace Ryujinx.Tests.Cpu
{
ulong rnd;
- do rnd = TestContext.CurrentContext.Random.NextULong();
- while (( rnd & 0x7FF0000000000000ul) == 0ul ||
+ do
+ rnd = TestContext.CurrentContext.Random.NextULong();
+ while ((rnd & 0x7FF0000000000000ul) == 0ul ||
(~rnd & 0x7FF0000000000000ul) == 0ul);
return rnd;
@@ -581,10 +595,11 @@ namespace Ryujinx.Tests.Cpu
{
ulong rnd;
- do rnd = TestContext.CurrentContext.Random.NextULong();
+ do
+ rnd = TestContext.CurrentContext.Random.NextULong();
while ((rnd & 0x000FFFFFFFFFFFFFul) == 0ul);
return rnd & 0x800FFFFFFFFFFFFFul;
}
}
-} \ No newline at end of file
+}