Remove old Tester, update Tests (some reworks). (#400)

* Delete Bits.cs

* Delete Integer.cs

* Delete Instructions.cs

* Delete Pseudocode.cs

* Add files via upload

* Add mnemonic.

* Literals all uppercase.

* Nit.

* Allow FPSR control.

* Allow FPSR control.

* Allow FPSR control.
This commit is contained in:
LDj3SNuD 2018-09-08 19:23:07 +02:00 committed by gdkchan
parent 76a3172f17
commit ca1e37a295
22 changed files with 1354 additions and 15384 deletions

View file

@ -33,9 +33,10 @@ namespace Ryujinx.Tests.Cpu
static CpuTest() static CpuTest()
{ {
UnicornAvailable = UnicornAArch64.IsAvailable(); UnicornAvailable = UnicornAArch64.IsAvailable();
if (!UnicornAvailable) if (!UnicornAvailable)
{ {
Console.WriteLine("WARNING: Could not find unicorn"); Console.WriteLine("WARNING: Could not find Unicorn.");
} }
} }
@ -43,7 +44,7 @@ namespace Ryujinx.Tests.Cpu
public void Setup() public void Setup()
{ {
Position = 0x1000; Position = 0x1000;
Size = 0x1000; Size = 0x1000;
EntryPoint = Position; EntryPoint = Position;
@ -79,10 +80,12 @@ namespace Ryujinx.Tests.Cpu
protected void Opcode(uint Opcode) protected void Opcode(uint Opcode)
{ {
Thread.Memory.WriteUInt32(Position, Opcode); Thread.Memory.WriteUInt32(Position, Opcode);
if (UnicornAvailable) if (UnicornAvailable)
{ {
UnicornEmu.MemoryWrite32((ulong)Position, Opcode); UnicornEmu.MemoryWrite32((ulong)Position, Opcode);
} }
Position += 4; Position += 4;
} }
@ -97,14 +100,18 @@ namespace Ryujinx.Tests.Cpu
Thread.ThreadState.X1 = X1; Thread.ThreadState.X1 = X1;
Thread.ThreadState.X2 = X2; Thread.ThreadState.X2 = X2;
Thread.ThreadState.X3 = X3; Thread.ThreadState.X3 = X3;
Thread.ThreadState.X31 = X31; Thread.ThreadState.X31 = X31;
Thread.ThreadState.V0 = V0; Thread.ThreadState.V0 = V0;
Thread.ThreadState.V1 = V1; Thread.ThreadState.V1 = V1;
Thread.ThreadState.V2 = V2; Thread.ThreadState.V2 = V2;
Thread.ThreadState.Overflow = Overflow; Thread.ThreadState.Overflow = Overflow;
Thread.ThreadState.Carry = Carry; Thread.ThreadState.Carry = Carry;
Thread.ThreadState.Zero = Zero; Thread.ThreadState.Zero = Zero;
Thread.ThreadState.Negative = Negative; Thread.ThreadState.Negative = Negative;
Thread.ThreadState.Fpcr = Fpcr; Thread.ThreadState.Fpcr = Fpcr;
Thread.ThreadState.Fpsr = Fpsr; Thread.ThreadState.Fpsr = Fpsr;
@ -114,14 +121,18 @@ namespace Ryujinx.Tests.Cpu
UnicornEmu.X[1] = X1; UnicornEmu.X[1] = X1;
UnicornEmu.X[2] = X2; UnicornEmu.X[2] = X2;
UnicornEmu.X[3] = X3; UnicornEmu.X[3] = X3;
UnicornEmu.SP = X31; UnicornEmu.SP = X31;
UnicornEmu.Q[0] = V0; UnicornEmu.Q[0] = V0;
UnicornEmu.Q[1] = V1; UnicornEmu.Q[1] = V1;
UnicornEmu.Q[2] = V2; UnicornEmu.Q[2] = V2;
UnicornEmu.OverflowFlag = Overflow; UnicornEmu.OverflowFlag = Overflow;
UnicornEmu.CarryFlag = Carry; UnicornEmu.CarryFlag = Carry;
UnicornEmu.ZeroFlag = Zero; UnicornEmu.ZeroFlag = Zero;
UnicornEmu.NegativeFlag = Negative; UnicornEmu.NegativeFlag = Negative;
UnicornEmu.Fpcr = Fpcr; UnicornEmu.Fpcr = Fpcr;
UnicornEmu.Fpsr = Fpsr; UnicornEmu.Fpsr = Fpsr;
} }
@ -144,10 +155,7 @@ namespace Ryujinx.Tests.Cpu
} }
} }
protected AThreadState GetThreadState() protected AThreadState GetThreadState() => Thread.ThreadState;
{
return Thread.ThreadState;
}
protected AThreadState SingleOpcode(uint Opcode, protected AThreadState SingleOpcode(uint Opcode,
ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X3 = 0, ulong X31 = 0, ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X3 = 0, ulong X31 = 0,
@ -166,23 +174,44 @@ namespace Ryujinx.Tests.Cpu
return GetThreadState(); return GetThreadState();
} }
protected void CompareAgainstUnicorn() [Flags]
protected enum FPSR
{
None = 0,
/// <summary>Invalid Operation cumulative floating-point exception bit.</summary>
IOC = 1 << 0,
/// <summary>Divide by Zero cumulative floating-point exception bit.</summary>
DZC = 1 << 1,
/// <summary>Overflow cumulative floating-point exception bit.</summary>
OFC = 1 << 2,
/// <summary>Underflow cumulative floating-point exception bit.</summary>
UFC = 1 << 3,
/// <summary>Inexact cumulative floating-point exception bit.</summary>
IXC = 1 << 4,
/// <summary>Input Denormal cumulative floating-point exception bit.</summary>
IDC = 1 << 7,
/// <summary>Cumulative saturation bit.</summary>
QC = 1 << 27
}
protected void CompareAgainstUnicorn(FPSR FpsrMask = FPSR.None)
{ {
if (!UnicornAvailable) if (!UnicornAvailable)
{ {
return; return;
} }
Assert.That(Thread.ThreadState.X0, Is.EqualTo(UnicornEmu.X[0])); Assert.That(Thread.ThreadState.X0, Is.EqualTo(UnicornEmu.X[0]));
Assert.That(Thread.ThreadState.X1, Is.EqualTo(UnicornEmu.X[1])); Assert.That(Thread.ThreadState.X1, Is.EqualTo(UnicornEmu.X[1]));
Assert.That(Thread.ThreadState.X2, Is.EqualTo(UnicornEmu.X[2])); Assert.That(Thread.ThreadState.X2, Is.EqualTo(UnicornEmu.X[2]));
Assert.That(Thread.ThreadState.X3, Is.EqualTo(UnicornEmu.X[3])); Assert.That(Thread.ThreadState.X3, Is.EqualTo(UnicornEmu.X[3]));
Assert.That(Thread.ThreadState.X4, Is.EqualTo(UnicornEmu.X[4])); Assert.That(Thread.ThreadState.X4, Is.EqualTo(UnicornEmu.X[4]));
Assert.That(Thread.ThreadState.X5, Is.EqualTo(UnicornEmu.X[5])); Assert.That(Thread.ThreadState.X5, Is.EqualTo(UnicornEmu.X[5]));
Assert.That(Thread.ThreadState.X6, Is.EqualTo(UnicornEmu.X[6])); Assert.That(Thread.ThreadState.X6, Is.EqualTo(UnicornEmu.X[6]));
Assert.That(Thread.ThreadState.X7, Is.EqualTo(UnicornEmu.X[7])); Assert.That(Thread.ThreadState.X7, Is.EqualTo(UnicornEmu.X[7]));
Assert.That(Thread.ThreadState.X8, Is.EqualTo(UnicornEmu.X[8])); Assert.That(Thread.ThreadState.X8, Is.EqualTo(UnicornEmu.X[8]));
Assert.That(Thread.ThreadState.X9, Is.EqualTo(UnicornEmu.X[9])); Assert.That(Thread.ThreadState.X9, Is.EqualTo(UnicornEmu.X[9]));
Assert.That(Thread.ThreadState.X10, Is.EqualTo(UnicornEmu.X[10])); Assert.That(Thread.ThreadState.X10, Is.EqualTo(UnicornEmu.X[10]));
Assert.That(Thread.ThreadState.X11, Is.EqualTo(UnicornEmu.X[11])); Assert.That(Thread.ThreadState.X11, Is.EqualTo(UnicornEmu.X[11]));
Assert.That(Thread.ThreadState.X12, Is.EqualTo(UnicornEmu.X[12])); Assert.That(Thread.ThreadState.X12, Is.EqualTo(UnicornEmu.X[12]));
@ -204,17 +233,19 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Thread.ThreadState.X28, Is.EqualTo(UnicornEmu.X[28])); Assert.That(Thread.ThreadState.X28, Is.EqualTo(UnicornEmu.X[28]));
Assert.That(Thread.ThreadState.X29, Is.EqualTo(UnicornEmu.X[29])); Assert.That(Thread.ThreadState.X29, Is.EqualTo(UnicornEmu.X[29]));
Assert.That(Thread.ThreadState.X30, Is.EqualTo(UnicornEmu.X[30])); Assert.That(Thread.ThreadState.X30, Is.EqualTo(UnicornEmu.X[30]));
Assert.That(Thread.ThreadState.X31, Is.EqualTo(UnicornEmu.SP)); Assert.That(Thread.ThreadState.X31, Is.EqualTo(UnicornEmu.SP));
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
Assert.That(Thread.ThreadState.V1, Is.EqualTo(UnicornEmu.Q[1])); Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
Assert.That(Thread.ThreadState.V2, Is.EqualTo(UnicornEmu.Q[2])); Assert.That(Thread.ThreadState.V1, Is.EqualTo(UnicornEmu.Q[1]));
Assert.That(Thread.ThreadState.V3, Is.EqualTo(UnicornEmu.Q[3])); Assert.That(Thread.ThreadState.V2, Is.EqualTo(UnicornEmu.Q[2]));
Assert.That(Thread.ThreadState.V4, Is.EqualTo(UnicornEmu.Q[4])); Assert.That(Thread.ThreadState.V3, Is.EqualTo(UnicornEmu.Q[3]));
Assert.That(Thread.ThreadState.V5, Is.EqualTo(UnicornEmu.Q[5])); Assert.That(Thread.ThreadState.V4, Is.EqualTo(UnicornEmu.Q[4]));
Assert.That(Thread.ThreadState.V6, Is.EqualTo(UnicornEmu.Q[6])); Assert.That(Thread.ThreadState.V5, Is.EqualTo(UnicornEmu.Q[5]));
Assert.That(Thread.ThreadState.V7, Is.EqualTo(UnicornEmu.Q[7])); Assert.That(Thread.ThreadState.V6, Is.EqualTo(UnicornEmu.Q[6]));
Assert.That(Thread.ThreadState.V8, Is.EqualTo(UnicornEmu.Q[8])); Assert.That(Thread.ThreadState.V7, Is.EqualTo(UnicornEmu.Q[7]));
Assert.That(Thread.ThreadState.V9, Is.EqualTo(UnicornEmu.Q[9])); Assert.That(Thread.ThreadState.V8, Is.EqualTo(UnicornEmu.Q[8]));
Assert.That(Thread.ThreadState.V9, Is.EqualTo(UnicornEmu.Q[9]));
Assert.That(Thread.ThreadState.V10, Is.EqualTo(UnicornEmu.Q[10])); Assert.That(Thread.ThreadState.V10, Is.EqualTo(UnicornEmu.Q[10]));
Assert.That(Thread.ThreadState.V11, Is.EqualTo(UnicornEmu.Q[11])); Assert.That(Thread.ThreadState.V11, Is.EqualTo(UnicornEmu.Q[11]));
Assert.That(Thread.ThreadState.V12, Is.EqualTo(UnicornEmu.Q[12])); Assert.That(Thread.ThreadState.V12, Is.EqualTo(UnicornEmu.Q[12]));
@ -238,11 +269,13 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Thread.ThreadState.V30, Is.EqualTo(UnicornEmu.Q[30])); Assert.That(Thread.ThreadState.V30, Is.EqualTo(UnicornEmu.Q[30]));
Assert.That(Thread.ThreadState.V31, Is.EqualTo(UnicornEmu.Q[31])); Assert.That(Thread.ThreadState.V31, Is.EqualTo(UnicornEmu.Q[31]));
Assert.That(Thread.ThreadState.V31, Is.EqualTo(UnicornEmu.Q[31])); Assert.That(Thread.ThreadState.V31, Is.EqualTo(UnicornEmu.Q[31]));
Assert.That(Thread.ThreadState.Fpcr, Is.EqualTo(UnicornEmu.Fpcr));
Assert.That(Thread.ThreadState.Fpsr & 0x08000000, Is.EqualTo(UnicornEmu.Fpsr & 0x08000000)); Assert.That(Thread.ThreadState.Fpcr, Is.EqualTo(UnicornEmu.Fpcr));
Assert.That(Thread.ThreadState.Fpsr & (int)FpsrMask, Is.EqualTo(UnicornEmu.Fpsr & (int)FpsrMask));
Assert.That(Thread.ThreadState.Overflow, Is.EqualTo(UnicornEmu.OverflowFlag)); Assert.That(Thread.ThreadState.Overflow, Is.EqualTo(UnicornEmu.OverflowFlag));
Assert.That(Thread.ThreadState.Carry, Is.EqualTo(UnicornEmu.CarryFlag)); Assert.That(Thread.ThreadState.Carry, Is.EqualTo(UnicornEmu.CarryFlag));
Assert.That(Thread.ThreadState.Zero, Is.EqualTo(UnicornEmu.ZeroFlag)); Assert.That(Thread.ThreadState.Zero, Is.EqualTo(UnicornEmu.ZeroFlag));
Assert.That(Thread.ThreadState.Negative, Is.EqualTo(UnicornEmu.NegativeFlag)); Assert.That(Thread.ThreadState.Negative, Is.EqualTo(UnicornEmu.NegativeFlag));
} }

View file

@ -1,4 +1,4 @@
//#define Alu #define Alu
using ChocolArm64.State; using ChocolArm64.State;
@ -6,334 +6,185 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("Alu")] // Tested: second half of 2018.
using Tester.Types;
[Category("Alu"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestAlu : CpuTest public sealed class CpuTestAlu : CpuTest
{ {
#if Alu #if Alu
[SetUp] private const int RndCnt = 2;
public void SetupTester()
{
AArch64.TakeReset(false);
}
[Test, Description("CLS <Xd>, <Xn>")] [Test, Pairwise, Description("CLS <Xd>, <Xn>")]
public void Cls_64bit([Values(0u, 31u)] uint Rd, public void Cls_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(256)] ulong Xn) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn)
{ {
uint Opcode = 0xDAC01400; // CLS X0, X0 uint Opcode = 0xDAC01400; // CLS X0, X0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Cls(Op[31], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CLS <Wd>, <Wn>")] [Test, Pairwise, Description("CLS <Wd>, <Wn>")]
public void Cls_32bit([Values(0u, 31u)] uint Rd, public void Cls_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(256)] uint Wn) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn)
{ {
uint Opcode = 0x5AC01400; // CLS W0, W0 uint Opcode = 0x5AC01400; // CLS W0, W0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31) CompareAgainstUnicorn();
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Cls(Op[31], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
} }
[Test, Description("CLZ <Xd>, <Xn>")] [Test, Pairwise, Description("CLZ <Xd>, <Xn>")]
public void Clz_64bit([Values(0u, 31u)] uint Rd, public void Clz_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(256)] ulong Xn) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn)
{ {
uint Opcode = 0xDAC01000; // CLZ X0, X0 uint Opcode = 0xDAC01000; // CLZ X0, X0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Clz(Op[31], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CLZ <Wd>, <Wn>")] [Test, Pairwise, Description("CLZ <Wd>, <Wn>")]
public void Clz_32bit([Values(0u, 31u)] uint Rd, public void Clz_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(256)] uint Wn) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn)
{ {
uint Opcode = 0x5AC01000; // CLZ W0, W0 uint Opcode = 0x5AC01000; // CLZ W0, W0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Clz(Op[31], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("RBIT <Xd>, <Xn>")] [Test, Pairwise, Description("RBIT <Xd>, <Xn>")]
public void Rbit_64bit([Values(0u, 31u)] uint Rd, public void Rbit_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(256)] ulong Xn) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn)
{ {
uint Opcode = 0xDAC00000; // RBIT X0, X0 uint Opcode = 0xDAC00000; // RBIT X0, X0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Rbit(Op[31], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("RBIT <Wd>, <Wn>")] [Test, Pairwise, Description("RBIT <Wd>, <Wn>")]
public void Rbit_32bit([Values(0u, 31u)] uint Rd, public void Rbit_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(256)] uint Wn) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn)
{ {
uint Opcode = 0x5AC00000; // RBIT W0, W0 uint Opcode = 0x5AC00000; // RBIT W0, W0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Rbit(Op[31], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("REV16 <Xd>, <Xn>")] [Test, Pairwise, Description("REV16 <Xd>, <Xn>")]
public void Rev16_64bit([Values(0u, 31u)] uint Rd, public void Rev16_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(256)] ulong Xn) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn)
{ {
uint Opcode = 0xDAC00400; // REV16 X0, X0 uint Opcode = 0xDAC00400; // REV16 X0, X0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Rev16(Op[31], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("REV16 <Wd>, <Wn>")] [Test, Pairwise, Description("REV16 <Wd>, <Wn>")]
public void Rev16_32bit([Values(0u, 31u)] uint Rd, public void Rev16_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(256)] uint Wn) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn)
{ {
uint Opcode = 0x5AC00400; // REV16 W0, W0 uint Opcode = 0x5AC00400; // REV16 W0, W0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Rev16(Op[31], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("REV32 <Xd>, <Xn>")] [Test, Pairwise, Description("REV32 <Xd>, <Xn>")]
public void Rev32_64bit([Values(0u, 31u)] uint Rd, public void Rev32_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(256)] ulong Xn) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn)
{ {
uint Opcode = 0xDAC00800; // REV32 X0, X0 uint Opcode = 0xDAC00800; // REV32 X0, X0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Rev32(Op[31], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("REV <Wd>, <Wn>")] [Test, Pairwise, Description("REV <Wd>, <Wn>")]
public void Rev32_32bit([Values(0u, 31u)] uint Rd, public void Rev32_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(256)] uint Wn) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn)
{ {
uint Opcode = 0x5AC00800; // REV W0, W0 uint Opcode = 0x5AC00800; // REV W0, W0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Rev32(Op[31], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("REV64 <Xd>, <Xn>")] [Test, Pairwise, Description("REV64 <Xd>, <Xn>")]
public void Rev64_64bit([Values(0u, 31u)] uint Rd, public void Rev64_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(256)] ulong Xn) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn)
{ {
uint Opcode = 0xDAC00C00; // REV64 X0, X0 uint Opcode = 0xDAC00C00; // REV64 X0, X0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Rev64(Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

View file

@ -1,4 +1,4 @@
//#define AluImm #define AluImm
using ChocolArm64.State; using ChocolArm64.State;
@ -6,824 +6,448 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("AluImm")] // Tested: second half of 2018.
using Tester.Types;
[Category("AluImm"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestAluImm : CpuTest public sealed class CpuTestAluImm : CpuTest
{ {
#if AluImm #if AluImm
[SetUp] private const int RndCnt = 2;
public void SetupTester() private const int RndCntImm = 2;
{ private const int RndCntImms = 2;
AArch64.TakeReset(false); private const int RndCntImmr = 2;
}
[Test, Description("ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")]
public void Add_64bit([Values(0u, 31u)] uint Rd, public void Add_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0x91000000; // ADD X0, X0, #0, LSL #0 uint Opcode = 0x91000000; // ADD X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Xn_SP); ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Xn_SP); ThreadState = SingleOpcode(Opcode, X31: Xn_SP);
AArch64.SP(new Bits(Xn_SP));
} }
Base.Add_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ADD <Wd|WSP>, <Wn|WSP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("ADD <Wd|WSP>, <Wn|WSP>, #<imm>{, <shift>}")]
public void Add_32bit([Values(0u, 31u)] uint Rd, public void Add_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0x11000000; // ADD W0, W0, #0, LSL #0 uint Opcode = 0x11000000; // ADD W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP); ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Wn_WSP); ThreadState = SingleOpcode(Opcode, X31: Wn_WSP);
AArch64.SP(new Bits(Wn_WSP));
} }
Base.Add_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint WSP = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ADDS <Xd>, <Xn|SP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("ADDS <Xd>, <Xn|SP>, #<imm>{, <shift>}")]
public void Adds_64bit([Values(0u, 31u)] uint Rd, public void Adds_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0xB1000000; // ADDS X0, X0, #0, LSL #0 uint Opcode = 0xB1000000; // ADDS X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Xn_SP); ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Xn_SP); ThreadState = SingleOpcode(Opcode, X31: Xn_SP);
AArch64.SP(new Bits(Xn_SP));
} }
Base.Adds_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong _X31 = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ADDS <Wd>, <Wn|WSP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("ADDS <Wd>, <Wn|WSP>, #<imm>{, <shift>}")]
public void Adds_32bit([Values(0u, 31u)] uint Rd, public void Adds_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0x31000000; // ADDS W0, W0, #0, LSL #0 uint Opcode = 0x31000000; // ADDS W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP); ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Wn_WSP); ThreadState = SingleOpcode(Opcode, X31: Wn_WSP);
AArch64.SP(new Bits(Wn_WSP));
} }
Base.Adds_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint _W31 = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("AND <Xd|SP>, <Xn>, #<imm>")] [Test, Pairwise, Description("AND <Xd|SP>, <Xn>, #<imm>")]
public void And_N1_64bit([Values(0u, 31u)] uint Rd, public void And_N1_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm> [Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm> [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0x92400000; // AND X0, X0, #0x1 uint Opcode = 0x92400000; // AND X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.And_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("AND <Xd|SP>, <Xn>, #<imm>")] [Test, Pairwise, Description("AND <Xd|SP>, <Xn>, #<imm>")]
public void And_N0_64bit([Values(0u, 31u)] uint Rd, public void And_N0_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0x92000000; // AND X0, X0, #0x100000001 uint Opcode = 0x92000000; // AND X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.And_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("AND <Wd|WSP>, <Wn>, #<imm>")] [Test, Pairwise, Description("AND <Wd|WSP>, <Wn>, #<imm>")]
public void And_32bit([Values(0u, 31u)] uint Rd, public void And_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0x12000000; // AND W0, W0, #0x1 uint Opcode = 0x12000000; // AND W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
AArch64.X((int)Rn, new Bits(Wn));
Base.And_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint WSP = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ANDS <Xd>, <Xn>, #<imm>")] [Test, Pairwise, Description("ANDS <Xd>, <Xn>, #<imm>")]
public void Ands_N1_64bit([Values(0u, 31u)] uint Rd, public void Ands_N1_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm> [Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm> [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0xF2400000; // ANDS X0, X0, #0x1 uint Opcode = 0xF2400000; // ANDS X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.Ands_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
if (Rd != 31)
{
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ANDS <Xd>, <Xn>, #<imm>")] [Test, Pairwise, Description("ANDS <Xd>, <Xn>, #<imm>")]
public void Ands_N0_64bit([Values(0u, 31u)] uint Rd, public void Ands_N0_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0xF2000000; // ANDS X0, X0, #0x100000001 uint Opcode = 0xF2000000; // ANDS X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.Ands_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
if (Rd != 31)
{
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ANDS <Wd>, <Wn>, #<imm>")] [Test, Pairwise, Description("ANDS <Wd>, <Wn>, #<imm>")]
public void Ands_32bit([Values(0u, 31u)] uint Rd, public void Ands_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0x72000000; // ANDS W0, W0, #0x1 uint Opcode = 0x72000000; // ANDS W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
AArch64.X((int)Rn, new Bits(Wn));
Base.Ands_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
if (Rd != 31)
{
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("EOR <Xd|SP>, <Xn>, #<imm>")] [Test, Pairwise, Description("EOR <Xd|SP>, <Xn>, #<imm>")]
public void Eor_N1_64bit([Values(0u, 31u)] uint Rd, public void Eor_N1_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm> [Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm> [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0xD2400000; // EOR X0, X0, #0x1 uint Opcode = 0xD2400000; // EOR X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.Eor_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("EOR <Xd|SP>, <Xn>, #<imm>")] [Test, Pairwise, Description("EOR <Xd|SP>, <Xn>, #<imm>")]
public void Eor_N0_64bit([Values(0u, 31u)] uint Rd, public void Eor_N0_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0xD2000000; // EOR X0, X0, #0x100000001 uint Opcode = 0xD2000000; // EOR X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.Eor_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("EOR <Wd>, <Wn>, #<imm>")] [Test, Pairwise, Description("EOR <Wd>, <Wn>, #<imm>")]
public void Eor_32bit([Values(0u, 31u)] uint Rd, public void Eor_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0x52000000; // EOR W0, W0, #0x1 uint Opcode = 0x52000000; // EOR W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
AArch64.X((int)Rn, new Bits(Wn));
Base.Eor_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint WSP = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ORR <Xd|SP>, <Xn>, #<imm>")] [Test, Pairwise, Description("ORR <Xd|SP>, <Xn>, #<imm>")]
public void Orr_N1_64bit([Values(0u, 31u)] uint Rd, public void Orr_N1_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm> [Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm> [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0xB2400000; // ORR X0, X0, #0x1 uint Opcode = 0xB2400000; // ORR X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.Orr_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ORR <Xd|SP>, <Xn>, #<imm>")] [Test, Pairwise, Description("ORR <Xd|SP>, <Xn>, #<imm>")]
public void Orr_N0_64bit([Values(0u, 31u)] uint Rd, public void Orr_N0_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0xB2000000; // ORR X0, X0, #0x100000001 uint Opcode = 0xB2000000; // ORR X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
AArch64.X((int)Rn, new Bits(Xn));
Base.Orr_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("ORR <Wd|WSP>, <Wn>, #<imm>")] [Test, Pairwise, Description("ORR <Wd|WSP>, <Wn>, #<imm>")]
public void Orr_32bit([Values(0u, 31u)] uint Rd, public void Orr_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm> [Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm> [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{ {
uint Opcode = 0x32000000; // ORR W0, W0, #0x1 uint Opcode = 0x32000000; // ORR W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
AArch64.X((int)Rn, new Bits(Wn));
Base.Orr_Imm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint WSP = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SUB <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("SUB <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}")]
public void Sub_64bit([Values(0u, 31u)] uint Rd, public void Sub_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0xD1000000; // SUB X0, X0, #0, LSL #0 uint Opcode = 0xD1000000; // SUB X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Xn_SP); ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Xn_SP); ThreadState = SingleOpcode(Opcode, X31: Xn_SP);
AArch64.SP(new Bits(Xn_SP));
} }
Base.Sub_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong SP = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SUB <Wd|WSP>, <Wn|WSP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("SUB <Wd|WSP>, <Wn|WSP>, #<imm>{, <shift>}")]
public void Sub_32bit([Values(0u, 31u)] uint Rd, public void Sub_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0x51000000; // SUB W0, W0, #0, LSL #0 uint Opcode = 0x51000000; // SUB W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP); ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Wn_WSP); ThreadState = SingleOpcode(Opcode, X31: Wn_WSP);
AArch64.SP(new Bits(Wn_WSP));
} }
Base.Sub_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint WSP = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SUBS <Xd>, <Xn|SP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("SUBS <Xd>, <Xn|SP>, #<imm>{, <shift>}")]
public void Subs_64bit([Values(0u, 31u)] uint Rd, public void Subs_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0xF1000000; // SUBS X0, X0, #0, LSL #0 uint Opcode = 0xF1000000; // SUBS X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Xn_SP); ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Xn_SP); ThreadState = SingleOpcode(Opcode, X31: Xn_SP);
AArch64.SP(new Bits(Xn_SP));
} }
Base.Subs_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
ulong _X31 = AArch64.SP(64).ToUInt64();
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SUBS <Wd>, <Wn|WSP>, #<imm>{, <shift>}")] [Test, Pairwise, Description("SUBS <Wd>, <Wn|WSP>, #<imm>{, <shift>}")]
public void Subs_32bit([Values(0u, 31u)] uint Rd, public void Subs_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm, [Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12> [Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{ {
uint Opcode = 0x71000000; // SUBS W0, W0, #0, LSL #0 uint Opcode = 0x71000000; // SUBS W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10); Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState; AThreadState ThreadState;
if (Rn != 31) if (Rn != 31)
{ {
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP); ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
} }
else else
{ {
ThreadState = SingleOpcode(Opcode, X31: Wn_WSP); ThreadState = SingleOpcode(Opcode, X31: Wn_WSP);
AArch64.SP(new Bits(Wn_WSP));
} }
Base.Subs_Imm(Op[31], Op[23, 22], Op[21, 10], Op[9, 5], Op[4, 0]);
if (Rd != 31)
{
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
uint _W31 = AArch64.SP(32).ToUInt32();
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
//#define Bfm #define Bfm
using ChocolArm64.State; using ChocolArm64.State;
@ -6,212 +6,127 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("Bfm")] // Tested: second half of 2018.
using Tester.Types;
[Category("Bfm"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestBfm : CpuTest public sealed class CpuTestBfm : CpuTest
{ {
#if Bfm #if Bfm
[SetUp] private const int RndCnt = 2;
public void SetupTester() private const int RndCntImmr = 2;
{ private const int RndCntImms = 2;
AArch64.TakeReset(false);
}
[Test, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")] [Test, Pairwise, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Bfm_64bit([Values(0u, 31u)] uint Rd, public void Bfm_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Random(2)] ulong _Xd, [Random(RndCnt)] ulong _Xd,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr, [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint imms) [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
{ {
uint Opcode = 0xB3400000; // BFM X0, X0, #0, #0 uint Opcode = 0xB3400000; // BFM X0, X0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rd, new Bits(_Xd));
AArch64.X((int)Rn, new Bits(Xn));
Base.Bfm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("BFM <Wd>, <Wn>, #<immr>, #<imms>")] [Test, Pairwise, Description("BFM <Wd>, <Wn>, #<immr>, #<imms>")]
public void Bfm_32bit([Values(0u, 31u)] uint Rd, public void Bfm_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Random(2)] uint _Wd, [Random(RndCnt)] uint _Wd,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr, [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint imms) [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
{ {
uint Opcode = 0x33000000; // BFM W0, W0, #0, #0 uint Opcode = 0x33000000; // BFM W0, W0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rd, new Bits(_Wd));
AArch64.X((int)Rn, new Bits(Wn));
Base.Bfm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SBFM <Xd>, <Xn>, #<immr>, #<imms>")] [Test, Pairwise, Description("SBFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Sbfm_64bit([Values(0u, 31u)] uint Rd, public void Sbfm_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr, [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint imms) [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
{ {
uint Opcode = 0x93400000; // SBFM X0, X0, #0, #0 uint Opcode = 0x93400000; // SBFM X0, X0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Sbfm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SBFM <Wd>, <Wn>, #<immr>, #<imms>")] [Test, Pairwise, Description("SBFM <Wd>, <Wn>, #<immr>, #<imms>")]
public void Sbfm_32bit([Values(0u, 31u)] uint Rd, public void Sbfm_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr, [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint imms) [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
{ {
uint Opcode = 0x13000000; // SBFM W0, W0, #0, #0 uint Opcode = 0x13000000; // SBFM W0, W0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Sbfm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("UBFM <Xd>, <Xn>, #<immr>, #<imms>")] [Test, Pairwise, Description("UBFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Ubfm_64bit([Values(0u, 31u)] uint Rd, public void Ubfm_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr, [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint imms) [Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
{ {
uint Opcode = 0xD3400000; // UBFM X0, X0, #0, #0 uint Opcode = 0xD3400000; // UBFM X0, X0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Ubfm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("UBFM <Wd>, <Wn>, #<immr>, #<imms>")] [Test, Pairwise, Description("UBFM <Wd>, <Wn>, #<immr>, #<imms>")]
public void Ubfm_32bit([Values(0u, 31u)] uint Rd, public void Ubfm_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr, [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint imms) [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
{ {
uint Opcode = 0x53000000; // UBFM W0, W0, #0, #0 uint Opcode = 0x53000000; // UBFM W0, W0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10); Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Ubfm(Op[31], Op[22], Op[21, 16], Op[15, 10], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

View file

@ -1,4 +1,4 @@
//#define CcmpImm #define CcmpImm
using ChocolArm64.State; using ChocolArm64.State;
@ -6,25 +6,20 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("CcmpImm")] // Tested: second half of 2018.
using Tester.Types;
[Category("CcmpImm"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestCcmpImm : CpuTest public sealed class CpuTestCcmpImm : CpuTest
{ {
#if CcmpImm #if CcmpImm
[SetUp] private const int RndCnt = 2;
public void SetupTester() private const int RndCntImm = 2;
{ private const int RndCntNzcv = 2;
AArch64.TakeReset(false);
}
[Test, Description("CCMN <Xn>, #<imm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMN <Xn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmn_64bit([Values(1u, 31u)] uint Rn, public void Ccmn_64bit([Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm, [Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -35,29 +30,18 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Ccmn_Imm(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CCMN <Wn>, #<imm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMN <Wn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmn_32bit([Values(1u, 31u)] uint Rn, public void Ccmn_32bit([Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm, [Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -68,29 +52,18 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Ccmn_Imm(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CCMP <Xn>, #<imm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMP <Xn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmp_64bit([Values(1u, 31u)] uint Rn, public void Ccmp_64bit([Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm, [Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -101,29 +74,18 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X31: _X31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
Base.Ccmp_Imm(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CCMP <Wn>, #<imm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMP <Wn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmp_32bit([Values(1u, 31u)] uint Rn, public void Ccmp_32bit([Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm, [Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -134,20 +96,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((imm & 31) << 16) | ((cond & 15) << 12) | ((nzcv & 15) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X31: _W31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
Base.Ccmp_Imm(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

View file

@ -1,4 +1,4 @@
//#define CcmpReg #define CcmpReg
using ChocolArm64.State; using ChocolArm64.State;
@ -6,27 +6,21 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("CcmpReg")] // Tested: second half of 2018.
using Tester.Types;
[Category("CcmpReg"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestCcmpReg : CpuTest public sealed class CpuTestCcmpReg : CpuTest
{ {
#if CcmpReg #if CcmpReg
[SetUp] private const int RndCnt = 2;
public void SetupTester() private const int RndCntNzcv = 2;
{
AArch64.TakeReset(false);
}
[Test, Description("CCMN <Xn>, <Xm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMN <Xn>, <Xm>, #<nzcv>, <cond>")]
public void Ccmn_64bit([Values(1u, 31u)] uint Rn, public void Ccmn_64bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -37,32 +31,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Ccmn_Reg(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CCMN <Wn>, <Wm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMN <Wn>, <Wm>, #<nzcv>, <cond>")]
public void Ccmn_32bit([Values(1u, 31u)] uint Rn, public void Ccmn_32bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -73,32 +55,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
Base.Ccmn_Reg(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CCMP <Xn>, <Xm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMP <Xn>, <Xm>, #<nzcv>, <cond>")]
public void Ccmp_64bit([Values(1u, 31u)] uint Rn, public void Ccmp_64bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -109,32 +79,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Ccmp_Reg(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CCMP <Wn>, <Wm>, #<nzcv>, <cond>")] [Test, Pairwise, Description("CCMP <Wn>, <Wm>, #<nzcv>, <cond>")]
public void Ccmp_32bit([Values(1u, 31u)] uint Rn, public void Ccmp_32bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Random(0u, 15u, 1)] uint nzcv, [Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -145,21 +103,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0); Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
Base.Ccmp_Reg(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[3, 0]);
Assert.Multiple(() =>
{
Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
});
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

View file

@ -1,4 +1,4 @@
//#define Csel #define Csel
using ChocolArm64.State; using ChocolArm64.State;
@ -6,27 +6,20 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("Csel")] // Tested: second half of 2018.
using Tester.Types;
[Category("Csel"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestCsel : CpuTest public sealed class CpuTestCsel : CpuTest
{ {
#if Csel #if Csel
[SetUp] private const int RndCnt = 2;
public void SetupTester()
{
AArch64.TakeReset(false);
}
[Test, Description("CSEL <Xd>, <Xn>, <Xm>, <cond>")] [Test, Pairwise, Description("CSEL <Xd>, <Xn>, <Xm>, <cond>")]
public void Csel_64bit([Values(0u, 31u)] uint Rd, public void Csel_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -37,34 +30,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Csel(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSEL <Wd>, <Wn>, <Wm>, <cond>")] [Test, Pairwise, Description("CSEL <Wd>, <Wn>, <Wm>, <cond>")]
public void Csel_32bit([Values(0u, 31u)] uint Rd, public void Csel_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -75,34 +54,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
Base.Csel(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSINC <Xd>, <Xn>, <Xm>, <cond>")] [Test, Pairwise, Description("CSINC <Xd>, <Xn>, <Xm>, <cond>")]
public void Csinc_64bit([Values(0u, 31u)] uint Rd, public void Csinc_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -113,34 +78,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Csinc(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSINC <Wd>, <Wn>, <Wm>, <cond>")] [Test, Pairwise, Description("CSINC <Wd>, <Wn>, <Wm>, <cond>")]
public void Csinc_32bit([Values(0u, 31u)] uint Rd, public void Csinc_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -151,34 +102,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
Base.Csinc(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSINV <Xd>, <Xn>, <Xm>, <cond>")] [Test, Pairwise, Description("CSINV <Xd>, <Xn>, <Xm>, <cond>")]
public void Csinv_64bit([Values(0u, 31u)] uint Rd, public void Csinv_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -189,34 +126,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Csinv(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSINV <Wd>, <Wn>, <Wm>, <cond>")] [Test, Pairwise, Description("CSINV <Wd>, <Wn>, <Wm>, <cond>")]
public void Csinv_32bit([Values(0u, 31u)] uint Rd, public void Csinv_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -227,34 +150,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
Base.Csinv(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSNEG <Xd>, <Xn>, <Xm>, <cond>")] [Test, Pairwise, Description("CSNEG <Xd>, <Xn>, <Xm>, <cond>")]
public void Csneg_64bit([Values(0u, 31u)] uint Rd, public void Csneg_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -265,34 +174,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Csneg(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("CSNEG <Wd>, <Wn>, <Wm>, <cond>")] [Test, Pairwise, Description("CSNEG <Wd>, <Wn>, <Wm>, <cond>")]
public void Csneg_32bit([Values(0u, 31u)] uint Rd, public void Csneg_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO, [Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC, 0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT, 0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -303,23 +198,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12); Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
Base.Csneg(Op[31], Op[20, 16], Op[15, 12], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

View file

@ -88,7 +88,7 @@ namespace Ryujinx.Tests.Cpu
Opcode(0xD65F03C0); Opcode(0xD65F03C0);
ExecuteOpcodes(); ExecuteOpcodes();
Assert.That(Sse41.Extract(GetThreadState().V0, 0), Is.EqualTo(16f)); Assert.That(Sse41.Extract(GetThreadState().V0, (byte)0), Is.EqualTo(16f));
} }
[TestCase(-20d, -5d)] // 18 integer solutions. [TestCase(-20d, -5d)] // 18 integer solutions.
@ -137,7 +137,7 @@ namespace Ryujinx.Tests.Cpu
Opcode(0xD65F03C0); Opcode(0xD65F03C0);
ExecuteOpcodes(); ExecuteOpcodes();
Assert.That(VectorExtractDouble(GetThreadState().V0, 0), Is.EqualTo(16d)); Assert.That(VectorExtractDouble(GetThreadState().V0, (byte)0), Is.EqualTo(16d));
} }
[Test] [Test]
@ -163,27 +163,27 @@ namespace Ryujinx.Tests.Cpu
} }
/* /*
0x0000000000000000: MOV W4, W0 0x0000000000001000: MOV W4, W0
0x0000000000000004: CBZ W0, #0x3C 0x0000000000001004: CBZ W0, #0x3C
0x0000000000000008: CMP W0, #1 0x0000000000001008: CMP W0, #1
0x000000000000000C: B.LS #0x48 0x000000000000100C: B.LS #0x48
0x0000000000000010: MOVZ W2, #0x2 0x0000000000001010: MOVZ W2, #0x2
0x0000000000000014: MOVZ X1, #0x1 0x0000000000001014: MOVZ X1, #0x1
0x0000000000000018: MOVZ X3, #0 0x0000000000001018: MOVZ X3, #0
0x000000000000001C: ADD X0, X3, X1 0x000000000000101C: ADD X0, X3, X1
0x0000000000000020: ADD W2, W2, #1 0x0000000000001020: ADD W2, W2, #1
0x0000000000000024: MOV X3, X1 0x0000000000001024: MOV X3, X1
0x0000000000000028: MOV X1, X0 0x0000000000001028: MOV X1, X0
0x000000000000002C: CMP W4, W2 0x000000000000102C: CMP W4, W2
0x0000000000000030: B.HS #0x1C 0x0000000000001030: B.HS #0x1C
0x0000000000000034: BRK #0 0x0000000000001034: BRK #0
0x0000000000000038: RET 0x0000000000001038: RET
0x000000000000003C: MOVZ X0, #0 0x000000000000103C: MOVZ X0, #0
0x0000000000000040: BRK #0 0x0000000000001040: BRK #0
0x0000000000000044: RET 0x0000000000001044: RET
0x0000000000000048: MOVZ X0, #0x1 0x0000000000001048: MOVZ X0, #0x1
0x000000000000004C: BRK #0 0x000000000000104C: BRK #0
0x0000000000000050: RET 0x0000000000001050: RET
*/ */
SetThreadState(X0: A); SetThreadState(X0: A);
@ -219,11 +219,11 @@ namespace Ryujinx.Tests.Cpu
const ulong Result = 5; const ulong Result = 5;
/* /*
0x0000000000000000: MOV X0, #2 0x0000000000001000: MOV X0, #2
0x0000000000000004: MOV X1, #3 0x0000000000001004: MOV X1, #3
0x0000000000000008: ADD X0, X0, X1 0x0000000000001008: ADD X0, X0, X1
0x000000000000000C: BRK #0 0x000000000000100C: BRK #0
0x0000000000000010: RET 0x0000000000001010: RET
*/ */
Opcode(0xD2800040); Opcode(0xD2800040);
@ -238,11 +238,11 @@ namespace Ryujinx.Tests.Cpu
Reset(); Reset();
/* /*
0x0000000000000000: MOV X0, #3 0x0000000000001000: MOV X0, #3
0x0000000000000004: MOV X1, #2 0x0000000000001004: MOV X1, #2
0x0000000000000008: ADD X0, X0, X1 0x0000000000001008: ADD X0, X0, X1
0x000000000000000C: BRK #0 0x000000000000100C: BRK #0
0x0000000000000010: RET 0x0000000000001010: RET
*/ */
Opcode(0xD2800060); Opcode(0xD2800060);

View file

@ -1,4 +1,4 @@
//#define Mov #define Mov
using ChocolArm64.State; using ChocolArm64.State;
@ -6,23 +6,16 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("Mov")] // Tested: second half of 2018.
using Tester.Types;
[Category("Mov"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestMov : CpuTest public sealed class CpuTestMov : CpuTest
{ {
#if Mov #if Mov
[SetUp] private const int RndCntImm = 2;
public void SetupTester()
{
AArch64.TakeReset(false);
}
[Test, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")]
public void Movk_64bit([Values(0u, 31u)] uint Rd, public void Movk_64bit([Values(0u, 31u)] uint Rd,
[Random(12)] ulong _Xd, [Random(RndCntImm)] ulong _Xd,
[Values(0u, 65535u)] [Random(0u, 65535u, 10)] uint imm, [Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift) [Values(0u, 16u, 32u, 48u)] uint shift)
{ {
uint Opcode = 0xF2800000; // MOVK X0, #0, LSL #0 uint Opcode = 0xF2800000; // MOVK X0, #0, LSL #0
@ -30,29 +23,16 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5); Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X0: _Xd, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rd, new Bits(_Xd));
Base.Movk(Op[31], Op[22, 21], Op[20, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MOVK <Wd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVK <Wd>, #<imm>{, LSL #<shift>}")]
public void Movk_32bit([Values(0u, 31u)] uint Rd, public void Movk_32bit([Values(0u, 31u)] uint Rd,
[Random(12)] uint _Wd, [Random(RndCntImm)] uint _Wd,
[Values(0u, 65535u)] [Random(0u, 65535u, 10)] uint imm, [Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u)] uint shift) [Values(0u, 16u)] uint shift)
{ {
uint Opcode = 0x72800000; // MOVK W0, #0, LSL #0 uint Opcode = 0x72800000; // MOVK W0, #0, LSL #0
@ -60,28 +40,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5); Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X0: _Wd, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rd, new Bits(_Wd));
Base.Movk(Op[31], Op[22, 21], Op[20, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MOVN <Xd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVN <Xd>, #<imm>{, LSL #<shift>}")]
public void Movn_64bit([Values(0u, 31u)] uint Rd, public void Movn_64bit([Values(0u, 31u)] uint Rd,
[Values(0u, 65535u)] [Random(0u, 65535u, 128)] uint imm, [Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift) [Values(0u, 16u, 32u, 48u)] uint shift)
{ {
uint Opcode = 0x92800000; // MOVN X0, #0, LSL #0 uint Opcode = 0x92800000; // MOVN X0, #0, LSL #0
@ -89,27 +56,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5); Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
Base.Movn(Op[31], Op[22, 21], Op[20, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MOVN <Wd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVN <Wd>, #<imm>{, LSL #<shift>}")]
public void Movn_32bit([Values(0u, 31u)] uint Rd, public void Movn_32bit([Values(0u, 31u)] uint Rd,
[Values(0u, 65535u)] [Random(0u, 65535u, 128)] uint imm, [Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u)] uint shift) [Values(0u, 16u)] uint shift)
{ {
uint Opcode = 0x12800000; // MOVN W0, #0, LSL #0 uint Opcode = 0x12800000; // MOVN W0, #0, LSL #0
@ -117,27 +72,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5); Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
Base.Movn(Op[31], Op[22, 21], Op[20, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MOVZ <Xd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVZ <Xd>, #<imm>{, LSL #<shift>}")]
public void Movz_64bit([Values(0u, 31u)] uint Rd, public void Movz_64bit([Values(0u, 31u)] uint Rd,
[Values(0u, 65535u)] [Random(0u, 65535u, 128)] uint imm, [Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift) [Values(0u, 16u, 32u, 48u)] uint shift)
{ {
uint Opcode = 0xD2800000; // MOVZ X0, #0, LSL #0 uint Opcode = 0xD2800000; // MOVZ X0, #0, LSL #0
@ -145,27 +88,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5); Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
Base.Movz(Op[31], Op[22, 21], Op[20, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MOVZ <Wd>, #<imm>{, LSL #<shift>}")] [Test, Pairwise, Description("MOVZ <Wd>, #<imm>{, LSL #<shift>}")]
public void Movz_32bit([Values(0u, 31u)] uint Rd, public void Movz_32bit([Values(0u, 31u)] uint Rd,
[Values(0u, 65535u)] [Random(0u, 65535u, 128)] uint imm, [Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u)] uint shift) [Values(0u, 16u)] uint shift)
{ {
uint Opcode = 0x52800000; // MOVZ W0, #0, LSL #0 uint Opcode = 0x52800000; // MOVZ W0, #0, LSL #0
@ -173,21 +104,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5); Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
Base.Movz(Op[31], Op[22, 21], Op[20, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

View file

@ -1,4 +1,4 @@
//#define Mul #define Mul
using ChocolArm64.State; using ChocolArm64.State;
@ -6,378 +6,223 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
using Tester; [Category("Mul")] // Tested: second half of 2018.
using Tester.Types;
[Category("Mul"), Ignore("Tested: second half of 2018.")]
public sealed class CpuTestMul : CpuTest public sealed class CpuTestMul : CpuTest
{ {
#if Mul #if Mul
[SetUp] private const int RndCnt = 2;
public void SetupTester()
{
AArch64.TakeReset(false);
}
[Test, Description("MADD <Xd>, <Xn>, <Xm>, <Xa>")] [Test, Pairwise, Description("MADD <Xd>, <Xn>, <Xm>, <Xa>")]
public void Madd_64bit([Values(0u, 31u)] uint Rd, public void Madd_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{ {
uint Opcode = 0x9B000000; // MADD X0, X0, X0, X0 uint Opcode = 0x9B000000; // MADD X0, X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
AArch64.X((int)Ra, new Bits(Xa));
Base.Madd(Op[31], Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MADD <Wd>, <Wn>, <Wm>, <Wa>")] [Test, Pairwise, Description("MADD <Wd>, <Wn>, <Wm>, <Wa>")]
public void Madd_32bit([Values(0u, 31u)] uint Rd, public void Madd_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wa) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wa)
{ {
uint Opcode = 0x1B000000; // MADD W0, W0, W0, W0 uint Opcode = 0x1B000000; // MADD W0, W0, W0, W0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
AArch64.X((int)Ra, new Bits(Wa));
Base.Madd(Op[31], Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MSUB <Xd>, <Xn>, <Xm>, <Xa>")] [Test, Pairwise, Description("MSUB <Xd>, <Xn>, <Xm>, <Xa>")]
public void Msub_64bit([Values(0u, 31u)] uint Rd, public void Msub_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xm, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{ {
uint Opcode = 0x9B008000; // MSUB X0, X0, X0, X0 uint Opcode = 0x9B008000; // MSUB X0, X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X3: Xa, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
AArch64.X((int)Ra, new Bits(Xa));
Base.Msub(Op[31], Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("MSUB <Wd>, <Wn>, <Wm>, <Wa>")] [Test, Pairwise, Description("MSUB <Wd>, <Wn>, <Wm>, <Wa>")]
public void Msub_32bit([Values(0u, 31u)] uint Rd, public void Msub_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wa) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wa)
{ {
uint Opcode = 0x1B008000; // MSUB W0, W0, W0, W0 uint Opcode = 0x1B008000; // MSUB W0, W0, W0, W0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt(); uint _W31 = TestContext.CurrentContext.Random.NextUInt();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Wa, X31: _W31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
AArch64.X((int)Ra, new Bits(Wa));
Base.Msub(Op[31], Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
}
else
{
Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SMADDL <Xd>, <Wn>, <Wm>, <Xa>")] [Test, Pairwise, Description("SMADDL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Smaddl_64bit([Values(0u, 31u)] uint Rd, public void Smaddl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{ {
uint Opcode = 0x9B200000; // SMADDL X0, W0, W0, X0 uint Opcode = 0x9B200000; // SMADDL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
AArch64.X((int)Ra, new Bits(Xa));
Base.Smaddl(Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("UMADDL <Xd>, <Wn>, <Wm>, <Xa>")] [Test, Pairwise, Description("UMADDL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Umaddl_64bit([Values(0u, 31u)] uint Rd, public void Umaddl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{ {
uint Opcode = 0x9BA00000; // UMADDL X0, W0, W0, X0 uint Opcode = 0x9BA00000; // UMADDL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
AArch64.X((int)Ra, new Bits(Xa));
Base.Umaddl(Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SMSUBL <Xd>, <Wn>, <Wm>, <Xa>")] [Test, Pairwise, Description("SMSUBL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Smsubl_64bit([Values(0u, 31u)] uint Rd, public void Smsubl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{ {
uint Opcode = 0x9B208000; // SMSUBL X0, W0, W0, X0 uint Opcode = 0x9B208000; // SMSUBL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
AArch64.X((int)Ra, new Bits(Xa));
Base.Smsubl(Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("UMSUBL <Xd>, <Wn>, <Wm>, <Xa>")] [Test, Pairwise, Description("UMSUBL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Umsubl_64bit([Values(0u, 31u)] uint Rd, public void Umsubl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra, [Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{ {
uint Opcode = 0x9BA08000; // UMSUBL X0, W0, W0, X0 uint Opcode = 0x9BA08000; // UMSUBL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn, X2: Wm, X3: Xa, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Wn));
AArch64.X((int)Rm, new Bits(Wm));
AArch64.X((int)Ra, new Bits(Xa));
Base.Umsubl(Op[20, 16], Op[14, 10], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("SMULH <Xd>, <Xn>, <Xm>")] [Test, Pairwise, Description("SMULH <Xd>, <Xn>, <Xm>")]
public void Smulh_64bit([Values(0u, 31u)] uint Rd, public void Smulh_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xm) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm)
{ {
uint Opcode = 0x9B407C00; // SMULH X0, X0, X0 uint Opcode = 0x9B407C00; // SMULH X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Smulh(Op[20, 16], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("UMULH <Xd>, <Xn>, <Xm>")] [Test, Pairwise, Description("UMULH <Xd>, <Xn>, <Xm>")]
public void Umulh_64bit([Values(0u, 31u)] uint Rd, public void Umulh_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn, [Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm, [Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xn, 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul, [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xm) 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm)
{ {
uint Opcode = 0x9BC07C00; // UMULH X0, X0, X0 uint Opcode = 0x9BC07C00; // UMULH X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong(); ulong _X31 = TestContext.CurrentContext.Random.NextULong();
AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31); AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn, X2: Xm, X31: _X31);
if (Rd != 31)
{
Bits Op = new Bits(Opcode);
AArch64.X((int)Rn, new Bits(Xn));
AArch64.X((int)Rm, new Bits(Xm));
Base.Umulh(Op[20, 16], Op[9, 5], Op[4, 0]);
ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
}
else
{
Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
}
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
{ {
public class CpuTestSimdArithmetic : CpuTest public class CpuTestSimdArithmetic : CpuTest
{ {
[TestCase(0x1E224820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x1E224820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000000000000ul)] // FMAX S0, S1, S2
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000000000000ul)] [TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000000000000ul)]
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)] [TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x000000003DCCCCCDul)] [TestCase(0x1E224820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x000000003DCCCCCDul)]
@ -22,17 +22,19 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x1E224820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul)] [TestCase(0x1E224820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul)]
[TestCase(0x1E224820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul)] [TestCase(0x1E224820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul)]
[TestCase(0x1E224820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul)] [TestCase(0x1E224820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul)]
[TestCase(0x1E624820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x0000000000000000ul)] [TestCase(0x1E624820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x0000000000000000ul)] // FMAX D0, D1, D2
[TestCase(0x1E624820u, 0x8000000000000000ul, 0x0000000000000000ul, 0x0000000000000000ul)] [TestCase(0x1E624820u, 0x8000000000000000ul, 0x0000000000000000ul, 0x0000000000000000ul)]
[TestCase(0x1E624820u, 0x8000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)] [TestCase(0x1E624820u, 0x8000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)]
[TestCase(0x1E624820u, 0x8000000000000000ul, 0x3FF3333333333333ul, 0x3FF3333333333333ul)] [TestCase(0x1E624820u, 0x8000000000000000ul, 0x3FF3333333333333ul, 0x3FF3333333333333ul)]
public void Fmax_S(uint Opcode, ulong A, ulong B, ulong Result) public void Fmax_S(uint Opcode, ulong A, ulong B, ulong Result)
{ {
// FMAX S0, S1, S2 Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(Opcode, Vector128<float> V2 = MakeVectorE0(B);
V1: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, A)),
V2: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, B))); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.AreEqual(Result, Sse41.Extract(Sse.StaticCast<float, ulong>(ThreadState.V0), 0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -51,19 +53,23 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC0000Au, 0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Bu, 0x7FC0000Au, 0x7FC0000Au)] [TestCase(0x7FC0000Au, 0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Bu, 0x7FC0000Au, 0x7FC0000Au)]
public void Fmax_V(uint A, uint B, uint C, uint D, uint Result0, uint Result1) public void Fmax_V(uint A, uint B, uint C, uint D, uint Result0, uint Result1)
{ {
uint Opcode = 0x4E22F420; uint Opcode = 0x4E22F420; // FMAX V0.4S, V1.4S, V2.4S
Vector128<float> V1 = MakeVectorE0E1(A, B); Vector128<float> V1 = MakeVectorE0E1(A, B);
Vector128<float> V2 = MakeVectorE0E1(C, D); Vector128<float> V2 = MakeVectorE0E1(C, D);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x1E225820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000080000000ul)] [TestCase(0x1E225820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000080000000ul)] // FMIN S0, S1, S2
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000080000000ul)] [TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000080000000ul)]
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)] [TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x0000000080000000ul)] [TestCase(0x1E225820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x0000000080000000ul)]
@ -76,17 +82,19 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x1E225820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul)] [TestCase(0x1E225820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul)]
[TestCase(0x1E225820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul)] [TestCase(0x1E225820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul)]
[TestCase(0x1E225820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul)] [TestCase(0x1E225820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul)]
[TestCase(0x1E625820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)] [TestCase(0x1E625820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)] // FMIN D0, D1, D2
[TestCase(0x1E625820u, 0x8000000000000000ul, 0x0000000000000000ul, 0x8000000000000000ul)] [TestCase(0x1E625820u, 0x8000000000000000ul, 0x0000000000000000ul, 0x8000000000000000ul)]
[TestCase(0x1E625820u, 0x8000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)] [TestCase(0x1E625820u, 0x8000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)]
[TestCase(0x1E625820u, 0x8000000000000000ul, 0x3FF3333333333333ul, 0x8000000000000000ul)] [TestCase(0x1E625820u, 0x8000000000000000ul, 0x3FF3333333333333ul, 0x8000000000000000ul)]
public void Fmin_S(uint Opcode, ulong A, ulong B, ulong Result) public void Fmin_S(uint Opcode, ulong A, ulong B, ulong Result)
{ {
// FMIN S0, S1, S2 Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(Opcode, Vector128<float> V2 = MakeVectorE0(B);
V1: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, A)),
V2: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, B))); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.AreEqual(Result, Sse41.Extract(Sse.StaticCast<float, ulong>(ThreadState.V0), 0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -105,15 +113,19 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC0000Au, 0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Bu, 0x7FC0000Au, 0x7FC0000Au)] [TestCase(0x7FC0000Au, 0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Bu, 0x7FC0000Au, 0x7FC0000Au)]
public void Fmin_V(uint A, uint B, uint C, uint D, uint Result0, uint Result1) public void Fmin_V(uint A, uint B, uint C, uint D, uint Result0, uint Result1)
{ {
uint Opcode = 0x4EA2F420; uint Opcode = 0x4EA2F420; // FMIN V0.4S, V1.4S, V2.4S
Vector128<float> V1 = MakeVectorE0E1(A, B); Vector128<float> V1 = MakeVectorE0E1(A, B);
Vector128<float> V2 = MakeVectorE0E1(C, D); Vector128<float> V2 = MakeVectorE0E1(C, D);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -125,6 +137,7 @@ namespace Ryujinx.Tests.Cpu
V0: Sse.SetVector128(0, B, 0, 0)); V0: Sse.SetVector128(0, B, 0, 0));
Assert.That(Sse41.Extract(ThreadState.V6, (byte)0), Is.EqualTo(A * B)); Assert.That(Sse41.Extract(ThreadState.V6, (byte)0), Is.EqualTo(A * B));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -137,21 +150,27 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x007FF000u, 0x7E800000u)] [TestCase(0x007FF000u, 0x7E800000u)]
public void Frecpe_S(uint A, uint Result) public void Frecpe_S(uint A, uint Result)
{ {
uint Opcode = 0x5EA1D820; // FRECPE S0, S1
Vector128<float> V1 = MakeVectorE0(A); Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x5EA1D820, V1: V1);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0)); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FRECPS D0, D1, D2")] [Test, Description("FRECPS D0, D1, D2"), Ignore("Not accurate enough.")]
public void Frecps_S([Random(10)] double A, [Random(10)] double B) public void Frecps_S([Random(10)] double A, [Random(10)] double B)
{ {
AThreadState ThreadState = SingleOpcode(0x5E62FC20, AThreadState ThreadState = SingleOpcode(0x5E62FC20,
V1: MakeVectorE0(A), V1: MakeVectorE0(A),
V2: MakeVectorE0(B)); V2: MakeVectorE0(B));
Assert.That(VectorExtractDouble(ThreadState.V0, 0), Is.EqualTo(2 - (A * B))); Assert.That(VectorExtractDouble(ThreadState.V0, (byte)0), Is.EqualTo(2 - (A * B)));
//CompareAgainstUnicorn(); // Not accurate enough
CompareAgainstUnicorn();
} }
[Test, Description("FRECPS V4.4S, V2.4S, V0.4S")] [Test, Description("FRECPS V4.4S, V2.4S, V0.4S")]
@ -170,6 +189,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Sse41.Extract(ThreadState.V4, (byte)2), Is.EqualTo(Result)); Assert.That(Sse41.Extract(ThreadState.V4, (byte)2), Is.EqualTo(Result));
Assert.That(Sse41.Extract(ThreadState.V4, (byte)3), Is.EqualTo(Result)); Assert.That(Sse41.Extract(ThreadState.V4, (byte)3), Is.EqualTo(Result));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -177,7 +197,7 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x3F99999Au, false, 0x3F800000u)] [TestCase(0x3F99999Au, false, 0x3F800000u)]
[TestCase(0x404CCCCDu, false, 0x40400000u)] [TestCase(0x404CCCCDu, false, 0x40400000u)]
[TestCase(0x40733333u, false, 0x40800000u)] [TestCase(0x40733333u, false, 0x40800000u)]
[TestCase(0x3fc00000u, false, 0x40000000u)] [TestCase(0x3FC00000u, false, 0x40000000u)]
[TestCase(0x40200000u, false, 0x40400000u)] [TestCase(0x40200000u, false, 0x40400000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
@ -213,42 +233,53 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")] [TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frinta_S(uint A, bool DefaultNaN, uint Result) public void Frinta_S(uint A, bool DefaultNaN, uint Result)
{ {
uint Opcode = 0x1E264020; // FRINTA S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E264020, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x6E618820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [Ignore("Wrong opcodes.")]
[TestCase(0x6E618820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] // FRINTA V0.2D, V1.2D
[TestCase(0x6E618820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6E618820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6E618820u, 0x3FF8000000000000ul, 0x3FF8000000000000ul, false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6E618820u, 0x3FF8000000000000ul, 0x3FF8000000000000ul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x3f80000040000000ul)] [TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x3F80000040000000ul)] // FRINTX V0.4S, V1.4S
[TestCase(0x6E219820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)] [TestCase(0x6E219820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x0000000000000000ul)] // FRINTX V0.2S, V1.2S
[TestCase(0x2E219820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2E218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)] // FRINTA V0.2S, V1.2S
[TestCase(0x2E218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)] [TestCase(0x2E218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0x2E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x2E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0x2E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x2E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
public void Frinta_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1) public void Frinta_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1)
{ {
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -294,36 +325,31 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u, Ignore = "NaN test.")] [TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frinti_S(uint A, char RoundType, bool DefaultNaN, uint Result) public void Frinti_S(uint A, char RoundType, bool DefaultNaN, uint Result)
{ {
uint Opcode = 0x1E27C020; // FRINTI S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
switch(RoundType) switch(RoundType)
{ {
case 'N': case 'N': FpcrTemp = 0x0; break;
FpcrTemp = 0x0; case 'P': FpcrTemp = 0x400000; break;
break; case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
} }
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp |= 1 << 25; FpcrTemp |= 1 << 25;
} }
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E27C020, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x6EE19820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'N', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6EE19820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'N', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] // FRINTI V0.2D, V1.2D
[TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'N', false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'N', false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6EE19820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6EE19820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)]
@ -331,14 +357,14 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'M', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'M', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6EE19820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6EE19820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x3f80000040000000ul)] [TestCase(0x6EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'N', false, 0x3F80000040000000ul, 0x3F80000040000000ul)] // FRINTI V0.4S, V1.4S
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x4000000040000000ul)] [TestCase(0x6EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'P', false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)] [TestCase(0x6EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'M', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)] [TestCase(0x6EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'N', false, 0x3F80000040000000ul, 0x0000000000000000ul)] // FRINTI V0.2S, V1.2S
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'P', false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'M', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'N', false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'N', false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'P', false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'P', false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'M', false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'M', false, 0x0000000080000000ul, 0x0000000000000000ul)]
@ -357,36 +383,29 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x2EA19820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, 'Z', true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x2EA19820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, 'Z', true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
public void Frinti_V(uint Opcode, ulong A, ulong B, char RoundType, bool DefaultNaN, ulong Result0, ulong Result1) public void Frinti_V(uint Opcode, ulong A, ulong B, char RoundType, bool DefaultNaN, ulong Result0, ulong Result1)
{ {
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
switch(RoundType) switch(RoundType)
{ {
case 'N': case 'N': FpcrTemp = 0x0; break;
FpcrTemp = 0x0; case 'P': FpcrTemp = 0x400000; break;
break; case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
} }
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp |= 1 << 25; FpcrTemp |= 1 << 25;
} }
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -394,7 +413,7 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x3F99999Au, false, 0x3F800000u)] [TestCase(0x3F99999Au, false, 0x3F800000u)]
[TestCase(0x404CCCCDu, false, 0x40400000u)] [TestCase(0x404CCCCDu, false, 0x40400000u)]
[TestCase(0x40733333u, false, 0x40400000u)] [TestCase(0x40733333u, false, 0x40400000u)]
[TestCase(0x3fc00000u, false, 0x3F800000u)] [TestCase(0x3FC00000u, false, 0x3F800000u)]
[TestCase(0x40200000u, false, 0x40000000u)] [TestCase(0x40200000u, false, 0x40000000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
@ -430,47 +449,58 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")] [TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintm_S(uint A, bool DefaultNaN, uint Result) public void Frintm_S(uint A, bool DefaultNaN, uint Result)
{ {
uint Opcode = 0x1E254020; // FRINTM S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E254020, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x4E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x4E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] // FRINTM V0.2D, V1.2D
[TestCase(0x4E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x4E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x4E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)] [TestCase(0x4E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)] // FRINTM V0.4S, V1.4S
[TestCase(0xE219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f8000003f800000ul, 0x0000000000000000ul)] [TestCase(0x0E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F8000003F800000ul, 0x0000000000000000ul)] // FRINTM V0.2S, V1.2S
[TestCase(0xE219820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x0E219820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0xE219820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)] [TestCase(0x0E219820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0xE219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x0E219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0xE219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x0E219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
public void Frintm_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1) public void Frintm_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1)
{ {
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Ignore("Wrong opcode.")]
[TestCase(0x3FE66666u, false, 0x40000000u)] [TestCase(0x3FE66666u, false, 0x40000000u)]
[TestCase(0x3F99999Au, false, 0x3F800000u)] [TestCase(0x3F99999Au, false, 0x3F800000u)]
[TestCase(0x404CCCCDu, false, 0x40400000u)] [TestCase(0x404CCCCDu, false, 0x40400000u)]
[TestCase(0x40733333u, false, 0x40800000u)] [TestCase(0x40733333u, false, 0x40800000u)]
[TestCase(0x3fc00000u, false, 0x40000000u)] [TestCase(0x3FC00000u, false, 0x40000000u)]
[TestCase(0x40200000u, false, 0x40400000u)] [TestCase(0x40200000u, false, 0x40400000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
@ -506,42 +536,52 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")] [TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintn_S(uint A, bool DefaultNaN, uint Result) public void Frintn_S(uint A, bool DefaultNaN, uint Result)
{ {
uint Opcode = 0x1E264020; // FRINTA S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E264020, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x4E618820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x4E618820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] // FRINTN V0.2D, V1.2D
[TestCase(0x4E618820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x4E618820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x4E618820u, 0x3FF8000000000000ul, 0x3FF8000000000000ul, false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x4E618820u, 0x3FF8000000000000ul, 0x3FF8000000000000ul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x4E218820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x3f80000040000000ul)] [TestCase(0x4E218820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x3F80000040000000ul)] // FRINTN V0.4S, V1.4S
[TestCase(0x4E218820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)] [TestCase(0x4E218820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0xE218820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x0000000000000000ul)] [TestCase(0x0E218820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x0000000000000000ul)] // FRINTN V0.2S, V1.2S
[TestCase(0xE218820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)] [TestCase(0x0E218820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x0E218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)] [TestCase(0x0E218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x0E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0xE218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x0E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
public void Frintn_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1) public void Frintn_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1)
{ {
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -549,7 +589,7 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x3F99999Au, false, 0x40000000u)] [TestCase(0x3F99999Au, false, 0x40000000u)]
[TestCase(0x404CCCCDu, false, 0x40800000u)] [TestCase(0x404CCCCDu, false, 0x40800000u)]
[TestCase(0x40733333u, false, 0x40800000u)] [TestCase(0x40733333u, false, 0x40800000u)]
[TestCase(0x3fc00000u, false, 0x40000000u)] [TestCase(0x3FC00000u, false, 0x40000000u)]
[TestCase(0x40200000u, false, 0x40400000u)] [TestCase(0x40200000u, false, 0x40400000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)] [TestCase(0x00000000u, false, 0x00000000u)]
@ -585,39 +625,49 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")] [TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintp_S(uint A, bool DefaultNaN, uint Result) public void Frintp_S(uint A, bool DefaultNaN, uint Result)
{ {
uint Opcode = 0x1E24C020; // FRINTP S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E24C020, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x4EE18820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x4EE18820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, false, 0x4000000000000000ul, 0x4000000000000000ul)] // FRINTP V0.2D, v1.2D
[TestCase(0x4EE18820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x4EE18820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x4EA18820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x4000000040000000ul, 0x4000000040000000ul)] [TestCase(0x4EA18820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x4000000040000000ul, 0x4000000040000000ul)] // FRINTP V0.4S, v1.4S
[TestCase(0xEA18820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x4000000040000000ul, 0x0000000000000000ul)] [TestCase(0x0EA18820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x4000000040000000ul, 0x0000000000000000ul)] // FRINTP V0.2S, v1.2S
[TestCase(0xEA18820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x0EA18820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0xEA18820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)] [TestCase(0x0EA18820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0xEA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x0EA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0xEA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x0EA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
public void Frintp_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1) public void Frintp_V(uint Opcode, ulong A, ulong B, bool DefaultNaN, ulong Result0, ulong Result1)
{ {
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp = 0x2000000; FpcrTemp = 0x2000000;
} }
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -663,36 +713,31 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u, Ignore = "NaN test.")] [TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintx_S(uint A, char RoundType, bool DefaultNaN, uint Result) public void Frintx_S(uint A, char RoundType, bool DefaultNaN, uint Result)
{ {
uint Opcode = 0x1E274020; // FRINTX S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
switch(RoundType) switch(RoundType)
{ {
case 'N': case 'N': FpcrTemp = 0x0; break;
FpcrTemp = 0x0; case 'P': FpcrTemp = 0x400000; break;
break; case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
} }
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp |= 1 << 25; FpcrTemp |= 1 << 25;
} }
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E274020, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x6E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'N', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'N', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] // FRINTX V0.2D, V1.2D
[TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'N', false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'N', false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)] [TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'P', false, 0x4000000000000000ul, 0x4000000000000000ul)]
@ -700,14 +745,14 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'M', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'M', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6E619820u, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)] [TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x3f80000040000000ul)] [TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'N', false, 0x3F80000040000000ul, 0x3F80000040000000ul)] // FRINTX V0.4S, V1.4S
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x4000000040000000ul)] [TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'P', false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)] [TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'M', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)] [TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'N', false, 0x3F80000040000000ul, 0x0000000000000000ul)] // FRINTX V0.2S, V1.2S
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'P', false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'M', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'N', false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'N', false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'P', false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'P', false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'M', false, 0x0000000080000000ul, 0x0000000000000000ul)] [TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'M', false, 0x0000000080000000ul, 0x0000000000000000ul)]
@ -726,45 +771,43 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x2E219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, 'Z', true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")] [TestCase(0x2E219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, 'Z', true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
public void Frintx_V(uint Opcode, ulong A, ulong B, char RoundType, bool DefaultNaN, ulong Result0, ulong Result1) public void Frintx_V(uint Opcode, ulong A, ulong B, char RoundType, bool DefaultNaN, ulong Result0, ulong Result1)
{ {
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0; int FpcrTemp = 0x0;
switch(RoundType) switch(RoundType)
{ {
case 'N': case 'N': FpcrTemp = 0x0; break;
FpcrTemp = 0x0; case 'P': FpcrTemp = 0x400000; break;
break; case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
} }
if(DefaultNaN) if(DefaultNaN)
{ {
FpcrTemp |= 1 << 25; FpcrTemp |= 1 << 25;
} }
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0)); Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0)); Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[TestCase(0x41200000u, 0x3EA18000u)] [TestCase(0x41200000u, 0x3EA18000u)]
public void Frsqrte_S(uint A, uint Result) public void Frsqrte_S(uint A, uint Result)
{ {
uint Opcode = 0x7EA1D820; // FRSQRTE S0, S1
Vector128<float> V1 = MakeVectorE0(A); Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x7EA1D820, V1: V1);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0)); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
} }

View file

@ -24,12 +24,15 @@ namespace Ryujinx.Tests.Cpu
} }
#endregion #endregion
private const int RndCnt = 2;
[Test, Description("FCMEQ D0, D1, D2 | FCMGE D0, D1, D2 | FCMGT D0, D1, D2")] [Test, Description("FCMEQ D0, D1, D2 | FCMGE D0, D1, D2 | FCMGT D0, D1, D2")]
public void Fcmeq_Fcmge_Fcmgt_Reg_S_D([ValueSource("_doubles_")] [Random(8)] double A, public void Fcmeq_Fcmge_Fcmgt_Reg_S_D([ValueSource("_doubles_")] [Random(RndCnt)] double A,
[ValueSource("_doubles_")] [Random(8)] double B, [ValueSource("_doubles_")] [Random(RndCnt)] double B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{ {
uint Opcode = 0x5E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23); uint Opcode = 0x5E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V0 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(TestContext.CurrentContext.Random.NextDouble())); Vector128<float> V0 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(TestContext.CurrentContext.Random.NextDouble()));
Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A)); Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A));
Vector128<float> V2 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(B)); Vector128<float> V2 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(B));
@ -52,15 +55,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
Assert.That(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero); Assert.That(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero);
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMEQ S0, S1, S2 | FCMGE S0, S1, S2 | FCMGT S0, S1, S2")] [Test, Description("FCMEQ S0, S1, S2 | FCMGE S0, S1, S2 | FCMGT S0, S1, S2")]
public void Fcmeq_Fcmge_Fcmgt_Reg_S_S([ValueSource("_floats_")] [Random(8)] float A, public void Fcmeq_Fcmge_Fcmgt_Reg_S_S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[ValueSource("_floats_")] [Random(8)] float B, [ValueSource("_floats_")] [Random(RndCnt)] float B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{ {
uint Opcode = 0x5E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23); uint Opcode = 0x5E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat()); Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
Vector128<float> V1 = Sse.SetScalarVector128(A); Vector128<float> V1 = Sse.SetScalarVector128(A);
Vector128<float> V2 = Sse.SetScalarVector128(B); Vector128<float> V2 = Sse.SetScalarVector128(B);
@ -85,15 +90,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMEQ V0.2D, V1.2D, V2.2D | FCMGE V0.2D, V1.2D, V2.2D | FCMGT V0.2D, V1.2D, V2.2D")] [Test, Description("FCMEQ V0.2D, V1.2D, V2.2D | FCMGE V0.2D, V1.2D, V2.2D | FCMGT V0.2D, V1.2D, V2.2D")]
public void Fcmeq_Fcmge_Fcmgt_Reg_V_2D([ValueSource("_doubles_")] [Random(8)] double A, public void Fcmeq_Fcmge_Fcmgt_Reg_V_2D([ValueSource("_doubles_")] [Random(RndCnt)] double A,
[ValueSource("_doubles_")] [Random(8)] double B, [ValueSource("_doubles_")] [Random(RndCnt)] double B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{ {
uint Opcode = 0x4E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23); uint Opcode = 0x4E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A)); Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A));
Vector128<float> V2 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(B)); Vector128<float> V2 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(B));
@ -115,15 +122,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMEQ V0.2S, V1.2S, V2.2S | FCMGE V0.2S, V1.2S, V2.2S | FCMGT V0.2S, V1.2S, V2.2S")] [Test, Description("FCMEQ V0.2S, V1.2S, V2.2S | FCMGE V0.2S, V1.2S, V2.2S | FCMGT V0.2S, V1.2S, V2.2S")]
public void Fcmeq_Fcmge_Fcmgt_Reg_V_2S([ValueSource("_floats_")] [Random(8)] float A, public void Fcmeq_Fcmge_Fcmgt_Reg_V_2S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[ValueSource("_floats_")] [Random(8)] float B, [ValueSource("_floats_")] [Random(RndCnt)] float B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{ {
uint Opcode = 0x0E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23); uint Opcode = 0x0E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat()); Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
Vector128<float> V1 = Sse.SetVector128(0, 0, A, A); Vector128<float> V1 = Sse.SetVector128(0, 0, A, A);
Vector128<float> V2 = Sse.SetVector128(0, 0, B, B); Vector128<float> V2 = Sse.SetVector128(0, 0, B, B);
@ -148,15 +157,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMEQ V0.4S, V1.4S, V2.4S | FCMGE V0.4S, V1.4S, V2.4S | FCMGT V0.4S, V1.4S, V2.4S")] [Test, Description("FCMEQ V0.4S, V1.4S, V2.4S | FCMGE V0.4S, V1.4S, V2.4S | FCMGT V0.4S, V1.4S, V2.4S")]
public void Fcmeq_Fcmge_Fcmgt_Reg_V_4S([ValueSource("_floats_")] [Random(8)] float A, public void Fcmeq_Fcmge_Fcmgt_Reg_V_4S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[ValueSource("_floats_")] [Random(8)] float B, [ValueSource("_floats_")] [Random(RndCnt)] float B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT [Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{ {
uint Opcode = 0x4E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23); uint Opcode = 0x4E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V1 = Sse.SetAllVector128(A); Vector128<float> V1 = Sse.SetAllVector128(A);
Vector128<float> V2 = Sse.SetAllVector128(B); Vector128<float> V2 = Sse.SetAllVector128(B);
@ -180,15 +191,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)2)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)2)), Is.EquivalentTo(Exp));
Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)3)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)3)), Is.EquivalentTo(Exp));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMGT D0, D1, #0.0 | FCMGE D0, D1, #0.0 | FCMEQ D0, D1, #0.0 | FCMLE D0, D1, #0.0 | FCMLT D0, D1, #0.0")] [Test, Description("FCMGT D0, D1, #0.0 | FCMGE D0, D1, #0.0 | FCMEQ D0, D1, #0.0 | FCMLE D0, D1, #0.0 | FCMLT D0, D1, #0.0")]
public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_S_D([ValueSource("_doubles_")] [Random(8)] double A, public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_S_D([ValueSource("_doubles_")] [Random(RndCnt)] double A,
[Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
[Values(0u, 1u)] uint bit13) // "LT" [Values(0u, 1u)] uint bit13) // "LT"
{ {
uint Opcode = 0x5EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12); uint Opcode = 0x5EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V0 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(TestContext.CurrentContext.Random.NextDouble())); Vector128<float> V0 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(TestContext.CurrentContext.Random.NextDouble()));
Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A)); Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetScalarVector128(A));
@ -219,15 +232,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
Assert.That(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero); Assert.That(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero);
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMGT S0, S1, #0.0 | FCMGE S0, S1, #0.0 | FCMEQ S0, S1, #0.0 | FCMLE S0, S1, #0.0 | FCMLT S0, S1, #0.0")] [Test, Description("FCMGT S0, S1, #0.0 | FCMGE S0, S1, #0.0 | FCMEQ S0, S1, #0.0 | FCMLE S0, S1, #0.0 | FCMLT S0, S1, #0.0")]
public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_S_S([ValueSource("_floats_")] [Random(8)] float A, public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_S_S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
[Values(0u, 1u)] uint bit13) // "LT" [Values(0u, 1u)] uint bit13) // "LT"
{ {
uint Opcode = 0x5EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12); uint Opcode = 0x5EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat()); Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
Vector128<float> V1 = Sse.SetScalarVector128(A); Vector128<float> V1 = Sse.SetScalarVector128(A);
@ -260,15 +275,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMGT V0.2D, V1.2D, #0.0 | FCMGE V0.2D, V1.2D, #0.0 | FCMEQ V0.2D, V1.2D, #0.0 | FCMLE V0.2D, V1.2D, #0.0 | FCMLT V0.2D, V1.2D, #0.0")] [Test, Description("FCMGT V0.2D, V1.2D, #0.0 | FCMGE V0.2D, V1.2D, #0.0 | FCMEQ V0.2D, V1.2D, #0.0 | FCMLE V0.2D, V1.2D, #0.0 | FCMLT V0.2D, V1.2D, #0.0")]
public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_2D([ValueSource("_doubles_")] [Random(8)] double A, public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_2D([ValueSource("_doubles_")] [Random(RndCnt)] double A,
[Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
[Values(0u, 1u)] uint bit13) // "LT" [Values(0u, 1u)] uint bit13) // "LT"
{ {
uint Opcode = 0x4EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12); uint Opcode = 0x4EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A)); Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
@ -298,15 +315,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)0)), Is.EquivalentTo(Exp));
Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(VectorExtractDouble(ThreadState.V0, (byte)1)), Is.EquivalentTo(Exp));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMGT V0.2S, V1.2S, #0.0 | FCMGE V0.2S, V1.2S, #0.0 | FCMEQ V0.2S, V1.2S, #0.0 | FCMLE V0.2S, V1.2S, #0.0 | FCMLT V0.2S, V1.2S, #0.0")] [Test, Description("FCMGT V0.2S, V1.2S, #0.0 | FCMGE V0.2S, V1.2S, #0.0 | FCMEQ V0.2S, V1.2S, #0.0 | FCMLE V0.2S, V1.2S, #0.0 | FCMLT V0.2S, V1.2S, #0.0")]
public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_2S([ValueSource("_floats_")] [Random(8)] float A, public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_2S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
[Values(0u, 1u)] uint bit13) // "LT" [Values(0u, 1u)] uint bit13) // "LT"
{ {
uint Opcode = 0x0EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12); uint Opcode = 0x0EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat()); Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
Vector128<float> V1 = Sse.SetVector128(0, 0, A, A); Vector128<float> V1 = Sse.SetVector128(0, 0, A, A);
@ -339,15 +358,17 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)2), Is.Zero);
Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero); Assert.That(Sse41.Extract(ThreadState.V0, (byte)3), Is.Zero);
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Description("FCMGT V0.4S, V1.4S, #0.0 | FCMGE V0.4S, V1.4S, #0.0 | FCMEQ V0.4S, V1.4S, #0.0 | FCMLE V0.4S, V1.4S, #0.0 | FCMLT V0.4S, V1.4S, #0.0")] [Test, Description("FCMGT V0.4S, V1.4S, #0.0 | FCMGE V0.4S, V1.4S, #0.0 | FCMEQ V0.4S, V1.4S, #0.0 | FCMLE V0.4S, V1.4S, #0.0 | FCMLT V0.4S, V1.4S, #0.0")]
public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_4S([ValueSource("_floats_")] [Random(8)] float A, public void Fcmgt_Fcmge_Fcmeq_Fcmle_Fcmlt_Zero_V_4S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE [Values(0u, 1u, 2u, 3u)] uint opU, // GT, GE, EQ, LE
[Values(0u, 1u)] uint bit13) // "LT" [Values(0u, 1u)] uint bit13) // "LT"
{ {
uint Opcode = 0x4EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12); uint Opcode = 0x4EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V1 = Sse.SetAllVector128(A); Vector128<float> V1 = Sse.SetAllVector128(A);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1); AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
@ -379,6 +400,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)2)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)2)), Is.EquivalentTo(Exp));
Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)3)), Is.EquivalentTo(Exp)); Assert.That(BitConverter.GetBytes(Sse41.Extract(ThreadState.V0, (byte)3)), Is.EquivalentTo(Exp));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
} }

View file

@ -22,6 +22,7 @@ namespace Ryujinx.Tests.Cpu
{ {
uint Opcode = 0x4E285800; // AESD V0.16B, V0.16B uint Opcode = 0x4E285800; // AESD V0.16B, V0.16B
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Vector128<float> V0 = MakeVectorE0E1(RoundKeyL ^ ValueL, RoundKeyH ^ ValueH); Vector128<float> V0 = MakeVectorE0E1(RoundKeyL ^ ValueL, RoundKeyH ^ ValueH);
Vector128<float> V1 = MakeVectorE0E1(RoundKeyL, RoundKeyH); Vector128<float> V1 = MakeVectorE0E1(RoundKeyL, RoundKeyH);
@ -37,6 +38,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V1), Is.EqualTo(RoundKeyL)); Assert.That(GetVectorE0(ThreadState.V1), Is.EqualTo(RoundKeyL));
Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(RoundKeyH)); Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(RoundKeyH));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -52,6 +54,7 @@ namespace Ryujinx.Tests.Cpu
{ {
uint Opcode = 0x4E284800; // AESE V0.16B, V0.16B uint Opcode = 0x4E284800; // AESE V0.16B, V0.16B
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Vector128<float> V0 = MakeVectorE0E1(RoundKeyL ^ ValueL, RoundKeyH ^ ValueH); Vector128<float> V0 = MakeVectorE0E1(RoundKeyL ^ ValueL, RoundKeyH ^ ValueH);
Vector128<float> V1 = MakeVectorE0E1(RoundKeyL, RoundKeyH); Vector128<float> V1 = MakeVectorE0E1(RoundKeyL, RoundKeyH);
@ -67,6 +70,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE0(ThreadState.V1), Is.EqualTo(RoundKeyL)); Assert.That(GetVectorE0(ThreadState.V1), Is.EqualTo(RoundKeyL));
Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(RoundKeyH)); Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(RoundKeyH));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -80,6 +84,7 @@ namespace Ryujinx.Tests.Cpu
{ {
uint Opcode = 0x4E287800; // AESIMC V0.16B, V0.16B uint Opcode = 0x4E287800; // AESIMC V0.16B, V0.16B
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Vector128<float> V = MakeVectorE0E1(ValueL, ValueH); Vector128<float> V = MakeVectorE0E1(ValueL, ValueH);
AThreadState ThreadState = SingleOpcode( AThreadState ThreadState = SingleOpcode(
@ -100,6 +105,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(ValueH)); Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(ValueH));
}); });
} }
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
@ -113,6 +119,7 @@ namespace Ryujinx.Tests.Cpu
{ {
uint Opcode = 0x4E286800; // AESMC V0.16B, V0.16B uint Opcode = 0x4E286800; // AESMC V0.16B, V0.16B
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0); Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Vector128<float> V = MakeVectorE0E1(ValueL, ValueH); Vector128<float> V = MakeVectorE0E1(ValueL, ValueH);
AThreadState ThreadState = SingleOpcode( AThreadState ThreadState = SingleOpcode(
@ -133,6 +140,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(ValueH)); Assert.That(GetVectorE1(ThreadState.V1), Is.EqualTo(ValueH));
}); });
} }
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
} }

View file

@ -23,7 +23,8 @@ namespace Ryujinx.Tests.Cpu
[TestCase((ushort)0x0001, 0x33800000u)] // 5.96046448e-8 (Smallest Subnormal) [TestCase((ushort)0x0001, 0x33800000u)] // 5.96046448e-8 (Smallest Subnormal)
public void Fcvtl_V_f16(ushort Value, uint Result) public void Fcvtl_V_f16(ushort Value, uint Result)
{ {
uint Opcode = 0x0E217801; uint Opcode = 0x0E217801; // FCVTL V1.4S, V0.4H
Vector128<float> V0 = Sse.StaticCast<ushort, float>(Sse2.SetAllVector128(Value)); Vector128<float> V0 = Sse.StaticCast<ushort, float>(Sse2.SetAllVector128(Value));
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0); AThreadState ThreadState = SingleOpcode(Opcode, V0: V0);
@ -35,6 +36,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V1), (byte)2), Is.EqualTo(Result)); Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V1), (byte)2), Is.EqualTo(Result));
Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V1), (byte)3), Is.EqualTo(Result)); Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V1), (byte)3), Is.EqualTo(Result));
}); });
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,282 +0,0 @@
// https://github.com/LDj3SNuD/ARM_v8-A_AArch64_Instructions_Tester/blob/master/Tester/Types/Bits.cs
// https://github.com/dotnet/corefx/blob/master/src/System.Collections/src/System/Collections/BitArray.cs
using System;
using System.Collections;
using System.Numerics;
namespace Ryujinx.Tests.Cpu.Tester.Types
{
internal sealed class Bits : ICollection, IEnumerable, IEquatable<Bits>
{
private BitArray bits;
public Bits(bool[] values) => bits = new BitArray(values);
public Bits(byte[] bytes) => bits = new BitArray(bytes);
public Bits(Bits bits) => this.bits = new BitArray(bits.bits); // Clone: deep copy.
public Bits(int length) => bits = new BitArray(length);
public Bits(int length, bool defaultValue) => bits = new BitArray(length, defaultValue);
private Bits(BitArray bitArray) => bits = new BitArray(bitArray);
public Bits(ulong value) => bits = new BitArray(BitConverter.GetBytes(value));
public Bits(uint value) => bits = new BitArray(BitConverter.GetBytes(value));
public Bits(BigInteger value) => bits = new BitArray(value.ToByteArray());
private BitArray ToBitArray() => new BitArray(bits);
public ulong ToUInt64()
{
byte[] dst = new byte[8];
bits.CopyTo(dst, 0);
return BitConverter.ToUInt64(dst,0);
}
public uint ToUInt32()
{
byte[] dst = new byte[4];
bits.CopyTo(dst, 0);
return BitConverter.ToUInt32(dst,0);
}
public BigInteger ToBigInteger()
{
if (bits.Count != 64 &&
bits.Count != 32 &&
bits.Count != 16 &&
bits.Count != 8)
{
throw new InvalidOperationException();
}
byte[] dst = new byte[bits.Count / 8];
bits.CopyTo(dst, 0);
return new BigInteger(dst);
}
public bool this[int index] // ASL: "<>".
{
get
{
return bits.Get(index);
}
set
{
bits.Set(index, value);
}
}
public Bits this[int highIndex, int lowIndex] // ASL: "<:>".
{
get
{
if (highIndex < lowIndex)
{
throw new IndexOutOfRangeException();
}
bool[] dst = new bool[highIndex - lowIndex + 1];
for (int i = lowIndex, n = 0; i <= highIndex; i++, n++)
{
dst[n] = bits.Get(i);
}
return new Bits(dst);
}
set
{
if (highIndex < lowIndex)
{
throw new IndexOutOfRangeException();
}
for (int i = lowIndex, n = 0; i <= highIndex; i++, n++)
{
bits.Set(i, value.Get(n));
}
}
}
public bool IsReadOnly { get => false; } // Mutable.
public int Count { get => bits.Count; } // Not resizable.
public bool IsSynchronized { get => bits.IsSynchronized; }
public object SyncRoot { get => bits.SyncRoot; }
public Bits And(Bits value) => new Bits(new BitArray(this.bits).And(value.bits)); // Immutable.
public void CopyTo(Array array, int index) => bits.CopyTo(array, index);
public bool Get(int index) => bits.Get(index);
public IEnumerator GetEnumerator() => bits.GetEnumerator();
//public Bits LeftShift(int count) => new Bits(new BitArray(bits).LeftShift(count)); // Immutable.
public Bits Not() => new Bits(new BitArray(bits).Not()); // Immutable.
public Bits Or(Bits value) => new Bits(new BitArray(this.bits).Or(value.bits)); // Immutable.
//public Bits RightShift(int count) => new Bits(new BitArray(bits).RightShift(count)); // Immutable.
public void Set(int index, bool value) => bits.Set(index, value);
public void SetAll(bool value) => bits.SetAll(value);
public Bits Xor(Bits value) => new Bits(new BitArray(this.bits).Xor(value.bits)); // Immutable.
public static Bits Concat(Bits highBits, Bits lowBits) // ASL: ":".
{
if (((object)lowBits == null) || ((object)highBits == null))
{
throw new ArgumentNullException();
}
bool[] dst = new bool[lowBits.Count + highBits.Count];
lowBits.CopyTo(dst, 0);
highBits.CopyTo(dst, lowBits.Count);
return new Bits(dst);
}
public static Bits Concat(bool bit3, bool bit2, bool bit1, bool bit0) // ASL: ":::".
{
return new Bits(new bool[] {bit0, bit1, bit2, bit3});
}
public static implicit operator Bits(bool value) => new Bits(1, value);
public static implicit operator Bits(string value)
{
if (String.IsNullOrEmpty(value))
{
throw new InvalidCastException();
}
bool[] dst = new bool[value.Length];
for (int i = value.Length - 1, n = 0; i >= 0; i--, n++)
{
if (value[i] == '1')
{
dst[n] = true;
}
else if (value[i] == '0')
{
dst[n] = false;
}
else
{
throw new InvalidCastException();
}
}
return new Bits(dst);
}
public static explicit operator bool(Bits bit)
{
if (((object)bit == null) || (bit.Count != 1))
{
throw new InvalidCastException();
}
return bit.Get(0);
}
public static Bits operator +(Bits left, BigInteger right) // ASL: "+".
{
if (((object)left == null) || ((object)right == null))
{
throw new ArgumentNullException();
}
BigInteger dst = left.ToBigInteger() + right;
return dst.SubBigInteger(left.Count - 1, 0);
}
public static Bits operator +(Bits left, Bits right) // ASL: "+".
{
if (((object)left == null) || ((object)right == null))
{
throw new ArgumentNullException();
}
if (left.Count != right.Count)
{
throw new InvalidOperationException();
}
BigInteger dst = left.ToBigInteger() + right.ToBigInteger();
return dst.SubBigInteger(left.Count - 1, 0);
}
public static Bits operator -(Bits left, Bits right) // ASL: "-".
{
if (((object)left == null) || ((object)right == null))
{
throw new ArgumentNullException();
}
if (left.Count != right.Count)
{
throw new InvalidOperationException();
}
BigInteger dst = left.ToBigInteger() - right.ToBigInteger();
return dst.SubBigInteger(left.Count - 1, 0);
}
public static bool operator ==(Bits left, Bits right) // ASL: "==".
{
if (((object)left == null) || ((object)right == null))
{
throw new ArgumentNullException();
}
if (left.Count != right.Count)
{
return false;
}
for (int i = 0; i <= left.Count - 1; i++)
{
if (left.Get(i) != right.Get(i))
{
return false;
}
}
return true;
}
public static bool operator !=(Bits left, Bits right) // ASL: "!=".
{
return !(left == right);
}
public bool Equals(Bits right) // ASL: "==".
{
if ((object)right == null)
{
throw new ArgumentNullException();
}
Bits left = this;
if (left.Count != right.Count)
{
return false;
}
for (int i = 0; i <= left.Count - 1; i++)
{
if (left.Get(i) != right.Get(i))
{
return false;
}
}
return true;
}
public override bool Equals(object obj)
{
if (obj == null)
{
throw new ArgumentNullException();
}
Bits right = obj as Bits;
return Equals(right);
}
public override int GetHashCode() => bits.GetHashCode();
}
}

View file

@ -1,42 +0,0 @@
// https://github.com/LDj3SNuD/ARM_v8-A_AArch64_Instructions_Tester/blob/master/Tester/Types/Integer.cs
using System;
using System.Numerics;
namespace Ryujinx.Tests.Cpu.Tester.Types
{
internal static class Integer
{
public static Bits SubBigInteger(this BigInteger x, int highIndex, int lowIndex) // ASL: "<:>".
{
if (highIndex < lowIndex)
{
throw new IndexOutOfRangeException();
}
Bits src = new Bits(x);
bool[] dst = new bool[highIndex - lowIndex + 1];
for (int i = lowIndex, n = 0; i <= highIndex; i++, n++)
{
if (i <= src.Count - 1)
{
dst[n] = src[i];
}
else
{
dst[n] = (x.Sign != -1 ? false : true); // Zero / Sign Extension.
}
}
return new Bits(dst);
}
public static bool SubBigInteger(this BigInteger x, int index) // ASL: "<>".
{
Bits dst = x.SubBigInteger(index, index);
return (bool)dst;
}
}
}