aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Tests/Cpu
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2020-06-24 01:43:44 +0100
committerGitHub <noreply@github.com>2020-06-24 10:43:44 +1000
commit9a49f8aec92f7707037f5d1e677078451d07036b (patch)
tree247380683eb145bf39ad3820e77c7f5f86af7f6c /Ryujinx.Tests/Cpu
parent4472196b484d7814176cd2786e603584bb9fd169 (diff)
Fix VMVN (immediate), Add VPMIN, VPMAX, VMVN (register) (#1303)
* Add Vmvn (register), tests for both Vmvn variants. * Add Vpmin, Vpmax, improve Non-FastFp accuracy for Vpadd * Rebase on top of PTC. * Add Nopcode * Increment PTC version. * Fix nits.
Diffstat (limited to 'Ryujinx.Tests/Cpu')
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs84
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs86
2 files changed, 153 insertions, 17 deletions
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs
index 8c9627ce..aba0f02d 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdMov32.cs
@@ -39,8 +39,8 @@ namespace Ryujinx.Tests.Cpu
0b1110_1
};
-
uint opcode = 0xf2800010u; // VMOV.I32 D0, #0
+
uint cmodeOp = variants[variant];
if (q)
@@ -49,11 +49,11 @@ namespace Ryujinx.Tests.Cpu
}
opcode |= ((cmodeOp & 1) << 5) | ((cmodeOp & 0x1e) << 7);
- opcode |= ((q ? 1u : 0u) << 6);
+ opcode |= (q ? 1u : 0u) << 6;
opcode |= (imm & 0xf) | ((imm & 0x70) << 12) | ((imm & 0x80) << 16);
- opcode |= ((vd & 0x10) << 18);
- opcode |= ((vd & 0xf) << 12);
+ opcode |= (vd & 0x10) << 18;
+ opcode |= (vd & 0xf) << 12;
SingleOpcode(opcode);
@@ -258,6 +258,82 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
+ [Test, Pairwise, Description("VMVN.<size> <Vt>, <Vm>")]
+ public void Vmvn([Range(0u, 1u, 2u)] uint size,
+ [Values(0u, 1u, 2u, 3u)] uint vd,
+ [Values(0u, 2u, 4u, 8u)] uint vm,
+ [Values] bool q)
+ {
+ uint opcode = 0xf3b00580u; // VMVN D0, D0
+
+ if (q)
+ {
+ opcode |= 1 << 6;
+ vm <<= 1;
+ vd <<= 1;
+ }
+
+ opcode |= (size & 0x3) << 18;
+ opcode |= (vm & 0x10) << 1;
+ opcode |= (vm & 0xf) << 0;
+
+ opcode |= (vd & 0x10) << 18;
+ opcode |= (vd & 0xf) << 12;
+
+ V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
+ V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
+ V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
+ V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
+
+ SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3);
+
+ CompareAgainstUnicorn();
+ }
+
+ [Test, Pairwise, Description("VMVN.I<size> <Dd/Qd>, #<imm>")]
+ public void Mvni_V([Range(0u, 7u)] uint variant,
+ [Values(0u, 1u, 2u, 3u)] uint vd,
+ [Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm,
+ [Values] bool q)
+ {
+ uint[] variants =
+ {
+ // I32
+ 0b0000,
+ 0b0010,
+ 0b0100,
+ 0b0110,
+
+ // I16
+ 0b1000,
+ 0b1010,
+
+ // I32
+ 0b1100,
+ 0b1101,
+ };
+
+ uint opcode = 0xf2800030u; // VMVN.I32 D0, #0
+
+ uint cmodeOp = variants[variant];
+
+ if (q)
+ {
+ vd <<= 1;
+ }
+
+ opcode |= (cmodeOp & 0xf) << 8;
+ opcode |= (q ? 1u : 0u) << 6;
+ opcode |= (imm & 0xf) | ((imm & 0x70) << 12) | ((imm & 0x80) << 16);
+
+ opcode |= (vd & 0x10) << 18;
+ opcode |= (vd & 0xf) << 12;
+
+ SingleOpcode(opcode);
+
+ CompareAgainstUnicorn();
+ }
+
[Test, Pairwise, Description("VTRN.<size> <Vd>, <Vm>")]
public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd,
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs b/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs
index 66db63bc..1581e850 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs
@@ -12,6 +12,31 @@ namespace Ryujinx.Tests.Cpu
{
#if SimdReg32
+#region "ValueSource (Opcodes)"
+ private static uint[] _Vp_Add_Max_Min_F_()
+ {
+ return new uint[]
+ {
+ 0xf3000d00u, // VPADD.F32 D0, D0, D0
+ 0xf3000f00u, // VPMAX.F32 D0, D0, D0
+ 0xf3200f00u // VPMIN.F32 D0, D0, D0
+ };
+ }
+
+ // 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_Max_Min_I_()
+ {
+ return new uint[]
+ {
+ VpaddI8,
+ 0xf2000a00u, // VPMAX.S8 D0, D0, D0
+ 0xf2000a10u // VPMIN.S8 D0, D0, D0
+ };
+ }
+#endregion
+
#region "ValueSource (Types)"
private static ulong[] _1B1H1S1D_()
{
@@ -296,7 +321,7 @@ namespace Ryujinx.Tests.Cpu
{
uint opcode = 0xf2800a00u; // VMLSL.S8 Q0, D0, D0
- opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
+ opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -329,7 +354,7 @@ namespace Ryujinx.Tests.Cpu
{
uint opcode = 0xf2800c00u; // VMULL.S8 Q0, D0, D0
- opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
+ opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -381,7 +406,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= 1 << 24;
}
- opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
+ opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
@@ -397,22 +422,57 @@ namespace Ryujinx.Tests.Cpu
}
[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)
+ [Test, Pairwise]
+ public void Vp_Add_Max_Min_F([ValueSource("_Vp_Add_Max_Min_F_")] uint opcode,
+ [Values(0u)] uint rd,
+ [Range(0u, 7u)] uint rn,
+ [Range(0u, 7u)] uint rm,
+ [ValueSource("_2S_F_")] ulong z0,
+ [ValueSource("_2S_F_")] ulong z1,
+ [ValueSource("_2S_F_")] ulong a0,
+ [ValueSource("_2S_F_")] ulong a1,
+ [ValueSource("_2S_F_")] ulong b0,
+ [ValueSource("_2S_F_")] ulong b1)
{
- // not currently a slow path test - just a sanity check for pairwise
- uint opcode = 0xf3000d00u; // VPADD.F32 D0, D0, D0
-
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
var rnd = TestContext.CurrentContext.Random;
- V128 v0 = new V128(rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue));
- V128 v1 = new V128(rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue));
- V128 v2 = new V128(rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue), rnd.NextFloat(int.MinValue, int.MaxValue));
+ V128 v0 = MakeVectorE0E1(z0, z1);
+ V128 v1 = MakeVectorE0E1(a0, a1);
+ V128 v2 = MakeVectorE0E1(b0, b1);
+
+ SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
+
+ CompareAgainstUnicorn();
+ }
+
+ [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)
+ {
+ if (u && opcode != VpaddI8)
+ {
+ opcode |= 1 << 24;
+ }
+
+ 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);