diff --git a/src/Ryujinx.Tests/Cpu/CpuTestMisc.cs b/src/Ryujinx.Tests/Cpu/CpuTestMisc.cs index dc058ab91..c587ec414 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestMisc.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestMisc.cs @@ -1,5 +1,8 @@ -// #define Misc +#define Misc +using ARMeilleure.State; +using System; +using System.Collections.Generic; using Xunit; namespace Ryujinx.Tests.Cpu @@ -43,7 +46,7 @@ namespace Ryujinx.Tests.Cpu for (int cnt = 1; cnt <= RndCnt; cnt++) { - ulong grbg = TestContext.CurrentContext.Random.NextUInt(); + ulong grbg = Random.Shared.NextUInt(); ulong rnd1 = GenNormalS(); ulong rnd2 = GenSubnormalS(); @@ -60,15 +63,44 @@ namespace Ryujinx.Tests.Cpu private static readonly bool _noNaNs = false; #region "AluImm & Csel" - [Test, Pairwise] - public void Adds_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, - 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn, - [Values(0u, 4095u)] uint imm, - [Values(0b00u, 0b01u)] uint shift, // - [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // + private static readonly ulong[] _testDataXn = + { + 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, + 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul, + }; + + private static readonly uint[] _testDataWn = + { + 0x00000000u, 0x7FFFFFFFu, + 0x80000000u, 0xFFFFFFFFu, + }; + + private static readonly uint[] _testDataImm = + { + 0u, 4095u, + }; + + private static readonly uint[] _testDataShift = + { + 0b00u, 0b01u, + }; + + private static readonly uint[] _testDataCond = + { + 0b0000u, 0b0001u, 0b0010u, 0b0011u, // + }; + + public static readonly MatrixTheoryData TestMatrixData_64bit = new(_testDataXn, _testDataImm, _testDataShift, _testDataCond); + public static readonly MatrixTheoryData TestMatrixData_32bit = new(_testDataWn, _testDataImm, _testDataShift, _testDataCond); + + public static readonly RangeTheoryData TestRangeData = new(0u, 92u, 1u); + + [Theory] + [MemberData(nameof(TestMatrixData_64bit))] + public void Adds_Csinc_64bit(ulong xn, uint imm, uint shift, uint cond) { uint opCmn = 0xB100001F; // ADDS X31, X0, #0, LSL #0 -> CMN X0, #0, LSL #0 uint opCset = 0x9A9F07E0; // CSINC X0, X31, X31, EQ -> CSET X0, NE @@ -85,15 +117,9 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise] - public void Adds_Csinc_32bit([Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] uint wn, - [Values(0u, 4095u)] uint imm, - [Values(0b00u, 0b01u)] uint shift, // - [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // + [Theory] + [MemberData(nameof(TestMatrixData_32bit))] + public void Adds_Csinc_32bit(uint wn, uint imm, uint shift, uint cond) { uint opCmn = 0x3100001F; // ADDS W31, W0, #0, LSL #0 -> CMN W0, #0, LSL #0 uint opCset = 0x1A9F07E0; // CSINC W0, W31, W31, EQ -> CSET W0, NE @@ -110,15 +136,9 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise] - public void Subs_Csinc_64bit([Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, - 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] ulong xn, - [Values(0u, 4095u)] uint imm, - [Values(0b00u, 0b01u)] uint shift, // - [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // + [Theory] + [MemberData(nameof(TestMatrixData_64bit))] + public void Subs_Csinc_64bit(ulong xn, uint imm, uint shift, uint cond) { uint opCmp = 0xF100001F; // SUBS X31, X0, #0, LSL #0 -> CMP X0, #0, LSL #0 uint opCset = 0x9A9F07E0; // CSINC X0, X31, X31, EQ -> CSET X0, NE @@ -135,15 +155,9 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise] - public void Subs_Csinc_32bit([Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] uint wn, - [Values(0u, 4095u)] uint imm, - [Values(0b00u, 0b01u)] uint shift, // - [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // + [Theory] + [MemberData(nameof(TestMatrixData_32bit))] + public void Subs_Csinc_32bit(uint wn, uint imm, uint shift, uint cond) { uint opCmp = 0x7100001F; // SUBS W31, W0, #0, LSL #0 -> CMP W0, #0, LSL #0 uint opCset = 0x1A9F07E0; // CSINC W0, W31, W31, EQ -> CSET W0, NE @@ -162,9 +176,9 @@ namespace Ryujinx.Tests.Cpu #endregion // Roots. - [Explicit] - [TestCase(0xFFFFFFFDu)] - [TestCase(0x00000005u)] + [Theory] + [InlineData(0xFFFFFFFDu)] + [InlineData(0x00000005u)] public void Misc1(uint a) { // ((a + 3) * (a - 5)) / ((a + 5) * (a - 3)) = 0 @@ -191,29 +205,29 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.That(GetContext().GetX(0), Is.Zero); + Assert.Equal(0ul, GetContext().GetX(0)); } // 18 integer solutions. - [Explicit] - [TestCase(-20f, -5f)] - [TestCase(-12f, -6f)] - [TestCase(-12f, 3f)] - [TestCase(-8f, -8f)] - [TestCase(-6f, -12f)] - [TestCase(-5f, -20f)] - [TestCase(-4f, 2f)] - [TestCase(-3f, 12f)] - [TestCase(-2f, 4f)] - [TestCase(2f, -4f)] - [TestCase(3f, -12f)] - [TestCase(4f, -2f)] - [TestCase(5f, 20f)] - [TestCase(6f, 12f)] - [TestCase(8f, 8f)] - [TestCase(12f, -3f)] - [TestCase(12f, 6f)] - [TestCase(20f, 5f)] + [Theory] + [InlineData(-20f, -5f)] + [InlineData(-12f, -6f)] + [InlineData(-12f, 3f)] + [InlineData(-8f, -8f)] + [InlineData(-6f, -12f)] + [InlineData(-5f, -20f)] + [InlineData(-4f, 2f)] + [InlineData(-3f, 12f)] + [InlineData(-2f, 4f)] + [InlineData(2f, -4f)] + [InlineData(3f, -12f)] + [InlineData(4f, -2f)] + [InlineData(5f, 20f)] + [InlineData(6f, 12f)] + [InlineData(8f, 8f)] + [InlineData(12f, -3f)] + [InlineData(12f, 6f)] + [InlineData(20f, 5f)] public void Misc2(float a, float b) { // 1 / ((1 / a + 1 / b) ^ 2) = 16 @@ -238,29 +252,29 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.That(GetContext().GetV(0).As(), Is.EqualTo(16f)); + Assert.Equal(16f, GetContext().GetV(0).As()); } // 18 integer solutions. - [Explicit] - [TestCase(-20d, -5d)] - [TestCase(-12d, -6d)] - [TestCase(-12d, 3d)] - [TestCase(-8d, -8d)] - [TestCase(-6d, -12d)] - [TestCase(-5d, -20d)] - [TestCase(-4d, 2d)] - [TestCase(-3d, 12d)] - [TestCase(-2d, 4d)] - [TestCase(2d, -4d)] - [TestCase(3d, -12d)] - [TestCase(4d, -2d)] - [TestCase(5d, 20d)] - [TestCase(6d, 12d)] - [TestCase(8d, 8d)] - [TestCase(12d, -3d)] - [TestCase(12d, 6d)] - [TestCase(20d, 5d)] + [Theory] + [InlineData(-20d, -5d)] + [InlineData(-12d, -6d)] + [InlineData(-12d, 3d)] + [InlineData(-8d, -8d)] + [InlineData(-6d, -12d)] + [InlineData(-5d, -20d)] + [InlineData(-4d, 2d)] + [InlineData(-3d, 12d)] + [InlineData(-2d, 4d)] + [InlineData(2d, -4d)] + [InlineData(3d, -12d)] + [InlineData(4d, -2d)] + [InlineData(5d, 20d)] + [InlineData(6d, 12d)] + [InlineData(8d, 8d)] + [InlineData(12d, -3d)] + [InlineData(12d, 6d)] + [InlineData(20d, 5d)] public void Misc3(double a, double b) { // 1 / ((1 / a + 1 / b) ^ 2) = 16 @@ -285,11 +299,12 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.That(GetContext().GetV(0).As(), Is.EqualTo(16d)); + Assert.Equal(16d, GetContext().GetV(0).As()); } - [Test, Ignore("The Tester supports only one return point.")] - public void MiscF([Range(0u, 92u, 1u)] uint a) + [Theory(Skip = "The Tester supports only one return point.")] + [MemberData(nameof(TestRangeData))] + public void MiscF(uint a) { static ulong Fn(uint n) { @@ -352,11 +367,11 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.That(GetContext().GetX(0), Is.EqualTo(Fn(a))); + Assert.Equal(Fn(a), GetContext().GetX(0)); } - [Explicit] - [Test] + // This test used to be skipped unless explicitly executed + [Fact] public void MiscR() { const ulong Result = 5; @@ -374,7 +389,7 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.That(GetContext().GetX(0), Is.EqualTo(Result)); + Assert.Equal(Result, GetContext().GetX(0)); Reset(); @@ -391,57 +406,67 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.That(GetContext().GetX(0), Is.EqualTo(Result)); + Assert.Equal(Result, GetContext().GetX(0)); } - [Explicit] - [TestCase(0ul)] - [TestCase(1ul)] - [TestCase(2ul)] - [TestCase(42ul)] + // This test used to be skipped unless explicitly executed + [Theory] + [InlineData(0ul)] + [InlineData(1ul)] + [InlineData(2ul)] + [InlineData(42ul)] public void SanityCheck(ulong a) { uint opcode = 0xD503201F; // NOP ExecutionContext context = SingleOpcode(opcode, x0: a); - Assert.That(context.GetX(0), Is.EqualTo(a)); + Assert.Equal(a, context.GetX(0)); } - [Explicit] - [Test, Pairwise] - public void Misc4([ValueSource(nameof(_1S_F_))] ulong a, - [ValueSource(nameof(_1S_F_))] ulong b, - [ValueSource(nameof(_1S_F_))] ulong c, - [Values(0ul, 1ul, 2ul, 3ul)] ulong displacement) + private static readonly ulong[] _testDataMisc4Displacement = { - if (!BitConverter.IsLittleEndian) - { - Assert.Ignore(); - } + 0ul, 1ul, 2ul, 3ul, + }; + + public static readonly MatrixTheoryData TestDataMisc4 = new(_1S_F_(), _1S_F_(), _1S_F_(), _testDataMisc4Displacement); + + // This test used to be skipped unless explicitly executed + [SkippableTheory] + [MemberData(nameof(TestDataMisc4))] + public void Misc4(ulong a, ulong b, ulong c, ulong displacement) + { + Skip.IfNot(BitConverter.IsLittleEndian); + + byte[] data = new byte[1]; for (ulong gapOffset = 0; gapOffset < displacement; gapOffset++) { - SetWorkingMemory(gapOffset, TestContext.CurrentContext.Random.NextByte()); + Random.Shared.NextBytes(data); + SetWorkingMemory(gapOffset, data[0]); } SetWorkingMemory(0x0 + displacement, BitConverter.GetBytes((uint)b)); SetWorkingMemory(0x4 + displacement, BitConverter.GetBytes((uint)c)); - SetWorkingMemory(0x8 + displacement, TestContext.CurrentContext.Random.NextByte()); - SetWorkingMemory(0x9 + displacement, TestContext.CurrentContext.Random.NextByte()); - SetWorkingMemory(0xA + displacement, TestContext.CurrentContext.Random.NextByte()); - SetWorkingMemory(0xB + displacement, TestContext.CurrentContext.Random.NextByte()); + Random.Shared.NextBytes(data); + SetWorkingMemory(0x8 + displacement, data[0]); + Random.Shared.NextBytes(data); + SetWorkingMemory(0x9 + displacement, data[0]); + Random.Shared.NextBytes(data); + SetWorkingMemory(0xA + displacement, data[0]); + Random.Shared.NextBytes(data); + SetWorkingMemory(0xB + displacement, data[0]); SetContext( x0: DataBaseAddress + displacement, - v0: MakeVectorE0E1(a, TestContext.CurrentContext.Random.NextULong()), - v1: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()), - v2: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()), - overflow: TestContext.CurrentContext.Random.NextBool(), - carry: TestContext.CurrentContext.Random.NextBool(), - zero: TestContext.CurrentContext.Random.NextBool(), - negative: TestContext.CurrentContext.Random.NextBool()); + v0: MakeVectorE0E1(a, Random.Shared.NextULong()), + v1: MakeVectorE0E1(Random.Shared.NextULong(), Random.Shared.NextULong()), + v2: MakeVectorE0E1(Random.Shared.NextULong(), Random.Shared.NextULong()), + overflow: Random.Shared.NextBool(), + carry: Random.Shared.NextBool(), + zero: Random.Shared.NextBool(), + negative: Random.Shared.NextBool()); Opcode(0xBD400001); // LDR S1, [X0,#0] Opcode(0xBD400402); // LDR S2, [X0,#4] @@ -455,17 +480,20 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Explicit] - [Test] - public void Misc5([ValueSource(nameof(_1S_F_))] ulong a) + public static readonly EnumerableTheoryData TestDataMisc5 = new(_1S_F_()); + + // This test used to be skipped unless explicitly executed + [Theory] + [MemberData(nameof(TestDataMisc5))] + public void Misc5(ulong a) { SetContext( - v0: MakeVectorE0E1(a, TestContext.CurrentContext.Random.NextULong()), - v1: MakeVectorE0E1(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()), - overflow: TestContext.CurrentContext.Random.NextBool(), - carry: TestContext.CurrentContext.Random.NextBool(), - zero: TestContext.CurrentContext.Random.NextBool(), - negative: TestContext.CurrentContext.Random.NextBool()); + v0: MakeVectorE0E1(a, Random.Shared.NextULong()), + v1: MakeVectorE0E1(Random.Shared.NextULong(), Random.Shared.NextULong()), + overflow: Random.Shared.NextBool(), + carry: Random.Shared.NextBool(), + zero: Random.Shared.NextBool(), + negative: Random.Shared.NextBool()); Opcode(0x1E202008); // FCMP S0, #0.0 Opcode(0x1E2E1001); // FMOV S1, #1.0 diff --git a/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs b/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs index 23c3791b7..b0b7285d5 100644 --- a/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs +++ b/src/Ryujinx.Tests/Cpu/CpuTestMisc32.cs @@ -1,5 +1,8 @@ -// #define Misc32 +#define Misc32 +using ARMeilleure.State; +using System; +using System.Collections.Generic; using Xunit; namespace Ryujinx.Tests.Cpu @@ -43,7 +46,7 @@ namespace Ryujinx.Tests.Cpu for (int cnt = 1; cnt <= RndCnt; cnt++) { - ulong grbg = TestContext.CurrentContext.Random.NextUInt(); + ulong grbg = Random.Shared.NextUInt(); ulong rnd1 = GenNormalS(); ulong rnd2 = GenSubnormalS(); @@ -59,28 +62,33 @@ namespace Ryujinx.Tests.Cpu private static readonly bool _noInfs = false; private static readonly bool _noNaNs = false; - [Test, Pairwise] - public void Vmsr_Vcmp_Vmrs([ValueSource(nameof(_1S_F_))] ulong a, - [ValueSource(nameof(_1S_F_))] ulong b, - [Values] bool mode1, - [Values] bool mode2, - [Values] bool mode3) + private static readonly bool[] _testData_bool = + { + false, + true, + }; + + public static readonly MatrixTheoryData TestData = new(_1S_F_(), _1S_F_(), _testData_bool, _testData_bool, _testData_bool); + + [Theory] + [MemberData(nameof(TestData))] + public void Vmsr_Vcmp_Vmrs(ulong a, ulong b, bool mode1, bool mode2, bool mode3) { V128 v4 = MakeVectorE0(a); V128 v5 = MakeVectorE0(b); uint r0 = mode1 - ? TestContext.CurrentContext.Random.NextUInt(0xf) << 28 - : TestContext.CurrentContext.Random.NextUInt(); + ? Random.Shared.NextUInt(0xf) << 28 + : Random.Shared.NextUInt(); - bool v = mode3 && TestContext.CurrentContext.Random.NextBool(); - bool c = mode3 && TestContext.CurrentContext.Random.NextBool(); - bool z = mode3 && TestContext.CurrentContext.Random.NextBool(); - bool n = mode3 && TestContext.CurrentContext.Random.NextBool(); + bool v = mode3 && Random.Shared.NextBool(); + bool c = mode3 && Random.Shared.NextBool(); + bool z = mode3 && Random.Shared.NextBool(); + bool n = mode3 && Random.Shared.NextBool(); int fpscr = mode1 - ? (int)TestContext.CurrentContext.Random.NextUInt() - : (int)TestContext.CurrentContext.Random.NextUInt(0xf) << 28; + ? (int)Random.Shared.NextUInt() + : (int)Random.Shared.NextUInt(0xf) << 28; SetContext(r0: r0, v4: v4, v5: v5, overflow: v, carry: c, zero: z, negative: n, fpscr: fpscr);