aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-09-01 16:52:51 +0200
committergdkchan <gab.dark.100@gmail.com>2018-09-01 11:52:51 -0300
commit42e4e02a648812c4dee1574a5cd9e7dddf7b2458 (patch)
treee5d4992e36bf17255d82690388ff4d185faf676f /Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
parent326777ca4a68b38c7a5e44c76291f09f07ddcf2e (diff)
Add Fcvtns_S, Fcvtns_V, Fcvtnu_S, Fcvtnu_V (AOpCodeSimd) FP & Umlal_V, Umlsl_V, Saddl_V, Ssubl_V, Usubl_V instructions; add 8 FP & 16 S/Umlal_V, S/Umlsl_V, S/Uaddl_V, S/Usubl_V Tests. (#390)
* Update AOpCodeTable.cs * Update AInstEmitSimdCvt.cs * Update Pseudocode.cs * Update Instructions.cs * Update CpuTestSimd.cs * Update AOpCodeTable.cs * Update AInstEmitSimdArithmetic.cs * Update Instructions.cs * Update CpuTestSimdReg.cs * Update CpuTestSimd.cs * Update AOpCodeTable.cs * Update AInstEmitSimdArithmetic.cs * Update Instructions.cs * Update CpuTestSimdReg.cs * Add QCFlagBit. * Add QCFlagBit.
Diffstat (limited to 'Ryujinx.Tests/Cpu/CpuTestSimdReg.cs')
-rw-r--r--Ryujinx.Tests/Cpu/CpuTestSimdReg.cs678
1 files changed, 587 insertions, 91 deletions
diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs b/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
index 782e5921..b7633e8b 100644
--- a/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestSimdReg.cs
@@ -86,7 +86,7 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
- private const int RndCnt = 4;
+ private const int RndCnt = 2;
[Test, Pairwise, Description("ADD <V><d>, <V><n>, <V><m>")]
public void Add_S_D([Values(0u)] uint Rd,
@@ -1738,6 +1738,68 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
+ [Test, Pairwise, Description("SADDL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Saddl_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x0E200000; // SADDL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Saddl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("SADDL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Saddl_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x4E200000; // SADDL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Saddl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
[Test, Pairwise, Description("SADDW{2} <Vd>.<Ta>, <Vn>.<Ta>, <Vm>.<Tb>")]
public void Saddw_V_8B8H8H_4H4S4S_2S2D2D([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn,
@@ -2040,6 +2102,130 @@ namespace Ryujinx.Tests.Cpu
});
}
+ [Test, Pairwise, Description("SMLAL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Smlal_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x0E208000; // SMLAL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Smlal_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("SMLAL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Smlal_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x4E208000; // SMLAL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Smlal_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("SMLSL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Smlsl_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x0E20A000; // SMLSL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Smlsl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("SMLSL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Smlsl_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x4E20A000; // SMLSL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Smlsl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
[Test, Pairwise, Description("SQADD <V><d>, <V><n>, <V><m>")]
public void Sqadd_S_B_H_S_D([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn,
@@ -2049,22 +2235,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_1B1H1S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <B, H, S, D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x5E200C00; // SQADD B0, B0, B0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqadd_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2072,7 +2257,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2084,22 +2270,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x0E200C00; // SQADD V0.8B, V0.8B, V0.8B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqadd_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2107,7 +2292,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2119,22 +2305,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x4E200C00; // SQADD V0.16B, V0.16B, V0.16B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.Vpart(1, 0, new Bits(A)); AArch64.Vpart(1, 1, new Bits(A));
AArch64.Vpart(2, 0, new Bits(B)); AArch64.Vpart(2, 1, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqadd_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2142,7 +2327,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQDMULH <V><d>, <V><n>, <V><m>")]
@@ -2154,22 +2340,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_1H1S_")] [Random(RndCnt)] ulong B,
[Values(0b01u, 0b10u)] uint size) // <H, S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x5E20B400; // SQDMULH B0, B0, B0 (RESERVED)
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqdmulh_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2177,7 +2362,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQDMULH <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2189,22 +2375,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b01u, 0b10u)] uint size) // <4H, 2S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x0E20B400; // SQDMULH V0.8B, V0.8B, V0.8B (RESERVED)
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqdmulh_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2212,7 +2397,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQDMULH <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2224,22 +2410,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b01u, 0b10u)] uint size) // <8H, 4S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x4E20B400; // SQDMULH V0.16B, V0.16B, V0.16B (RESERVED)
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.Vpart(1, 0, new Bits(A)); AArch64.Vpart(1, 1, new Bits(A));
AArch64.Vpart(2, 0, new Bits(B)); AArch64.Vpart(2, 1, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqdmulh_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2247,7 +2432,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQRDMULH <V><d>, <V><n>, <V><m>")]
@@ -2259,22 +2445,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_1H1S_")] [Random(RndCnt)] ulong B,
[Values(0b01u, 0b10u)] uint size) // <H, S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x7E20B400; // SQRDMULH B0, B0, B0 (RESERVED)
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqrdmulh_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2282,7 +2467,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQRDMULH <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2294,22 +2480,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b01u, 0b10u)] uint size) // <4H, 2S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x2E20B400; // SQRDMULH V0.8B, V0.8B, V0.8B (RESERVED)
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqrdmulh_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2317,7 +2502,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQRDMULH <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2329,22 +2515,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b01u, 0b10u)] uint size) // <8H, 4S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x6E20B400; // SQRDMULH V0.16B, V0.16B, V0.16B (RESERVED)
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.Vpart(1, 0, new Bits(A)); AArch64.Vpart(1, 1, new Bits(A));
AArch64.Vpart(2, 0, new Bits(B)); AArch64.Vpart(2, 1, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqrdmulh_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2352,7 +2537,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQSUB <V><d>, <V><n>, <V><m>")]
@@ -2364,22 +2550,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_1B1H1S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <B, H, S, D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x5E202C00; // SQSUB B0, B0, B0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqsub_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2387,7 +2572,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQSUB <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2399,22 +2585,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x0E202C00; // SQSUB V0.8B, V0.8B, V0.8B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqsub_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2422,7 +2607,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SQSUB <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2434,22 +2620,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x4E202C00; // SQSUB V0.16B, V0.16B, V0.16B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.Vpart(1, 0, new Bits(A)); AArch64.Vpart(1, 1, new Bits(A));
AArch64.Vpart(2, 0, new Bits(B)); AArch64.Vpart(2, 1, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Sqsub_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -2457,7 +2642,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("SRHADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -2522,6 +2708,68 @@ namespace Ryujinx.Tests.Cpu
});
}
+ [Test, Pairwise, Description("SSUBL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Ssubl_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x0E202000; // SSUBL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Ssubl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("SSUBL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Ssubl_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x4E202000; // SSUBL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Ssubl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
[Test, Pairwise, Description("SSUBW{2} <Vd>.<Ta>, <Vn>.<Ta>, <Vm>.<Tb>")]
public void Ssubw_V_8B8H8H_4H4S4S_2S2D2D([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn,
@@ -3128,6 +3376,68 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
+ [Test, Pairwise, Description("UADDL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Uaddl_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x2E200000; // UADDL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Uaddl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("UADDL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Uaddl_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x6E200000; // UADDL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Uaddl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
[Test, Pairwise, Description("UADDW{2} <Vd>.<Ta>, <Vn>.<Ta>, <Vm>.<Tb>")]
public void Uaddw_V_8B8H8H_4H4S4S_2S2D2D([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn,
@@ -3316,6 +3626,130 @@ namespace Ryujinx.Tests.Cpu
});
}
+ [Test, Pairwise, Description("UMLAL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Umlal_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x2E208000; // UMLAL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Umlal_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("UMLAL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Umlal_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x6E208000; // UMLAL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Umlal_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("UMLSL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Umlsl_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x2E20A000; // UMLSL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Umlsl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("UMLSL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Umlsl_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x6E20A000; // UMLSL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Umlsl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
[Test, Pairwise, Description("UQADD <V><d>, <V><n>, <V><m>")]
public void Uqadd_S_B_H_S_D([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn,
@@ -3325,22 +3759,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_1B1H1S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <B, H, S, D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x7E200C00; // UQADD B0, B0, B0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Uqadd_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -3348,7 +3781,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("UQADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -3360,22 +3794,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x2E200C00; // UQADD V0.8B, V0.8B, V0.8B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Uqadd_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -3383,7 +3816,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("UQADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -3395,22 +3829,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x6E200C00; // UQADD V0.16B, V0.16B, V0.16B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.Vpart(1, 0, new Bits(A)); AArch64.Vpart(1, 1, new Bits(A));
AArch64.Vpart(2, 0, new Bits(B)); AArch64.Vpart(2, 1, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Uqadd_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -3418,7 +3851,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("UQSUB <V><d>, <V><n>, <V><m>")]
@@ -3430,22 +3864,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_1B1H1S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <B, H, S, D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x7E202C00; // UQSUB B0, B0, B0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Uqsub_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -3453,7 +3886,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("UQSUB <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -3465,22 +3899,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x2E202C00; // UQSUB V0.8B, V0.8B, V0.8B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.V(1, new Bits(A));
AArch64.V(2, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Uqsub_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -3488,7 +3921,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("UQSUB <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -3500,22 +3934,21 @@ namespace Ryujinx.Tests.Cpu
[ValueSource("_8B4H2S1D_")] [Random(RndCnt)] ulong B,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
{
+ const int QCFlagBit = 27; // Cumulative saturation bit.
+
uint Opcode = 0x6E202C00; // UQSUB V0.16B, V0.16B, V0.16B
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((size & 3) << 22);
Bits Op = new Bits(Opcode);
- int Fpsr = (int)TestContext.CurrentContext.Random.NextUInt();
-
Vector128<float> V0 = MakeVectorE0E1(Z, Z);
Vector128<float> V1 = MakeVectorE0E1(A, A);
Vector128<float> V2 = MakeVectorE0E1(B, B);
- AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2, Fpsr: Fpsr);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
AArch64.Vpart(1, 0, new Bits(A)); AArch64.Vpart(1, 1, new Bits(A));
AArch64.Vpart(2, 0, new Bits(B)); AArch64.Vpart(2, 1, new Bits(B));
- Shared.FPSR = new Bits((uint)Fpsr);
SimdFp.Uqsub_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
Assert.Multiple(() =>
@@ -3523,7 +3956,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
});
- Assert.That(ThreadState.Fpsr, Is.EqualTo((int)Shared.FPSR.ToUInt32()));
+
+ Assert.That(((ThreadState.Fpsr >> QCFlagBit) & 1) != 0, Is.EqualTo(Shared.FPSR[QCFlagBit]));
}
[Test, Pairwise, Description("URHADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
@@ -3588,6 +4022,68 @@ namespace Ryujinx.Tests.Cpu
});
}
+ [Test, Pairwise, Description("USUBL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Usubl_V_8B8H_4H4S_2S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B8H, 4H4S, 2S2D>
+ {
+ uint Opcode = 0x2E202000; // USUBL V0.8H, V0.8B, V0.8B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE0(A);
+ Vector128<float> V2 = MakeVectorE0(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 0, new Bits(A));
+ AArch64.Vpart(2, 0, new Bits(B));
+ SimdFp.Usubl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
+ [Test, Pairwise, Description("USUBL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>")]
+ public void Usubl_V_16B8H_8H4S_4S2D([Values(0u)] uint Rd,
+ [Values(1u, 0u)] uint Rn,
+ [Values(2u, 0u)] uint Rm,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong Z,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong A,
+ [ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong B,
+ [Values(0b00u, 0b01u, 0b10u)] uint size) // <16B8H, 8H4S, 4S2D>
+ {
+ uint Opcode = 0x6E202000; // USUBL2 V0.8H, V0.16B, V0.16B
+ Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
+ Opcode |= ((size & 3) << 22);
+ Bits Op = new Bits(Opcode);
+
+ Vector128<float> V0 = MakeVectorE0E1(Z, Z);
+ Vector128<float> V1 = MakeVectorE1(A);
+ Vector128<float> V2 = MakeVectorE1(B);
+ AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
+
+ AArch64.Vpart(0, 0, new Bits(Z)); AArch64.Vpart(0, 1, new Bits(Z));
+ AArch64.Vpart(1, 1, new Bits(A));
+ AArch64.Vpart(2, 1, new Bits(B));
+ SimdFp.Usubl_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
+ Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
+ });
+ }
+
[Test, Pairwise, Description("USUBW{2} <Vd>.<Ta>, <Vn>.<Ta>, <Vm>.<Tb>")]
public void Usubw_V_8B8H8H_4H4S4S_2S2D2D([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn,