0
0
Fork 0
mirror of https://github.com/ryujinx-mirror/ryujinx.git synced 2024-12-23 08:45:46 +00:00

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()
{
UnicornAvailable = UnicornAArch64.IsAvailable();
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()
{
Position = 0x1000;
Size = 0x1000;
Size = 0x1000;
EntryPoint = Position;
@ -79,10 +80,12 @@ namespace Ryujinx.Tests.Cpu
protected void Opcode(uint Opcode)
{
Thread.Memory.WriteUInt32(Position, Opcode);
if (UnicornAvailable)
{
UnicornEmu.MemoryWrite32((ulong)Position, Opcode);
}
Position += 4;
}
@ -97,14 +100,18 @@ namespace Ryujinx.Tests.Cpu
Thread.ThreadState.X1 = X1;
Thread.ThreadState.X2 = X2;
Thread.ThreadState.X3 = X3;
Thread.ThreadState.X31 = X31;
Thread.ThreadState.V0 = V0;
Thread.ThreadState.V1 = V1;
Thread.ThreadState.V2 = V2;
Thread.ThreadState.Overflow = Overflow;
Thread.ThreadState.Carry = Carry;
Thread.ThreadState.Zero = Zero;
Thread.ThreadState.Carry = Carry;
Thread.ThreadState.Zero = Zero;
Thread.ThreadState.Negative = Negative;
Thread.ThreadState.Fpcr = Fpcr;
Thread.ThreadState.Fpsr = Fpsr;
@ -114,14 +121,18 @@ namespace Ryujinx.Tests.Cpu
UnicornEmu.X[1] = X1;
UnicornEmu.X[2] = X2;
UnicornEmu.X[3] = X3;
UnicornEmu.SP = X31;
UnicornEmu.Q[0] = V0;
UnicornEmu.Q[1] = V1;
UnicornEmu.Q[2] = V2;
UnicornEmu.OverflowFlag = Overflow;
UnicornEmu.CarryFlag = Carry;
UnicornEmu.ZeroFlag = Zero;
UnicornEmu.CarryFlag = Carry;
UnicornEmu.ZeroFlag = Zero;
UnicornEmu.NegativeFlag = Negative;
UnicornEmu.Fpcr = Fpcr;
UnicornEmu.Fpsr = Fpsr;
}
@ -144,10 +155,7 @@ namespace Ryujinx.Tests.Cpu
}
}
protected AThreadState GetThreadState()
{
return Thread.ThreadState;
}
protected AThreadState GetThreadState() => Thread.ThreadState;
protected AThreadState SingleOpcode(uint Opcode,
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();
}
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)
{
return;
}
Assert.That(Thread.ThreadState.X0, Is.EqualTo(UnicornEmu.X[0]));
Assert.That(Thread.ThreadState.X1, Is.EqualTo(UnicornEmu.X[1]));
Assert.That(Thread.ThreadState.X2, Is.EqualTo(UnicornEmu.X[2]));
Assert.That(Thread.ThreadState.X3, Is.EqualTo(UnicornEmu.X[3]));
Assert.That(Thread.ThreadState.X4, Is.EqualTo(UnicornEmu.X[4]));
Assert.That(Thread.ThreadState.X5, Is.EqualTo(UnicornEmu.X[5]));
Assert.That(Thread.ThreadState.X6, Is.EqualTo(UnicornEmu.X[6]));
Assert.That(Thread.ThreadState.X7, Is.EqualTo(UnicornEmu.X[7]));
Assert.That(Thread.ThreadState.X8, Is.EqualTo(UnicornEmu.X[8]));
Assert.That(Thread.ThreadState.X9, Is.EqualTo(UnicornEmu.X[9]));
Assert.That(Thread.ThreadState.X0, Is.EqualTo(UnicornEmu.X[0]));
Assert.That(Thread.ThreadState.X1, Is.EqualTo(UnicornEmu.X[1]));
Assert.That(Thread.ThreadState.X2, Is.EqualTo(UnicornEmu.X[2]));
Assert.That(Thread.ThreadState.X3, Is.EqualTo(UnicornEmu.X[3]));
Assert.That(Thread.ThreadState.X4, Is.EqualTo(UnicornEmu.X[4]));
Assert.That(Thread.ThreadState.X5, Is.EqualTo(UnicornEmu.X[5]));
Assert.That(Thread.ThreadState.X6, Is.EqualTo(UnicornEmu.X[6]));
Assert.That(Thread.ThreadState.X7, Is.EqualTo(UnicornEmu.X[7]));
Assert.That(Thread.ThreadState.X8, Is.EqualTo(UnicornEmu.X[8]));
Assert.That(Thread.ThreadState.X9, Is.EqualTo(UnicornEmu.X[9]));
Assert.That(Thread.ThreadState.X10, Is.EqualTo(UnicornEmu.X[10]));
Assert.That(Thread.ThreadState.X11, Is.EqualTo(UnicornEmu.X[11]));
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.X29, Is.EqualTo(UnicornEmu.X[29]));
Assert.That(Thread.ThreadState.X30, Is.EqualTo(UnicornEmu.X[30]));
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.V2, Is.EqualTo(UnicornEmu.Q[2]));
Assert.That(Thread.ThreadState.V3, Is.EqualTo(UnicornEmu.Q[3]));
Assert.That(Thread.ThreadState.V4, Is.EqualTo(UnicornEmu.Q[4]));
Assert.That(Thread.ThreadState.V5, Is.EqualTo(UnicornEmu.Q[5]));
Assert.That(Thread.ThreadState.V6, Is.EqualTo(UnicornEmu.Q[6]));
Assert.That(Thread.ThreadState.V7, Is.EqualTo(UnicornEmu.Q[7]));
Assert.That(Thread.ThreadState.V8, Is.EqualTo(UnicornEmu.Q[8]));
Assert.That(Thread.ThreadState.V9, Is.EqualTo(UnicornEmu.Q[9]));
Assert.That(Thread.ThreadState.V0, Is.EqualTo(UnicornEmu.Q[0]));
Assert.That(Thread.ThreadState.V1, Is.EqualTo(UnicornEmu.Q[1]));
Assert.That(Thread.ThreadState.V2, Is.EqualTo(UnicornEmu.Q[2]));
Assert.That(Thread.ThreadState.V3, Is.EqualTo(UnicornEmu.Q[3]));
Assert.That(Thread.ThreadState.V4, Is.EqualTo(UnicornEmu.Q[4]));
Assert.That(Thread.ThreadState.V5, Is.EqualTo(UnicornEmu.Q[5]));
Assert.That(Thread.ThreadState.V6, Is.EqualTo(UnicornEmu.Q[6]));
Assert.That(Thread.ThreadState.V7, Is.EqualTo(UnicornEmu.Q[7]));
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.V11, Is.EqualTo(UnicornEmu.Q[11]));
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.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.Carry, Is.EqualTo(UnicornEmu.CarryFlag));
Assert.That(Thread.ThreadState.Zero, Is.EqualTo(UnicornEmu.ZeroFlag));
Assert.That(Thread.ThreadState.Carry, Is.EqualTo(UnicornEmu.CarryFlag));
Assert.That(Thread.ThreadState.Zero, Is.EqualTo(UnicornEmu.ZeroFlag));
Assert.That(Thread.ThreadState.Negative, Is.EqualTo(UnicornEmu.NegativeFlag));
}

View file

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

View file

@ -1,4 +1,4 @@
//#define AluImm
#define AluImm
using ChocolArm64.State;
@ -6,824 +6,448 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("AluImm"), Ignore("Tested: second half of 2018.")]
[Category("AluImm")] // Tested: second half of 2018.
public sealed class CpuTestAluImm : CpuTest
{
#if AluImm
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCnt = 2;
private const int RndCntImm = 2;
private const int RndCntImms = 2;
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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0x91000000; // ADD X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0x11000000; // ADD W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0xB1000000; // ADDS X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0x31000000; // ADDS W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0x92400000; // AND X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0x92000000; // AND X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("AND <Wd|WSP>, <Wn>, #<imm>")]
[Test, Pairwise, Description("AND <Wd|WSP>, <Wn>, #<imm>")]
public void And_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0x12000000; // AND W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("ANDS <Xd>, <Xn>, #<imm>")]
[Test, Pairwise, Description("ANDS <Xd>, <Xn>, #<imm>")]
public void Ands_N1_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0xF2400000; // ANDS X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("ANDS <Xd>, <Xn>, #<imm>")]
[Test, Pairwise, Description("ANDS <Xd>, <Xn>, #<imm>")]
public void Ands_N0_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0xF2000000; // ANDS X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("ANDS <Wd>, <Wn>, #<imm>")]
[Test, Pairwise, Description("ANDS <Wd>, <Wn>, #<imm>")]
public void Ands_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0x72000000; // ANDS W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0xD2400000; // EOR X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0xD2000000; // EOR X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("EOR <Wd>, <Wn>, #<imm>")]
[Test, Pairwise, Description("EOR <Wd>, <Wn>, #<imm>")]
public void Eor_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0x52000000; // EOR W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, 2)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 62u)] [Random(0u, 62u, RndCntImms)] uint imms, // <imm>
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0xB2400000; // ORR X0, X0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0xB2000000; // ORR X0, X0, #0x100000001
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("ORR <Wd|WSP>, <Wn>, #<imm>")]
[Test, Pairwise, Description("ORR <Wd|WSP>, <Wn>, #<imm>")]
public void Orr_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, 2)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr) // <imm>
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 30u)] [Random(0u, 30u, RndCntImms)] uint imms, // <imm>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr) // <imm>
{
uint Opcode = 0x32000000; // ORR W0, W0, #0x1
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
Bits Op = new Bits(Opcode);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0xD1000000; // SUB X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0x51000000; // SUB W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(8)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn_SP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0xF1000000; // SUBS X0, X0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Xn_SP);
AArch64.X((int)Rn, new Bits(Xn_SP));
}
else
{
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();
}
[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,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(8)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, 10)] uint imm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn_WSP,
[Values(0u, 4095u)] [Random(0u, 4095u, RndCntImm)] uint imm,
[Values(0b00u, 0b01u)] uint shift) // <LSL #0, LSL #12>
{
uint Opcode = 0x71000000; // SUBS W0, W0, #0, LSL #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((shift & 3) << 22) | ((imm & 4095) << 10);
Bits Op = new Bits(Opcode);
AThreadState ThreadState;
if (Rn != 31)
{
ThreadState = SingleOpcode(Opcode, X1: Wn_WSP);
AArch64.X((int)Rn, new Bits(Wn_WSP));
}
else
{
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();
}
#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;
@ -6,212 +6,127 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("Bfm"), Ignore("Tested: second half of 2018.")]
[Category("Bfm")] // Tested: second half of 2018.
public sealed class CpuTestBfm : CpuTest
{
#if Bfm
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCnt = 2;
private const int RndCntImmr = 2;
private const int RndCntImms = 2;
[Test, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")]
[Test, Pairwise, Description("BFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Bfm_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Random(2)] ulong _Xd,
[Random(RndCnt)] ulong _Xd,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint imms)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
{
uint Opcode = 0xB3400000; // BFM X0, X0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("BFM <Wd>, <Wn>, #<immr>, #<imms>")]
[Test, Pairwise, Description("BFM <Wd>, <Wn>, #<immr>, #<imms>")]
public void Bfm_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Random(2)] uint _Wd,
[Random(RndCnt)] uint _Wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint imms)
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
{
uint Opcode = 0x33000000; // BFM W0, W0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("SBFM <Xd>, <Xn>, #<immr>, #<imms>")]
[Test, Pairwise, Description("SBFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Sbfm_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint imms)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
{
uint Opcode = 0x93400000; // SBFM X0, X0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("SBFM <Wd>, <Wn>, #<immr>, #<imms>")]
[Test, Pairwise, Description("SBFM <Wd>, <Wn>, #<immr>, #<imms>")]
public void Sbfm_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint imms)
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
{
uint Opcode = 0x13000000; // SBFM W0, W0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("UBFM <Xd>, <Xn>, #<immr>, #<imms>")]
[Test, Pairwise, Description("UBFM <Xd>, <Xn>, #<immr>, #<imms>")]
public void Ubfm_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, 2)] uint imms)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImmr)] uint immr,
[Values(0u, 31u, 32u, 63u)] [Random(0u, 63u, RndCntImms)] uint imms)
{
uint Opcode = 0xD3400000; // UBFM X0, X0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("UBFM <Wd>, <Wn>, #<immr>, #<imms>")]
[Test, Pairwise, Description("UBFM <Wd>, <Wn>, #<immr>, #<imms>")]
public void Ubfm_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, 2)] uint imms)
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint immr,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint imms)
{
uint Opcode = 0x53000000; // UBFM W0, W0, #0, #0
Opcode |= ((Rn & 31) << 5) | ((Rd & 31) << 0);
Opcode |= ((immr & 63) << 16) | ((imms & 63) << 10);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
#endif

View file

@ -1,4 +1,4 @@
//#define CcmpImm
#define CcmpImm
using ChocolArm64.State;
@ -6,25 +6,20 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("CcmpImm"), Ignore("Tested: second half of 2018.")]
[Category("CcmpImm")] // Tested: second half of 2018.
public sealed class CpuTestCcmpImm : CpuTest
{
#if CcmpImm
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCnt = 2;
private const int RndCntImm = 2;
private const int RndCntNzcv = 2;
[Test, Description("CCMN <Xn>, #<imm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMN <Xn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmn_64bit([Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm,
[Random(0u, 15u, 1)] uint nzcv,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
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);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CCMN <Wn>, #<imm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMN <Wn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmn_32bit([Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm,
[Random(0u, 15u, 1)] uint nzcv,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
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);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("CCMP <Xn>, #<imm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMP <Xn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmp_64bit([Values(1u, 31u)] uint Rn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm,
[Random(0u, 15u, 1)] uint nzcv,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
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);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CCMP <Wn>, #<imm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMP <Wn>, #<imm>, #<nzcv>, <cond>")]
public void Ccmp_32bit([Values(1u, 31u)] uint Rn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
[Values(0u, 31u)] [Random(0u, 31u, 3)] uint imm,
[Random(0u, 15u, 1)] uint nzcv,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0u, 31u)] [Random(0u, 31u, RndCntImm)] uint imm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
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);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
#endif

View file

@ -1,4 +1,4 @@
//#define CcmpReg
#define CcmpReg
using ChocolArm64.State;
@ -6,27 +6,21 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("CcmpReg"), Ignore("Tested: second half of 2018.")]
[Category("CcmpReg")] // Tested: second half of 2018.
public sealed class CpuTestCcmpReg : CpuTest
{
#if CcmpReg
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCnt = 2;
private const int RndCntNzcv = 2;
[Test, Description("CCMN <Xn>, <Xm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMN <Xn>, <Xm>, #<nzcv>, <cond>")]
public void Ccmn_64bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm,
[Random(0u, 15u, 1)] uint nzcv,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -37,32 +31,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CCMN <Wn>, <Wm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMN <Wn>, <Wm>, #<nzcv>, <cond>")]
public void Ccmn_32bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm,
[Random(0u, 15u, 1)] uint nzcv,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -73,32 +55,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("CCMP <Xn>, <Xm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMP <Xn>, <Xm>, #<nzcv>, <cond>")]
public void Ccmp_64bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xm,
[Random(0u, 15u, 1)] uint nzcv,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -109,32 +79,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CCMP <Wn>, <Wm>, #<nzcv>, <cond>")]
[Test, Pairwise, Description("CCMP <Wn>, <Wm>, #<nzcv>, <cond>")]
public void Ccmp_32bit([Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wm,
[Random(0u, 15u, 1)] uint nzcv,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Random(0u, 15u, RndCntNzcv)] uint nzcv,
[Values(0b0000u, 0b0001u, 0b0010u, 0b0011u, // <EQ, NE, CS/HS, CC/LO,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -145,21 +103,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12) | ((nzcv & 15) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
#endif

View file

@ -1,4 +1,4 @@
//#define Csel
#define Csel
using ChocolArm64.State;
@ -6,27 +6,20 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("Csel"), Ignore("Tested: second half of 2018.")]
[Category("Csel")] // Tested: second half of 2018.
public sealed class CpuTestCsel : CpuTest
{
#if Csel
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCnt = 2;
[Test, Description("CSEL <Xd>, <Xn>, <Xm>, <cond>")]
[Test, Pairwise, Description("CSEL <Xd>, <Xn>, <Xm>, <cond>")]
public void Csel_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -37,34 +30,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CSEL <Wd>, <Wn>, <Wm>, <cond>")]
[Test, Pairwise, Description("CSEL <Wd>, <Wn>, <Wm>, <cond>")]
public void Csel_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -75,34 +54,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("CSINC <Xd>, <Xn>, <Xm>, <cond>")]
[Test, Pairwise, Description("CSINC <Xd>, <Xn>, <Xm>, <cond>")]
public void Csinc_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -113,34 +78,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CSINC <Wd>, <Wn>, <Wm>, <cond>")]
[Test, Pairwise, Description("CSINC <Wd>, <Wn>, <Wm>, <cond>")]
public void Csinc_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -151,34 +102,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("CSINV <Xd>, <Xn>, <Xm>, <cond>")]
[Test, Pairwise, Description("CSINV <Xd>, <Xn>, <Xm>, <cond>")]
public void Csinv_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -189,34 +126,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CSINV <Wd>, <Wn>, <Wm>, <cond>")]
[Test, Pairwise, Description("CSINV <Wd>, <Wn>, <Wm>, <cond>")]
public void Csinv_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -227,34 +150,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("CSNEG <Xd>, <Xn>, <Xm>, <cond>")]
[Test, Pairwise, Description("CSNEG <Xd>, <Xn>, <Xm>, <cond>")]
public void Csneg_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -265,34 +174,20 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("CSNEG <Wd>, <Wn>, <Wm>, <cond>")]
[Test, Pairwise, Description("CSNEG <Wd>, <Wn>, <Wm>, <cond>")]
public void Csneg_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[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,
0b0100u, 0b0101u, 0b0110u, 0b0111u, // MI, PL, VS, VC,
0b1000u, 0b1001u, 0b1010u, 0b1011u, // HI, LS, GE, LT,
@ -303,23 +198,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= ((cond & 15) << 12);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
#endif

View file

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

View file

@ -1,4 +1,4 @@
//#define Mov
#define Mov
using ChocolArm64.State;
@ -6,23 +6,16 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("Mov"), Ignore("Tested: second half of 2018.")]
[Category("Mov")] // Tested: second half of 2018.
public sealed class CpuTestMov : CpuTest
{
#if Mov
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCntImm = 2;
[Test, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")]
[Test, Pairwise, Description("MOVK <Xd>, #<imm>{, LSL #<shift>}")]
public void Movk_64bit([Values(0u, 31u)] uint Rd,
[Random(12)] ulong _Xd,
[Values(0u, 65535u)] [Random(0u, 65535u, 10)] uint imm,
[Random(RndCntImm)] ulong _Xd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u, 32u, 48u)] uint shift)
{
uint Opcode = 0xF2800000; // MOVK X0, #0, LSL #0
@ -30,29 +23,16 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("MOVK <Wd>, #<imm>{, LSL #<shift>}")]
[Test, Pairwise, Description("MOVK <Wd>, #<imm>{, LSL #<shift>}")]
public void Movk_32bit([Values(0u, 31u)] uint Rd,
[Random(12)] uint _Wd,
[Values(0u, 65535u)] [Random(0u, 65535u, 10)] uint imm,
[Random(RndCntImm)] uint _Wd,
[Values(0u, 65535u)] [Random(0u, 65535u, RndCntImm)] uint imm,
[Values(0u, 16u)] uint shift)
{
uint Opcode = 0x72800000; // MOVK W0, #0, LSL #0
@ -60,28 +40,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("MOVN <Xd>, #<imm>{, LSL #<shift>}")]
[Test, Pairwise, Description("MOVN <Xd>, #<imm>{, LSL #<shift>}")]
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)
{
uint Opcode = 0x92800000; // MOVN X0, #0, LSL #0
@ -89,27 +56,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("MOVN <Wd>, #<imm>{, LSL #<shift>}")]
[Test, Pairwise, Description("MOVN <Wd>, #<imm>{, LSL #<shift>}")]
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)
{
uint Opcode = 0x12800000; // MOVN W0, #0, LSL #0
@ -117,27 +72,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("MOVZ <Xd>, #<imm>{, LSL #<shift>}")]
[Test, Pairwise, Description("MOVZ <Xd>, #<imm>{, LSL #<shift>}")]
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)
{
uint Opcode = 0xD2800000; // MOVZ X0, #0, LSL #0
@ -145,27 +88,15 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("MOVZ <Wd>, #<imm>{, LSL #<shift>}")]
[Test, Pairwise, Description("MOVZ <Wd>, #<imm>{, LSL #<shift>}")]
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)
{
uint Opcode = 0x52800000; // MOVZ W0, #0, LSL #0
@ -173,21 +104,9 @@ namespace Ryujinx.Tests.Cpu
Opcode |= (((shift / 16) & 3) << 21) | ((imm & 65535) << 5);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
#endif

View file

@ -1,4 +1,4 @@
//#define Mul
#define Mul
using ChocolArm64.State;
@ -6,378 +6,223 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu
{
using Tester;
using Tester.Types;
[Category("Mul"), Ignore("Tested: second half of 2018.")]
[Category("Mul")] // Tested: second half of 2018.
public sealed class CpuTestMul : CpuTest
{
#if Mul
[SetUp]
public void SetupTester()
{
AArch64.TakeReset(false);
}
private const int RndCnt = 2;
[Test, Description("MADD <Xd>, <Xn>, <Xm>, <Xa>")]
[Test, Pairwise, Description("MADD <Xd>, <Xn>, <Xm>, <Xa>")]
public void Madd_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{
uint Opcode = 0x9B000000; // MADD X0, X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("MADD <Wd>, <Wn>, <Wm>, <Wa>")]
[Test, Pairwise, Description("MADD <Wd>, <Wn>, <Wm>, <Wa>")]
public void Madd_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wa)
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wa)
{
uint Opcode = 0x1B000000; // MADD W0, W0, W0, W0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("MSUB <Xd>, <Xn>, <Xm>, <Xa>")]
[Test, Pairwise, Description("MSUB <Xd>, <Xn>, <Xm>, <Xa>")]
public void Msub_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xm,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{
uint Opcode = 0x9B008000; // MSUB X0, X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("MSUB <Wd>, <Wn>, <Wm>, <Wa>")]
[Test, Pairwise, Description("MSUB <Wd>, <Wn>, <Wm>, <Wa>")]
public void Msub_32bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wa)
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wa)
{
uint Opcode = 0x1B008000; // MSUB W0, W0, W0, W0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
uint _W31 = TestContext.CurrentContext.Random.NextUInt();
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();
}
[Test, Description("SMADDL <Xd>, <Wn>, <Wm>, <Xa>")]
[Test, Pairwise, Description("SMADDL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Smaddl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{
uint Opcode = 0x9B200000; // SMADDL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("UMADDL <Xd>, <Wn>, <Wm>, <Xa>")]
[Test, Pairwise, Description("UMADDL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Umaddl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{
uint Opcode = 0x9BA00000; // UMADDL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("SMSUBL <Xd>, <Wn>, <Wm>, <Xa>")]
[Test, Pairwise, Description("SMSUBL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Smsubl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{
uint Opcode = 0x9B208000; // SMSUBL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("UMSUBL <Xd>, <Wn>, <Wm>, <Xa>")]
[Test, Pairwise, Description("UMSUBL <Xd>, <Wn>, <Wm>, <Xa>")]
public void Umsubl_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(3u, 31u)] uint Ra,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(2)] uint Wm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint Wm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(2)] ulong Xa)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xa)
{
uint Opcode = 0x9BA08000; // UMSUBL X0, W0, W0, X0
Opcode |= ((Rm & 31) << 16) | ((Ra & 31) << 10) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("SMULH <Xd>, <Xn>, <Xm>")]
[Test, Pairwise, Description("SMULH <Xd>, <Xn>, <Xm>")]
public void Smulh_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm)
{
uint Opcode = 0x9B407C00; // SMULH X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
[Test, Description("UMULH <Xd>, <Xn>, <Xm>")]
[Test, Pairwise, Description("UMULH <Xd>, <Xn>, <Xm>")]
public void Umulh_64bit([Values(0u, 31u)] uint Rd,
[Values(1u, 31u)] uint Rn,
[Values(2u, 31u)] uint Rm,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xn,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xn,
[Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(16)] ulong Xm)
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(RndCnt)] ulong Xm)
{
uint Opcode = 0x9BC07C00; // UMULH X0, X0, X0
Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
ulong _X31 = TestContext.CurrentContext.Random.NextULong();
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();
}
#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
{
[TestCase(0x1E224820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x1E224820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000000000000ul)] // FMAX S0, S1, S2
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000000000000ul)]
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x000000003DCCCCCDul)]
@ -22,17 +22,19 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x1E224820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul)]
[TestCase(0x1E224820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul)]
[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, 0x8000000000000000ul, 0x8000000000000000ul)]
[TestCase(0x1E624820u, 0x8000000000000000ul, 0x3FF3333333333333ul, 0x3FF3333333333333ul)]
public void Fmax_S(uint Opcode, ulong A, ulong B, ulong Result)
{
// FMAX S0, S1, S2
AThreadState ThreadState = SingleOpcode(Opcode,
V1: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, A)),
V2: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, B)));
Assert.AreEqual(Result, Sse41.Extract(Sse.StaticCast<float, ulong>(ThreadState.V0), 0));
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn();
}
@ -51,19 +53,23 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC0000Au, 0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Bu, 0x7FC0000Au, 0x7FC0000Au)]
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> V2 = MakeVectorE0E1(C, D);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
[TestCase(0x1E225820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
[TestCase(0x1E225820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000080000000ul)] // FMIN S0, S1, S2
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000080000000ul)]
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x0000000080000000ul)]
@ -76,17 +82,19 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x1E225820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul)]
[TestCase(0x1E225820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul)]
[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, 0x8000000000000000ul, 0x8000000000000000ul)]
[TestCase(0x1E625820u, 0x8000000000000000ul, 0x3FF3333333333333ul, 0x8000000000000000ul)]
public void Fmin_S(uint Opcode, ulong A, ulong B, ulong Result)
{
// FMIN S0, S1, S2
AThreadState ThreadState = SingleOpcode(Opcode,
V1: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, A)),
V2: Sse.StaticCast<ulong, float>(Sse2.SetVector128(0, B)));
Assert.AreEqual(Result, Sse41.Extract(Sse.StaticCast<float, ulong>(ThreadState.V0), 0));
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
CompareAgainstUnicorn();
}
@ -105,15 +113,19 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC0000Au, 0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Bu, 0x7FC0000Au, 0x7FC0000Au)]
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> V2 = MakeVectorE0E1(C, D);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
@ -125,6 +137,7 @@ namespace Ryujinx.Tests.Cpu
V0: Sse.SetVector128(0, B, 0, 0));
Assert.That(Sse41.Extract(ThreadState.V6, (byte)0), Is.EqualTo(A * B));
CompareAgainstUnicorn();
}
@ -137,21 +150,27 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x007FF000u, 0x7E800000u)]
public void Frecpe_S(uint A, uint Result)
{
uint Opcode = 0x5EA1D820; // FRECPE S0, S1
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();
}
[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)
{
AThreadState ThreadState = SingleOpcode(0x5E62FC20,
V1: MakeVectorE0(A),
V2: MakeVectorE0(B));
Assert.That(VectorExtractDouble(ThreadState.V0, 0), Is.EqualTo(2 - (A * B)));
//CompareAgainstUnicorn(); // Not accurate enough
Assert.That(VectorExtractDouble(ThreadState.V0, (byte)0), Is.EqualTo(2 - (A * B)));
CompareAgainstUnicorn();
}
[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)3), Is.EqualTo(Result));
});
CompareAgainstUnicorn();
}
@ -177,7 +197,7 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x3F99999Au, false, 0x3F800000u)]
[TestCase(0x404CCCCDu, false, 0x40400000u)]
[TestCase(0x40733333u, false, 0x40800000u)]
[TestCase(0x3fc00000u, false, 0x40000000u)]
[TestCase(0x3FC00000u, false, 0x40000000u)]
[TestCase(0x40200000u, false, 0x40400000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
@ -213,42 +233,53 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frinta_S(uint A, bool DefaultNaN, uint Result)
{
uint Opcode = 0x1E264020; // FRINTA S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E264020, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
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, 0x3FF8000000000000ul, 0x3FF8000000000000ul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x3f80000040000000ul)]
[TestCase(0x6E219820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x3F80000040000000ul)] // FRINTX V0.4S, V1.4S
[TestCase(0x6E219820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x0000000000000000ul)] // FRINTX V0.2S, V1.2S
[TestCase(0x2E219820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)] // FRINTA V0.2S, V1.2S
[TestCase(0x2E218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0x2E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 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)
{
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
@ -294,36 +325,31 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u, Ignore = "NaN test.")]
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;
switch(RoundType)
{
case 'N':
FpcrTemp = 0x0;
break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
case 'N': FpcrTemp = 0x0; break;
case 'P': FpcrTemp = 0x400000; break;
case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
}
if(DefaultNaN)
{
FpcrTemp |= 1 << 25;
}
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E27C020, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
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, 0x3FF3333333333333ul, 0x3FF3333333333333ul, '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, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6EE19820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x3f80000040000000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)]
[TestCase(0x6EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x0000000000000000ul)]
[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, 'M', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[TestCase(0x6EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[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, 'M', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'N', false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x2EA19820u, 0x0000000080000000ul, 0x0000000000000000ul, 'P', 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.")]
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;
switch(RoundType)
{
case 'N':
FpcrTemp = 0x0;
break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
case 'N': FpcrTemp = 0x0; break;
case 'P': FpcrTemp = 0x400000; break;
case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
}
if(DefaultNaN)
{
FpcrTemp |= 1 << 25;
}
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
@ -394,7 +413,7 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x3F99999Au, false, 0x3F800000u)]
[TestCase(0x404CCCCDu, false, 0x40400000u)]
[TestCase(0x40733333u, false, 0x40400000u)]
[TestCase(0x3fc00000u, false, 0x3F800000u)]
[TestCase(0x3FC00000u, false, 0x3F800000u)]
[TestCase(0x40200000u, false, 0x40000000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
@ -430,47 +449,58 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintm_S(uint A, bool DefaultNaN, uint Result)
{
uint Opcode = 0x1E254020; // FRINTM S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E254020, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
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(0x4E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)]
[TestCase(0xE219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f8000003f800000ul, 0x0000000000000000ul)]
[TestCase(0xE219820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0xE219820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0xE219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0xE219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0x4E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)] // FRINTM V0.4S, V1.4S
[TestCase(0x0E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F8000003F800000ul, 0x0000000000000000ul)] // FRINTM V0.2S, V1.2S
[TestCase(0x0E219820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x0E219820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0x0E219820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 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)
{
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
[Ignore("Wrong opcode.")]
[TestCase(0x3FE66666u, false, 0x40000000u)]
[TestCase(0x3F99999Au, false, 0x3F800000u)]
[TestCase(0x404CCCCDu, false, 0x40400000u)]
[TestCase(0x40733333u, false, 0x40800000u)]
[TestCase(0x3fc00000u, false, 0x40000000u)]
[TestCase(0x3FC00000u, false, 0x40000000u)]
[TestCase(0x40200000u, false, 0x40400000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
@ -506,42 +536,52 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintn_S(uint A, bool DefaultNaN, uint Result)
{
uint Opcode = 0x1E264020; // FRINTA S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E264020, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
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, 0x3FF8000000000000ul, 0x3FF8000000000000ul, false, 0x4000000000000000ul, 0x4000000000000000ul)]
[TestCase(0x4E218820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x3f80000040000000ul)]
[TestCase(0x4E218820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0xE218820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x3f80000040000000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0x3fc000003fc00000ul, 0x3fc000003fc00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0xE218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0xE218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0x4E218820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x3F80000040000000ul)] // FRINTN V0.4S, V1.4S
[TestCase(0x4E218820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x0E218820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x3F80000040000000ul, 0x0000000000000000ul)] // FRINTN V0.2S, V1.2S
[TestCase(0x0E218820u, 0x3FC000003FC00000ul, 0x3FC000003FC00000ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x0E218820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x0E218820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0x0E218820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 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)
{
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
@ -549,7 +589,7 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x3F99999Au, false, 0x40000000u)]
[TestCase(0x404CCCCDu, false, 0x40800000u)]
[TestCase(0x40733333u, false, 0x40800000u)]
[TestCase(0x3fc00000u, false, 0x40000000u)]
[TestCase(0x3FC00000u, false, 0x40000000u)]
[TestCase(0x40200000u, false, 0x40400000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
[TestCase(0x00000000u, false, 0x00000000u)]
@ -585,39 +625,49 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, true, 0x7FC00000u, Ignore = "NaN test.")]
public void Frintp_S(uint A, bool DefaultNaN, uint Result)
{
uint Opcode = 0x1E24C020; // FRINTP S0, S1
Vector128<float> V1 = MakeVectorE0(A);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E24C020, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
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(0x4EA18820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0xEA18820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0xEA18820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0xEA18820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0xEA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0xEA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, true, 0x7FC000007FC00000ul, 0x0000000000000000ul, Ignore = "NaN test.")]
[TestCase(0x4EA18820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x4000000040000000ul, 0x4000000040000000ul)] // FRINTP V0.4S, v1.4S
[TestCase(0x0EA18820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, false, 0x4000000040000000ul, 0x0000000000000000ul)] // FRINTP V0.2S, v1.2S
[TestCase(0x0EA18820u, 0x0000000080000000ul, 0x0000000000000000ul, false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x0EA18820u, 0x7F800000FF800000ul, 0x0000000000000000ul, false, 0x7F800000FF800000ul, 0x0000000000000000ul)]
[TestCase(0x0EA18820u, 0xFF8000017FC00002ul, 0x0000000000000000ul, false, 0xFFC000017FC00002ul, 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)
{
Vector128<float> V1 = MakeVectorE0E1(A, B);
int FpcrTemp = 0x0;
if(DefaultNaN)
{
FpcrTemp = 0x2000000;
}
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
@ -663,36 +713,31 @@ namespace Ryujinx.Tests.Cpu
[TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u, Ignore = "NaN test.")]
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;
switch(RoundType)
{
case 'N':
FpcrTemp = 0x0;
break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
case 'N': FpcrTemp = 0x0; break;
case 'P': FpcrTemp = 0x400000; break;
case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
}
if(DefaultNaN)
{
FpcrTemp |= 1 << 25;
}
Vector128<float> V1 = MakeVectorE0(A);
AThreadState ThreadState = SingleOpcode(0x1E274020, V1: V1, Fpcr: FpcrTemp);
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result));
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, 0x3FF3333333333333ul, 0x3FF3333333333333ul, '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, 0x3FF3333333333333ul, 0x3FF3333333333333ul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6E619820u, 0x3FFCCCCCCCCCCCCDul, 0x3FFCCCCCCCCCCCCDul, 'Z', false, 0x3FF0000000000000ul, 0x3FF0000000000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x3f80000040000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x4000000040000000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)]
[TestCase(0x6E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x3f8000003f800000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'N', false, 0x3f80000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'P', false, 0x4000000040000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'M', false, 0x3f8000003f800000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3f99999a3fe66666ul, 0x3f99999a3fe66666ul, 'Z', false, 0x3f8000003f800000ul, 0x0000000000000000ul)]
[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, 'M', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[TestCase(0x6E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x3F8000003F800000ul)]
[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, 'M', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x3F99999A3FE66666ul, 0x3F99999A3FE66666ul, 'Z', false, 0x3F8000003F800000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'N', false, 0x0000000080000000ul, 0x0000000000000000ul)]
[TestCase(0x2E219820u, 0x0000000080000000ul, 0x0000000000000000ul, 'P', 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.")]
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;
switch(RoundType)
{
case 'N':
FpcrTemp = 0x0;
break;
case 'P':
FpcrTemp = 0x400000;
break;
case 'M':
FpcrTemp = 0x800000;
break;
case 'Z':
FpcrTemp = 0xC00000;
break;
case 'N': FpcrTemp = 0x0; break;
case 'P': FpcrTemp = 0x400000; break;
case 'M': FpcrTemp = 0x800000; break;
case 'Z': FpcrTemp = 0xC00000; break;
}
if(DefaultNaN)
{
FpcrTemp |= 1 << 25;
}
Vector128<float> V1 = MakeVectorE0E1(A, B);
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, Fpcr: FpcrTemp);
Assert.Multiple(() =>
{
Assert.AreEqual(Result0, GetVectorE0(ThreadState.V0));
Assert.AreEqual(Result1, GetVectorE1(ThreadState.V0));
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(Result0));
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(Result1));
});
CompareAgainstUnicorn();
}
[TestCase(0x41200000u, 0x3EA18000u)]
public void Frsqrte_S(uint A, uint Result)
{
uint Opcode = 0x7EA1D820; // FRSQRTE S0, S1
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();
}
}

View file

@ -24,12 +24,15 @@ namespace Ryujinx.Tests.Cpu
}
#endregion
private const int RndCnt = 2;
[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,
[ValueSource("_doubles_")] [Random(8)] double B,
public void Fcmeq_Fcmge_Fcmgt_Reg_S_D([ValueSource("_doubles_")] [Random(RndCnt)] double A,
[ValueSource("_doubles_")] [Random(RndCnt)] double B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{
uint Opcode = 0x5E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
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> 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(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero);
});
CompareAgainstUnicorn();
}
[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,
[ValueSource("_floats_")] [Random(8)] float B,
public void Fcmeq_Fcmge_Fcmgt_Reg_S_S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[ValueSource("_floats_")] [Random(RndCnt)] float B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{
uint Opcode = 0x5E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
Vector128<float> V1 = Sse.SetScalarVector128(A);
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)3), Is.Zero);
});
CompareAgainstUnicorn();
}
[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,
[ValueSource("_doubles_")] [Random(8)] double B,
public void Fcmeq_Fcmge_Fcmgt_Reg_V_2D([ValueSource("_doubles_")] [Random(RndCnt)] double A,
[ValueSource("_doubles_")] [Random(RndCnt)] double B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{
uint Opcode = 0x4E62E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A));
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)1)), Is.EquivalentTo(Exp));
});
CompareAgainstUnicorn();
}
[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,
[ValueSource("_floats_")] [Random(8)] float B,
public void Fcmeq_Fcmge_Fcmgt_Reg_V_2S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[ValueSource("_floats_")] [Random(RndCnt)] float B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{
uint Opcode = 0x0E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
Vector128<float> V1 = Sse.SetVector128(0, 0, A, A);
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)3), Is.Zero);
});
CompareAgainstUnicorn();
}
[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,
[ValueSource("_floats_")] [Random(8)] float B,
public void Fcmeq_Fcmge_Fcmgt_Reg_V_4S([ValueSource("_floats_")] [Random(RndCnt)] float A,
[ValueSource("_floats_")] [Random(RndCnt)] float B,
[Values(0u, 1u, 3u)] uint EU) // EQ, GE, GT
{
uint Opcode = 0x4E22E420 | ((EU & 1) << 29) | ((EU >> 1) << 23);
Vector128<float> V1 = Sse.SetAllVector128(A);
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)3)), Is.EquivalentTo(Exp));
});
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")]
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)] uint bit13) // "LT"
{
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> 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(VectorExtractDouble(ThreadState.V0, (byte)1), Is.Zero);
});
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")]
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)] uint bit13) // "LT"
{
uint Opcode = 0x5EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
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)3), Is.Zero);
});
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")]
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)] uint bit13) // "LT"
{
uint Opcode = 0x4EE0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V1 = Sse.StaticCast<double, float>(Sse2.SetAllVector128(A));
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)1)), Is.EquivalentTo(Exp));
});
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")]
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)] uint bit13) // "LT"
{
uint Opcode = 0x0EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V0 = Sse.SetAllVector128(TestContext.CurrentContext.Random.NextFloat());
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)3), Is.Zero);
});
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")]
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)] uint bit13) // "LT"
{
uint Opcode = 0x4EA0C820 | (((opU & 1) & ~bit13) << 29) | (bit13 << 13) | (((opU >> 1) & ~bit13) << 12);
Vector128<float> V1 = Sse.SetAllVector128(A);
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)3)), Is.EquivalentTo(Exp));
});
CompareAgainstUnicorn();
}
}

View file

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

View file

@ -23,7 +23,8 @@ namespace Ryujinx.Tests.Cpu
[TestCase((ushort)0x0001, 0x33800000u)] // 5.96046448e-8 (Smallest Subnormal)
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));
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)3), Is.EqualTo(Result));
});
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;
}
}
}