From ea6fc47fac84ef57beb762945c0c6302d1c7858b Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 13 Feb 2020 22:26:09 +0000 Subject: [PATCH] Address Feedback from LDj3SNuD Opcode table reordered to have alphabetical sorting within groups, Vmaxnm and Vminnm have split names to be less ambiguous, SoftFloat nits, Test nits and Test simplification with ValueSource. --- ARMeilleure/Decoders/OpCodeSimdHelper.cs | 17 -- ARMeilleure/Decoders/OpCodeTable.cs | 55 ++--- ARMeilleure/Instructions/InstName.cs | 3 +- ARMeilleure/Instructions/SoftFloat.cs | 25 +-- Ryujinx.Tests/Cpu/CpuTestAlu32.cs | 78 ++----- Ryujinx.Tests/Cpu/CpuTestAluRs32.cs | 243 +++++----------------- Ryujinx.Tests/Cpu/CpuTestBf32.cs | 16 +- Ryujinx.Tests/Cpu/CpuTestSimdLogical32.cs | 101 +++------ Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs | 4 +- Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs | 18 +- Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs | 15 +- 11 files changed, 168 insertions(+), 407 deletions(-) diff --git a/ARMeilleure/Decoders/OpCodeSimdHelper.cs b/ARMeilleure/Decoders/OpCodeSimdHelper.cs index 086e4b9c29..3e5a7f65b9 100644 --- a/ARMeilleure/Decoders/OpCodeSimdHelper.cs +++ b/ARMeilleure/Decoders/OpCodeSimdHelper.cs @@ -73,23 +73,6 @@ return (imm, size); } - public static long VFPExpandImm(long imm, int n) - { - int e = (n == 16) ? 5 : ((n == 32) ? 8 : 11); - int f = (n) * 8 - e - 1; - long sign = (imm & 0x80) << (n - 8); - - var bit6 = (imm >> 6) & 0x1; - - long exp = ((imm >> 4) & 0x3); - if (bit6 == 1) exp |= ShlOnes(0, e - 3) << 2; - if (bit6 == 0) exp |= (long)1 << (e - 1); - - long frac = (imm & 0xf) << (f - 4); - - return sign | (exp << f) | frac; - } - private static long ShlOnes(long value, int shift) { if (shift != 0) diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 621c732eaf..d03f6a27f0 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -741,32 +741,32 @@ namespace ARMeilleure.Decoders SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, typeof(OpCode32AluUx)); SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx)); - // FP & SIMD (AArch32) + // FP & SIMD SetA32("<<<<11101x110000xxxx10xx11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, typeof(OpCode32SimdRegS)); SetA32("111100111x11xx01xxxx0x110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, typeof(OpCode32SimdReg)); + SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg)); SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, typeof(OpCode32SimdRegS)); SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, typeof(OpCode32SimdReg)); - SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg)); SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, typeof(OpCode32SimdBinary)); SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, typeof(OpCode32SimdBinary)); - SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, typeof(OpCode32SimdBinary)); SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary)); + SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, typeof(OpCode32SimdBinary)); - SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ)); - SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg)); SetA32("111100110x<>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // The many FP32 to int encodings (fp). + SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, typeof(OpCode32SimdCmpZ)); // FP and integer, vector. SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP)); @@ -812,19 +812,20 @@ namespace ARMeilleure.Decoders SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, typeof(OpCode32SimdMemImm)); - SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, typeof(OpCode32SimdReg)); SetA32("1111001x0x<>x0x0xxxx", InstName.VMMmn, InstEmit32.VmaxNm_S, typeof(OpCode32SimdRegS)); - SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.VMMmn, InstEmit32.VminNm_S, typeof(OpCode32SimdRegS)); - SetA32("111100110xxxxxxxxxxx1111xxx1xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg)); + SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.VmaxNm_S, typeof(OpCode32SimdRegS)); + SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg)); + SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.VminNm_S, typeof(OpCode32SimdRegS)); + SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg)); + SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, typeof(OpCode32SimdReg)); SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, typeof(OpCode32SimdRegS)); SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, typeof(OpCode32SimdReg)); - SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, typeof(OpCode32SimdReg)); SetA32("1111001x1x<>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShImm)); + SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, typeof(OpCode32SimdReg)); SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, typeof(OpCode32SimdShImm)); SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, typeof(OpCode32SimdShImm)); @@ -905,22 +906,22 @@ namespace ARMeilleure.Decoders SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult)); SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult)); - SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, typeof(OpCode32SimdMemImm)); - SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, typeof(OpCode32SimdS)); SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, typeof(OpCode32SimdSqrte)); SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, typeof(OpCode32SimdReg)); SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, typeof(OpCode32SimdSqrte)); SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, typeof(OpCode32SimdReg)); + SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, typeof(OpCode32SimdS)); + SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, typeof(OpCode32SimdMemImm)); + SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, typeof(OpCode32SimdReg)); SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, typeof(OpCode32SimdRegS)); SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, typeof(OpCode32SimdReg)); - SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, typeof(OpCode32SimdReg)); SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, typeof(OpCode32SimdTbl)); SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, typeof(OpCode32SimdCmpZ)); - #endregion +#endregion FillFastLookupTable(_instA32FastLookup, _allInstA32); FillFastLookupTable(_instT32FastLookup, _allInstT32); diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index adf8bb9fc7..0c2dd18d49 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -544,10 +544,11 @@ namespace ARMeilleure.Instructions Vldm, Vldr, Vmax, + Vmaxnm, Vmin, + Vminnm, Vmla, Vmls, - VMMmn, Vmov, Vmovn, Vmrs, diff --git a/ARMeilleure/Instructions/SoftFloat.cs b/ARMeilleure/Instructions/SoftFloat.cs index 6cca80da75..aa3df0696a 100644 --- a/ARMeilleure/Instructions/SoftFloat.cs +++ b/ARMeilleure/Instructions/SoftFloat.cs @@ -119,10 +119,9 @@ namespace ARMeilleure.Instructions return result; } - private static float _DefaultNaN = BitConverter.Int32BitsToSingle(0x7fc00000); private static float FPDefaultNaN() { - return _DefaultNaN; + return BitConverter.Int32BitsToSingle(0x7fc00000); } private static float FPInfinity(bool sign) @@ -1343,6 +1342,7 @@ namespace ARMeilleure.Instructions bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; float product; + if ((inf1 && zero2) || (zero1 && inf2)) { product = FPZero(false); @@ -1506,6 +1506,7 @@ namespace ARMeilleure.Instructions { bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero; bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; + if (inf1 && inf2 && sign1 == sign2) { result = FPDefaultNaN(); @@ -1527,6 +1528,7 @@ namespace ARMeilleure.Instructions else { result = (value1 - value2) / 2.0f; + if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result)) { context.Fpsr |= FPSR.Ufc; @@ -1555,6 +1557,7 @@ namespace ARMeilleure.Instructions bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; float product; + if ((inf1 && zero2) || (zero1 && inf2)) { product = FPZero(false); @@ -1563,9 +1566,8 @@ namespace ARMeilleure.Instructions { product = FPMulFpscr(value1, value2, true); } - - float three = FPThree(false); - result = FPHalvedSub(three, product, context, fpcr); + + result = FPHalvedSub(FPThree(false), product, context, fpcr); } return result; @@ -1708,11 +1710,9 @@ namespace ARMeilleure.Instructions return result; } - private static float _DefaultNaN = BitConverter.Int32BitsToSingle(0x7fc00000); - private static float FPDefaultNaN() { - return _DefaultNaN; + return BitConverter.Int32BitsToSingle(0x7fc00000); } private static float FPInfinity(bool sign) @@ -2635,6 +2635,7 @@ namespace ARMeilleure.Instructions bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; double product; + if ((inf1 && zero2) || (zero1 && inf2)) { product = FPZero(false); @@ -2819,6 +2820,7 @@ namespace ARMeilleure.Instructions else { result = (value1 - value2) / 2.0; + if ((fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result)) { context.Fpsr |= FPSR.Ufc; @@ -2847,6 +2849,7 @@ namespace ARMeilleure.Instructions bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; double product; + if ((inf1 && zero2) || (zero1 && inf2)) { product = FPZero(false); @@ -2856,8 +2859,7 @@ namespace ARMeilleure.Instructions product = FPMulFpscr(value1, value2, true); } - double three = FPThree(false); - result = FPHalvedSub(three, product, context, fpcr); + result = FPHalvedSub(FPThree(false), product, context, fpcr); } return result; @@ -3000,10 +3002,9 @@ namespace ARMeilleure.Instructions return result; } - private static double _DefaultNaN = BitConverter.Int64BitsToDouble(0x7ff8000000000000); private static double FPDefaultNaN() { - return _DefaultNaN; + return BitConverter.Int64BitsToDouble(0x7ff8000000000000); } private static double FPInfinity(bool sign) diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs index 266ec9dd40..29663c746e 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs @@ -1,13 +1,27 @@ #define Alu32 + using NUnit.Framework; using System; namespace Ryujinx.Tests.Cpu { -#if Alu32 [Category("Alu32")] - class CpuTestAlu32 : CpuTest32 + public sealed class CpuTestAlu32 : CpuTest32 { +#if Alu32 +#region "ValueSource (Opcodes)" + private static uint[] _Lsr_Lsl_Asr_Ror_() + { + return new uint[] + { + 0xe1b00030u, // LSRS R0, R0, R0 + 0xe1b00010u, // LSLS R0, R0, R0 + 0xe1b00050u, // ASRS R0, R0, R0 + 0xe1b00070u // RORS R0, R0, R0 + }; + } +#endregion + private const int RndCnt = 2; [Test, Pairwise, Description("RBIT , ")] @@ -26,60 +40,12 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("LSRS {,} , ")] - public void Lsr([Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue, - [Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount) + [Test, Pairwise] + public void Lsr_Lsl_Asr_Ror([ValueSource("_Lsr_Lsl_Asr_Ror_")] uint opcode, + [Values(0x00000000u, 0x7FFFFFFFu, + 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue, + [Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount) { - uint opcode = 0xe1b00030u; // LSRS R0, R0, R0 - uint rd = 0; - uint rm = 1; - uint rs = 2; - opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8); - - SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("LSLS {,} , ")] - public void Lsl([Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue, - [Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount) - { - uint opcode = 0xe1b00010u; // LSLS R0, R0, R0 - uint rd = 0; - uint rm = 1; - uint rs = 2; - opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8); - - SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("ASRS {,} , ")] - public void Asr([Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue, - [Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount) - { - uint opcode = 0xe1b00050u; // ASRS R0, R0, R0 - uint rd = 0; - uint rm = 1; - uint rs = 2; - opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8); - - SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("RORS {,} , ")] - public void Ror([Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue, - [Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount) - { - uint opcode = 0xe1b00070u; // RORS R0, R0, R0 uint rd = 0; uint rm = 1; uint rs = 2; @@ -89,6 +55,6 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } +#endif } -#endif } diff --git a/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs b/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs index 0309dd8159..b4d3107654 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAluRs32.cs @@ -4,25 +4,50 @@ using NUnit.Framework; namespace Ryujinx.Tests.Cpu { - [Category("AluRs")] + [Category("AluRs32")] public sealed class CpuTestAluRs32 : CpuTest32 { #if AluRs32 - private const int RndCnt = 5; - private const int RndCntAmount = 50; - private const int RndCntLsb = 2; - - [Test, Pairwise, Description("ADC , , ")] - public void Adc([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values] bool carryIn) +#region "ValueSource (Opcodes)" + private static uint[] _Add_Adds_Rsb_Rsbs_() + { + return new uint[] + { + 0xe0800000u, // ADD R0, R0, R0, LSL #0 + 0xe0900000u, // ADDS R0, R0, R0, LSL #0 + 0xe0600000u, // RSB R0, R0, R0, LSL #0 + 0xe0700000u // RSBS R0, R0, R0, LSL #0 + }; + } + + private static uint[] _Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_() + { + return new uint[] + { + 0xe0a00000u, // ADC R0, R0, R0 + 0xe0b00000u, // ADCS R0, R0, R0 + 0xe0e00000u, // RSC R0, R0, R0 + 0xe0f00000u, // RSCS R0, R0, R0 + 0xe0c00000u, // SBC R0, R0, R0 + 0xe0d00000u // SBCS R0, R0, R0 + }; + } + #endregion + + private const int RndCnt = 2; + private const int RndCntAmount = 2; + + [Test, Pairwise] + public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource("_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_")] uint opcode, + [Values(0u, 13u)] uint rd, + [Values(1u, 13u)] uint rn, + [Values(2u, 13u)] uint rm, + [Values(0x00000000u, 0x7FFFFFFFu, + 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, + [Values(0x00000000u, 0x7FFFFFFFu, + 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, + [Values] bool carryIn) { - uint opcode = 0xe0a00000u; // ADC R0, R0, R0 opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); uint sp = TestContext.CurrentContext.Random.NextUInt(); @@ -32,38 +57,18 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("ADCS , , ")] - public void Adcs([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values] bool carryIn) + [Test, Pairwise] + public void Add_Adds_Rsb_Rsbs([ValueSource("_Add_Adds_Rsb_Rsbs_")] uint opcode, + [Values(0u, 13u)] uint rd, + [Values(1u, 13u)] uint rn, + [Values(2u, 13u)] uint rm, + [Values(0x00000000u, 0x7FFFFFFFu, + 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, + [Values(0x00000000u, 0x7FFFFFFFu, + 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, + [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // + [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount) { - uint opcode = 0xe0b00000u; // ADCS R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("ADD , , {, #}")] - public void Add([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // - [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount) - { - uint opcode = 0xe0800000u; // ADD R0, R0, R0, LSL #0 opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); opcode |= ((shift & 3) << 5) | ((amount & 31) << 7); @@ -73,152 +78,6 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - - [Test, Pairwise, Description("ADDS , , {, #}")] - public void Adds([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // - [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount) - { - uint opcode = 0xe0900000u; // ADDS R0, R0, R0, LSL #0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - opcode |= ((shift & 3) << 5) | ((amount & 31) << 7); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("RSB , , {, #}")] - public void Rsb([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // - [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount) - { - uint opcode = 0xe0600000u; // RSB R0, R0, R0, LSL #0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - opcode |= ((shift & 3) << 5) | ((amount & 31) << 7); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("RSBS , , {, #}")] - public void Rsbs([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // - [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount) - { - uint opcode = 0xe0700000u; // RSBS R0, R0, R0, LSL #0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - opcode |= ((shift & 3) << 5) | ((amount & 31) << 7); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("RSB , , ")] - public void Rsc([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values] bool carryIn) - { - uint opcode = 0xe0e00000u; // RSC R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("RSCS , , ")] - public void Rscs([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values] bool carryIn) - { - uint opcode = 0xe0f00000u; // RSCS R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("SBC , , ")] - public void Sbc([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values] bool carryIn) - { - uint opcode = 0xe0c00000u; // SBC R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("SBCS , , ")] - public void Sbcs([Values(0u, 13u)] uint rd, - [Values(1u, 13u)] uint rn, - [Values(2u, 13u)] uint rm, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, - [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, - [Values] bool carryIn) - { - uint opcode = 0xe0d00000u; // SBCS R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); - - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn); - - CompareAgainstUnicorn(); - } #endif } } diff --git a/Ryujinx.Tests/Cpu/CpuTestBf32.cs b/Ryujinx.Tests/Cpu/CpuTestBf32.cs index acc70a5971..66b8fc0623 100644 --- a/Ryujinx.Tests/Cpu/CpuTestBf32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestBf32.cs @@ -1,14 +1,17 @@ -using NUnit.Framework; +#define Bf32 + +using NUnit.Framework; using System; namespace Ryujinx.Tests.Cpu { - [Category("Bfm")] + [Category("Bf32")] public sealed class CpuTestBf32 : CpuTest32 { - private const int RndCnt = 10; - private const int RndCntImmr = 10; - private const int RndCntImms = 10; +#if Bf32 + private const int RndCnt = 2; + private const int RndCntImmr = 2; + private const int RndCntImms = 2; [Test, Pairwise, Description("BFC , #, #")] public void Bfc([Values(0u, 0xdu)] uint rd, @@ -81,7 +84,7 @@ namespace Ryujinx.Tests.Cpu [Values(1u, 0xdu)] uint rn, [Random(RndCnt)] uint wd, [Values(0x00000000u, 0x7FFFFFFFu, - 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, + 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb, [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1) { @@ -100,5 +103,6 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } +#endif } } diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdLogical32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdLogical32.cs index 2c9dfb6b6a..2614d3e8a8 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdLogical32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdLogical32.cs @@ -1,4 +1,5 @@ #define SimdLogical32 + using ARMeilleure.State; using NUnit.Framework; using System; @@ -6,13 +7,33 @@ using System; namespace Ryujinx.Tests.Cpu { [Category("SimdLogical32")] - class CpuTestSimdLogical32 : CpuTest32 + public sealed class CpuTestSimdLogical32 : CpuTest32 { #if SimdLogical32 +#region "ValueSource (Opcodes)" + private static uint[] _Vbif_Vbit_Vbsl_Vand_() + { + return new uint[] + { + 0xf3300110u, // VBIF D0, D0, D0 + 0xf3200110u, // VBIT D0, D0, D0 + 0xf3100110u, // VBSL D0, D0, D0 + 0xf2000110u // VAND D0, D0, D0 + }; + } + #endregion - private const int RndCnt = 5; + private const int RndCnt = 2; - private uint GenerateVectorOpcode(uint opcode, uint rd, uint rn, uint rm, bool q) + [Test, Pairwise] + public void Vbif_Vbit_Vbsl_Vand([ValueSource("_Vbif_Vbit_Vbsl_Vand_")] uint opcode, + [Range(0u, 4u)] uint rd, + [Range(0u, 4u)] uint rn, + [Range(0u, 4u)] uint rm, + [Random(RndCnt)] ulong z, + [Random(RndCnt)] ulong a, + [Random(RndCnt)] ulong b, + [Values] bool q) { if (q) { @@ -26,80 +47,6 @@ namespace Ryujinx.Tests.Cpu opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); - return opcode; - } - - [Test, Pairwise, Description("VBIF {}, , ")] - public void Vbif([Range(0u, 4u)] uint rd, - [Range(0u, 4u)] uint rn, - [Range(0u, 4u)] uint rm, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool q) - { - uint opcode = GenerateVectorOpcode(0xf3300110u, rd, rn, rm, q); // VBIF D0, D0, D0 - - V128 v0 = MakeVectorE0E1(z, z); - V128 v1 = MakeVectorE0E1(a, z); - V128 v2 = MakeVectorE0E1(b, z); - - SingleOpcode(opcode, v0: v0, v1: v1, v2: v2); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("VBIT {}, , ")] - public void Vbit([Range(0u, 4u)] uint rd, - [Range(0u, 4u)] uint rn, - [Range(0u, 4u)] uint rm, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool q) - { - uint opcode = GenerateVectorOpcode(0xf3200110u, rd, rn, rm, q); // VBIT D0, D0, D0 - - V128 v0 = MakeVectorE0E1(z, z); - V128 v1 = MakeVectorE0E1(a, z); - V128 v2 = MakeVectorE0E1(b, z); - - SingleOpcode(opcode, v0: v0, v1: v1, v2: v2); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("VBSL {}, , ")] - public void Vbsl([Range(0u, 4u)] uint rd, - [Range(0u, 4u)] uint rn, - [Range(0u, 4u)] uint rm, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool q) - { - uint opcode = GenerateVectorOpcode(0xf3100110u, rd, rn, rm, q); // VBSL D0, D0, D0 - - V128 v0 = MakeVectorE0E1(z, z); - V128 v1 = MakeVectorE0E1(a, z); - V128 v2 = MakeVectorE0E1(b, z); - - SingleOpcode(opcode, v0: v0, v1: v1, v2: v2); - - CompareAgainstUnicorn(); - } - - [Test, Pairwise, Description("VAND {}, , ")] - public void Vand([Range(0u, 4u)] uint rd, - [Range(0u, 4u)] uint rn, - [Range(0u, 4u)] uint rm, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool q) - { - uint opcode = GenerateVectorOpcode(0xf2000110u, rd, rn, rm, q); // VAND D0, D0, D0 - V128 v0 = MakeVectorE0E1(z, z); V128 v1 = MakeVectorE0E1(a, z); V128 v2 = MakeVectorE0E1(b, z); diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs index 4751833b2f..eb27d95fbc 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs @@ -1,4 +1,4 @@ -#define SimdMem32 +#define SimdMemory32 using ARMeilleure.State; using NUnit.Framework; @@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu [Category("SimdMemory32")] public sealed class CpuTestSimdMemory32 : CpuTest32 { -#if SimdMem32 +#if SimdMemory32 private const int RndCntImm = 2; private uint[] LDSTModes = diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs index 888f283bb5..4975c87248 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Tests.Cpu #if SimdMov32 private const int RndCntImm = 10; - [Test, Combinatorial, Description("VMOV.I
, #")] + [Test, Pairwise, Description("VMOV.I
, #")] public void Movi_V([Range(0u, 10u)] uint variant, [Values(0u, 1u, 2u, 3u)] uint vd, [Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm, @@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VMOV.F , #")] + [Test, Pairwise, Description("VMOV.F , #")] public void Movi_S([Range(2u, 3u)] uint size, [Values(0u, 1u, 2u, 3u)] uint vd, [Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm) @@ -107,7 +107,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VMOV. , ")] + [Test, Pairwise, Description("VMOV. , ")] public void Mov_GP_Elem([Range(0u, 7u)] uint vn, [Values(0u, 1u, 2u, 3u)] uint rt, [Range(0u, 2u)] uint size, @@ -206,7 +206,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VMOVN.
, ")] + [Test, Pairwise, Description("VMOVN.
, ")] public void Movn_V([Range(0u, 1u, 2u)] uint size, [Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 2u, 4u, 8u)] uint vm) @@ -230,7 +230,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VTRN. , ")] + [Test, Pairwise, Description("VTRN. , ")] public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm, [Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u)] uint size, @@ -263,7 +263,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VZIP. , ")] + [Test, Pairwise, Description("VZIP. , ")] public void Vzip([Values(0u, 1u, 2u, 3u)] uint vm, [Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u)] uint size, @@ -296,7 +296,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VUZP. , ")] + [Test, Pairwise, Description("VUZP. , ")] public void Vuzp([Values(0u, 1u, 2u, 3u)] uint vm, [Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u)] uint size, @@ -329,7 +329,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VTBL.8
, {list}, ")] + [Test, Pairwise, Description("VTBL.8
, {list}, ")] public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid. [Range(4u, 12u)] uint vn, // Selection. [Values(0u, 1u)] uint vd, // Destinations. @@ -378,7 +378,7 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VEXT.8 {,} , , #")] + [Test, Pairwise, Description("VEXT.8 {,} , , #")] public void Vext([Values(0u, 1u, 2u, 3u)] uint vm, [Values(0u, 1u, 2u, 3u)] uint vn, [Values(0u, 1u, 2u, 3u)] uint vd, diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs index bf912b37b8..5a29f7b265 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs @@ -4,13 +4,12 @@ using ARMeilleure.State; using NUnit.Framework; using System; using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; namespace Ryujinx.Tests.Cpu { [Category("SimdReg32")] - public sealed class CpuTestSimdReg32 : CpuTest32 { + public sealed class CpuTestSimdReg32 : CpuTest32 + { #if SimdReg32 #region "ValueSource (Types)" @@ -224,11 +223,10 @@ namespace Ryujinx.Tests.Cpu uint opcode = 0xf2000d00u; // VADD.F32 D0, D0, D0 if (q) { - rm <<= 2; - rn <<= 2; - rd <<= 2; - opcode |= 1 << 6; + rm <<= 1; + rn <<= 1; + rd <<= 1; } opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); @@ -326,7 +324,8 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Combinatorial, Description("VPADD.f32 V0, V0, V0")] + [Explicit] + [Test, Pairwise, Description("VPADD.f32 V0, V0, V0")] public void Vpadd_f32([Values(0u)] uint rd, [Range(0u, 7u)] uint rn, [Range(0u, 7u)] uint rm)