diff options
Diffstat (limited to 'Ryujinx.Tests')
| -rw-r--r-- | Ryujinx.Tests/Cpu/CpuTestSimd32.cs | 93 | ||||
| -rw-r--r-- | Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs | 190 | ||||
| -rw-r--r-- | Ryujinx.Tests/Cpu/CpuTestSimdShImm32.cs | 68 |
3 files changed, 261 insertions, 90 deletions
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimd32.cs b/Ryujinx.Tests/Cpu/CpuTestSimd32.cs index 34e94068..34173cd7 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimd32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimd32.cs @@ -12,12 +12,22 @@ namespace Ryujinx.Tests.Cpu #if Simd32 #region "ValueSource (Opcodes)" - private static uint[] _Vabs_Vneg_V_() + private static uint[] _Vabs_Vneg_Vpaddl_I_() { return new uint[] { - 0xf3b10300u, // VABS.S8 D0, D0 - 0xf3b10380u // VNEG.S8 D0, D0 + 0xf3b10300u, // VABS.S8 D0, D0 + 0xf3b10380u, // VNEG.S8 D0, D0 + 0xf3b00200u // VPADDL.S8 D0, D0 + }; + } + + private static uint[] _Vabs_Vneg_F_() + { + return new uint[] + { + 0xf3b90700u, // VABS.F32 D0, D0 + 0xf3b90780u // VNEG.F32 D0, D0 }; } #endregion @@ -201,40 +211,43 @@ namespace Ryujinx.Tests.Cpu } [Test, Pairwise] - public void Vabs_Vneg_V_S8_S16_S32([ValueSource("_Vabs_Vneg_V_")] uint opcode, - [Range(0u, 3u)] uint rd, - [Range(0u, 3u)] uint rm, - [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z, - [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong b, - [Values(0u, 1u, 2u)] uint size, // <S8, S16, S32> - [Values] bool q) + public void Vabs_Vneg_Vpaddl_V_I([ValueSource("_Vabs_Vneg_Vpaddl_I_")] uint opcode, + [Range(0u, 3u)] uint rd, + [Range(0u, 3u)] uint rm, + [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z, + [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong b, + [Values(0u, 1u, 2u)] uint size, // <S8, S16, S32> + [Values] bool q) { - const bool f = false; + if (q) + { + opcode |= 1 << 6; + + rd >>= 1; rd <<= 1; + rm >>= 1; rm <<= 1; + } - Vabs_Vneg_V(opcode, rd, rm, z, b, size, f, q); + opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); + opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); + + opcode |= (size & 0x3) << 18; + + V128 v0 = MakeVectorE0E1(z, ~z); + V128 v1 = MakeVectorE0E1(b, ~b); + + SingleOpcode(opcode, v0: v0, v1: v1); + + CompareAgainstUnicorn(); } [Test, Pairwise] - public void Vabs_Vneg_V_F32([ValueSource("_Vabs_Vneg_V_")] uint opcode, + public void Vabs_Vneg_V_F32([ValueSource("_Vabs_Vneg_F_")] uint opcode, [Range(0u, 3u)] uint rd, [Range(0u, 3u)] uint rm, [ValueSource("_2S_F_")] ulong z, [ValueSource("_2S_F_")] ulong b, [Values] bool q) { - const uint size = 0b10; // <F32> - const bool f = true; - - Vabs_Vneg_V(opcode, rd, rm, z, b, size, f, q); - } - - private void Vabs_Vneg_V(uint opcode, uint rd, uint rm, ulong z, ulong b, uint size, bool f, bool q) - { - if (f) - { - opcode |= 1 << 10; - } - if (q) { opcode |= 1 << 6; @@ -246,8 +259,6 @@ namespace Ryujinx.Tests.Cpu opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); - opcode |= (size & 0x3) << 18; - V128 v0 = MakeVectorE0E1(z, ~z); V128 v1 = MakeVectorE0E1(b, ~b); @@ -283,6 +294,32 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } + + [Test, Pairwise] + public void Vmovn_V([Range(0u, 3u)] uint rd, + [Range(0u, 3u)] uint rm, + [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z, + [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong b, + [Values(0u, 1u, 2u, 3u)] uint op, + [Values(0u, 1u, 2u)] uint size) // <S8, S16, S32> + { + rm >>= 1; rm <<= 1; + + uint opcode = 0xf3b20200u; // VMOVN.S16 D0, Q0 + + opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); + opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); + + opcode |= (op & 0x3) << 6; + opcode |= (size & 0x3) << 18; + + V128 v0 = MakeVectorE0E1(z, ~z); + V128 v1 = MakeVectorE0E1(b, ~b); + + SingleOpcode(opcode, v0: v0, v1: v1); + + CompareAgainstUnicorn(); + } #endif } } diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs index 0635d8fc..93fc658a 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs @@ -12,11 +12,13 @@ namespace Ryujinx.Tests.Cpu #if SimdReg32 #region "ValueSource (Opcodes)" - private static uint[] _V_Add_Sub_Wide_I_() + private static uint[] _V_Add_Sub_Long_Wide_I_() { return new uint[] { + 0xf2800000u, // VADDL.S8 Q0, D0, D0 0xf2800100u, // VADDW.S8 Q0, Q0, D0 + 0xf2800200u, // VSUBL.S8 Q0, D0, D0 0xf2800300u // VSUBW.S8 Q0, Q0, D0 }; } @@ -74,6 +76,15 @@ namespace Ryujinx.Tests.Cpu }; } + private static uint[] _Vmlal_Vmlsl_V_I_() + { + return new uint[] + { + 0xf2800800u, // VMLAL.S8 Q0, D0, D0 + 0xf2800a00u // VMLSL.S8 Q0, D0, D0 + }; + } + private static uint[] _Vp_Add_Max_Min_F_() { return new uint[] @@ -84,16 +95,30 @@ namespace Ryujinx.Tests.Cpu }; } - // VPADD does not have an unsigned flag, so we check the opcode before setting it. - private static uint VpaddI8 = 0xf2000b10u; // VPADD.I8 D0, D0, D0 + private static uint[] _Vp_Add_I_() + { + return new uint[] + { + 0xf2000b10u // VPADD.I8 D0, D0, D0 + }; + } - private static uint[] _Vp_Add_Max_Min_I_() + private static uint[] _V_Pmax_Pmin_Rhadd_I_() { return new uint[] { - VpaddI8, - 0xf2000a00u, // VPMAX.S8 D0, D0, D0 - 0xf2000a10u // VPMIN.S8 D0, D0, D0 + 0xf2000a00u, // VPMAX .S8 D0, D0, D0 + 0xf2000a10u, // VPMIN .S8 D0, D0, D0 + 0xf2000100u, // VRHADD.S8 D0, D0, D0 + }; + } + + private static uint[] _Vq_Add_Sub_I_() + { + return new uint[] + { + 0xf2000050u, // VQADD.S8 Q0, Q0, Q0 + 0xf2000250u // VQSUB.S8 Q0, Q0, Q0 }; } #endregion @@ -350,7 +375,7 @@ namespace Ryujinx.Tests.Cpu [Explicit] [Test, Pairwise, Description("VADD.f32 V0, V0, V0")] - public void Vadd_f32([Values(0u)] uint rd, + public void Vadd_F32([Values(0u)] uint rd, [Values(0u, 1u)] uint rn, [Values(0u, 2u)] uint rm, [ValueSource("_2S_F_")] ulong z0, @@ -384,15 +409,15 @@ namespace Ryujinx.Tests.Cpu } [Test, Pairwise] - public void V_Add_Sub_Wide_I([ValueSource("_V_Add_Sub_Wide_I_")] uint opcode, - [Range(0u, 5u)] uint rd, - [Range(0u, 5u)] uint rn, - [Range(0u, 5u)] uint rm, - [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z, - [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a, - [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b, - [Values(0u, 1u, 2u)] uint size, // <SU8, SU16, SU32> - [Values] bool u) // <S, U> + public void V_Add_Sub_Long_Wide_I([ValueSource("_V_Add_Sub_Long_Wide_I_")] uint opcode, + [Range(0u, 5u)] uint rd, + [Range(0u, 5u)] uint rn, + [Range(0u, 5u)] uint rm, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b, + [Values(0u, 1u, 2u)] uint size, // <SU8, SU16, SU32> + [Values] bool u) // <S, U> { if (u) { @@ -566,18 +591,17 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("VMLSL.<type><size> <Vd>, <Vn>, <Vm>")] - public void Vmlsl_I([Values(0u)] uint rd, - [Values(1u, 0u)] uint rn, - [Values(2u, 0u)] uint rm, - [Values(0u, 1u, 2u)] uint size, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool u) + [Test, Pairwise] + public void Vmlal_Vmlsl_I([ValueSource(nameof(_Vmlal_Vmlsl_V_I_))] uint opcode, + [Values(0u)] uint rd, + [Values(1u, 0u)] uint rn, + [Values(2u, 0u)] uint rm, + [Values(0u, 1u, 2u)] uint size, + [Random(RndCnt)] ulong z, + [Random(RndCnt)] ulong a, + [Random(RndCnt)] ulong b, + [Values] bool u) { - uint opcode = 0xf2800a00u; // VMLSL.S8 Q0, D0, D0 - opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); @@ -736,17 +760,42 @@ namespace Ryujinx.Tests.Cpu } [Test, Pairwise] - public void Vp_Add_Max_Min_I([ValueSource("_Vp_Add_Max_Min_I_")] uint opcode, - [Values(0u)] uint rd, - [Range(0u, 5u)] uint rn, - [Range(0u, 5u)] uint rm, - [Values(0u, 1u, 2u)] uint size, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool u) + public void Vp_Add_I([ValueSource("_Vp_Add_I_")] uint opcode, + [Values(0u)] uint rd, + [Range(0u, 5u)] uint rn, + [Range(0u, 5u)] uint rm, + [Values(0u, 1u, 2u)] uint size, + [Random(RndCnt)] ulong z, + [Random(RndCnt)] ulong a, + [Random(RndCnt)] ulong b) + { + opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); + opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); + opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); + + opcode |= size << 20; + + 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] + public void V_Pmax_Pmin_Rhadd_I([ValueSource("_V_Pmax_Pmin_Rhadd_I_")] uint opcode, + [Values(0u)] uint rd, + [Range(0u, 5u)] uint rn, + [Range(0u, 5u)] uint rm, + [Values(0u, 1u, 2u)] uint size, + [Random(RndCnt)] ulong z, + [Random(RndCnt)] ulong a, + [Random(RndCnt)] ulong b, + [Values] bool u) { - if (u && opcode != VpaddI8) + if (u) { opcode |= 1 << 24; } @@ -765,6 +814,71 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } + + [Test, Pairwise] + public void Vq_Add_Sub_I([ValueSource("_Vq_Add_Sub_I_")] uint opcode, + [Range(0u, 5u)] uint rd, + [Range(0u, 5u)] uint rn, + [Range(0u, 5u)] uint rm, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b, + [Values(0u, 1u, 2u)] uint size, // <SU8, SU16, SU32> + [Values] bool u) // <S, U> + { + if (u) + { + opcode |= 1 << 24; + } + + rd >>= 1; rd <<= 1; + rn >>= 1; rn <<= 1; + rm >>= 1; rm <<= 1; + + opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); + opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); + opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); + + opcode |= (size & 0x3) << 20; + + V128 v0 = MakeVectorE0E1(z, ~z); + V128 v1 = MakeVectorE0E1(a, ~a); + V128 v2 = MakeVectorE0E1(b, ~b); + + SingleOpcode(opcode, v0: v0, v1: v1, v2: v2); + + CompareAgainstUnicorn(); + } + + [Test, Pairwise, Description("VQDMULH.<S16, S32> <Qd>, <Qn>, <Qm>")] + public void Vqdmulh_I([Range(0u, 5u)] uint rd, + [Range(0u, 5u)] uint rn, + [Range(0u, 5u)] uint rm, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong z, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong a, + [ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong b, + [Values(1u, 2u)] uint size) // <S16, S32> + { + rd >>= 1; rd <<= 1; + rn >>= 1; rn <<= 1; + rm >>= 1; rm <<= 1; + + uint opcode = 0xf2100b40u & ~(3u << 20); // VQDMULH.S16 Q0, Q0, Q0 + + opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); + opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); + opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); + + opcode |= (size & 0x3) << 20; + + V128 v0 = MakeVectorE0E1(z, ~z); + V128 v1 = MakeVectorE0E1(a, ~a); + V128 v2 = MakeVectorE0E1(b, ~b); + + SingleOpcode(opcode, v0: v0, v1: v1, v2: v2); + + CompareAgainstUnicorn(); + } #endif } } diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdShImm32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdShImm32.cs index a8c32d58..45481f85 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdShImm32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdShImm32.cs @@ -41,9 +41,10 @@ namespace Ryujinx.Tests.Cpu { return new uint[] { + 0xf2880010u, // VSHR.S8 D0, D0, #8 0xf2880110u, // VSRA.S8 D0, D0, #8 0xf2880210u, // VRSHR.S8 D0, D0, #8 - 0xf2880010u // VSHR.S8 D0, D0, #8 + 0xf2880310u // VRSRA.S8 D0, D0, #8 }; } @@ -51,9 +52,10 @@ namespace Ryujinx.Tests.Cpu { return new uint[] { + 0xf2900010u, // VSHR.S16 D0, D0, #16 0xf2900110u, // VSRA.S16 D0, D0, #16 0xf2900210u, // VRSHR.S16 D0, D0, #16 - 0xf2900010u // VSHR.S16 D0, D0, #16 + 0xf2900310u // VRSRA.S16 D0, D0, #16 }; } @@ -61,9 +63,10 @@ namespace Ryujinx.Tests.Cpu { return new uint[] { + 0xf2a00010u, // VSHR.S32 D0, D0, #32 0xf2a00110u, // VSRA.S32 D0, D0, #32 0xf2a00210u, // VRSHR.S32 D0, D0, #32 - 0xf2a00010u // VSHR.S32 D0, D0, #32 + 0xf2a00310u // VRSRA.S32 D0, D0, #32 }; } @@ -76,6 +79,25 @@ namespace Ryujinx.Tests.Cpu 0xf2800090u // VSHR.S64 D0, D0, #64 }; } + + private static uint[] _Vqshrn_Vqrshrn_Vrshrn_Imm_() + { + return new uint[] + { + 0xf2800910u, // VORR.I16 D0, #0 (immediate value changes it into QSHRN) + 0xf2800950u, // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN) + 0xf2800850u // VMOV.I16 Q0, #0 (immediate value changes it into RSHRN) + }; + } + + private static uint[] _Vqshrun_Vqrshrun_Imm_() + { + return new uint[] + { + 0xf3800810u, // VMOV.I16 D0, #0x80 (immediate value changes it into QSHRUN) + 0xf3800850u // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN) + }; + } #endregion private const int RndCnt = 2; @@ -230,18 +252,17 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("VQRSHRN.<type><size> <Vd>, <Vm>, #<imm>")] - public void Vqrshrn_Imm([Values(0u, 1u)] uint rd, - [Values(2u, 0u)] uint rm, - [Values(0u, 1u, 2u)] uint size, - [Random(RndCntShiftImm)] [Values(0u)] uint shiftImm, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b, - [Values] bool u) + [Test, Pairwise] + public void Vqshrn_Vqrshrn_Vrshrn_Imm([ValueSource("_Vqshrn_Vqrshrn_Vrshrn_Imm_")] uint opcode, + [Values(0u, 1u)] uint rd, + [Values(2u, 0u)] uint rm, + [Values(0u, 1u, 2u)] uint size, + [Random(RndCntShiftImm)] [Values(0u)] uint shiftImm, + [Random(RndCnt)] ulong z, + [Random(RndCnt)] ulong a, + [Random(RndCnt)] ulong b, + [Values] bool u) { - uint opcode = 0xf2800950u; // VORR.I16 Q0, #0 (immediate value changes it into QRSHRN) - uint imm = 1u << ((int)size + 3); imm |= shiftImm & (imm - 1); @@ -265,17 +286,16 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(fpsrMask: Fpsr.Qc); } - [Test, Pairwise, Description("VQRSHRUN.<type><size> <Vd>, <Vm>, #<imm>")] - public void Vqrshrun_Imm([Values(0u, 1u)] uint rd, - [Values(2u, 0u)] uint rm, - [Values(0u, 1u, 2u)] uint size, - [Random(RndCntShiftImm)] [Values(0u)] uint shiftImm, - [Random(RndCnt)] ulong z, - [Random(RndCnt)] ulong a, - [Random(RndCnt)] ulong b) + [Test, Pairwise] + public void Vqshrun_Vqrshrun_Imm([ValueSource("_Vqshrun_Vqrshrun_Imm_")] uint opcode, + [Values(0u, 1u)] uint rd, + [Values(2u, 0u)] uint rm, + [Values(0u, 1u, 2u)] uint size, + [Random(RndCntShiftImm)] [Values(0u)] uint shiftImm, + [Random(RndCnt)] ulong z, + [Random(RndCnt)] ulong a, + [Random(RndCnt)] ulong b) { - uint opcode = 0xf3800850u; // VMOV.I16 Q0, #0x80 (immediate value changes it into QRSHRUN) - uint imm = 1u << ((int)size + 3); imm |= shiftImm & (imm - 1); |
