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)