aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Tests')
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimd32.cs93
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs190
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdShImm32.cs68
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);