forked from Mirror/Ryujinx
Add Cmeq_S, Cmge_S, Cmgt_S, Cmhi_S, Cmhs_S, Cmle_S, Cmlt_S (Reg, Zero) & Cmtst_S compare instructions. Add 22 compare tests (Scalar, Vector). Add Eor_V, Not_V tests. (#171)
* Add files via upload * Add files via upload * Delete CpuTestScalar.cs * Update CpuTestSimdArithmetic.cs
This commit is contained in:
parent
35e695552e
commit
3bdd109f45
20 changed files with 2624 additions and 338 deletions
|
@ -187,16 +187,27 @@ namespace ChocolArm64
|
||||||
SetA64("0x101110011xxxxx000111xxxxxxxxxx", AInstEmit.Bsl_V, typeof(AOpCodeSimdReg));
|
SetA64("0x101110011xxxxx000111xxxxxxxxxx", AInstEmit.Bsl_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x001110<<100000010010xxxxxxxxxx", AInstEmit.Cls_V, typeof(AOpCodeSimd));
|
SetA64("0x001110<<100000010010xxxxxxxxxx", AInstEmit.Cls_V, typeof(AOpCodeSimd));
|
||||||
SetA64("0x101110<<100000010010xxxxxxxxxx", AInstEmit.Clz_V, typeof(AOpCodeSimd));
|
SetA64("0x101110<<100000010010xxxxxxxxxx", AInstEmit.Clz_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("01111110111xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_S, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("0101111011100000100110xxxxxxxxxx", AInstEmit.Cmeq_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>001110<<100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
|
SetA64("0>001110<<100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("01011110111xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_S, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("0111111011100000100010xxxxxxxxxx", AInstEmit.Cmge_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0>001110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>101110<<100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
|
SetA64("0>101110<<100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("01011110111xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_S, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("0101111011100000100010xxxxxxxxxx", AInstEmit.Cmgt_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0>001110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>001110<<100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
|
SetA64("0>001110<<100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("01111110111xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_S, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>101110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("01111110111xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_S, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>101110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("0111111011100000100110xxxxxxxxxx", AInstEmit.Cmle_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0>101110<<100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
|
SetA64("0>101110<<100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("0101111011100000101010xxxxxxxxxx", AInstEmit.Cmlt_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0>001110<<100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
|
SetA64("0>001110<<100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("01011110111xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_S, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_V, typeof(AOpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd));
|
SetA64("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd));
|
||||||
SetA64("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns));
|
SetA64("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns));
|
||||||
|
|
|
@ -12,6 +12,11 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
static partial class AInstEmit
|
static partial class AInstEmit
|
||||||
{
|
{
|
||||||
|
public static void Cmeq_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Beq_S, Scalar: true);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Cmeq_V(AILEmitterCtx Context)
|
public static void Cmeq_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
if (AOptimizations.UseSse2 && Context.CurrOp is AOpCodeSimdReg Op && Op.Size < 3)
|
if (AOptimizations.UseSse2 && Context.CurrOp is AOpCodeSimdReg Op && Op.Size < 3)
|
||||||
|
@ -20,13 +25,23 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Beq_S);
|
EmitCmp(Context, OpCodes.Beq_S, Scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Cmge_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Bge_S, Scalar: true);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Cmge_V(AILEmitterCtx Context)
|
public static void Cmge_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Bge_S);
|
EmitCmp(Context, OpCodes.Bge_S, Scalar: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Cmgt_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Bgt_S, Scalar: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cmgt_V(AILEmitterCtx Context)
|
public static void Cmgt_V(AILEmitterCtx Context)
|
||||||
|
@ -37,67 +52,58 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Bgt_S);
|
EmitCmp(Context, OpCodes.Bgt_S, Scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Cmhi_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Bgt_Un_S, Scalar: true);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Cmhi_V(AILEmitterCtx Context)
|
public static void Cmhi_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Bgt_Un_S);
|
EmitCmp(Context, OpCodes.Bgt_Un_S, Scalar: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Cmhs_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Bge_Un_S, Scalar: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cmhs_V(AILEmitterCtx Context)
|
public static void Cmhs_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Bge_Un_S);
|
EmitCmp(Context, OpCodes.Bge_Un_S, Scalar: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Cmle_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Ble_S, Scalar: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cmle_V(AILEmitterCtx Context)
|
public static void Cmle_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Ble_S);
|
EmitCmp(Context, OpCodes.Ble_S, Scalar: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Cmlt_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmp(Context, OpCodes.Blt_S, Scalar: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cmlt_V(AILEmitterCtx Context)
|
public static void Cmlt_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorCmp(Context, OpCodes.Blt_S);
|
EmitCmp(Context, OpCodes.Blt_S, Scalar: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Cmtst_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitCmtst(Context, Scalar: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cmtst_V(AILEmitterCtx Context)
|
public static void Cmtst_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
EmitCmtst(Context, Scalar: false);
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
|
||||||
|
|
||||||
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
|
||||||
{
|
|
||||||
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
|
||||||
EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size);
|
|
||||||
|
|
||||||
AILLabel LblTrue = new AILLabel();
|
|
||||||
AILLabel LblEnd = new AILLabel();
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.And);
|
|
||||||
|
|
||||||
Context.EmitLdc_I8(0);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Bne_Un_S, LblTrue);
|
|
||||||
|
|
||||||
EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Br_S, LblEnd);
|
|
||||||
|
|
||||||
Context.MarkLabel(LblTrue);
|
|
||||||
|
|
||||||
EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask);
|
|
||||||
|
|
||||||
Context.MarkLabel(LblEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
|
||||||
{
|
|
||||||
EmitVectorZeroUpper(Context, Op.Rd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Fccmp_S(AILEmitterCtx Context)
|
public static void Fccmp_S(AILEmitterCtx Context)
|
||||||
|
@ -325,15 +331,16 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorCmp(AILEmitterCtx Context, OpCode ILOp)
|
private static void EmitCmp(AILEmitterCtx Context, OpCode ILOp, bool Scalar)
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||||
|
int Elems = (!Scalar ? Bytes >> Op.Size : 1);
|
||||||
|
|
||||||
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitVectorExtractSx(Context, Op.Rn, Index, Op.Size);
|
EmitVectorExtractSx(Context, Op.Rn, Index, Op.Size);
|
||||||
|
|
||||||
|
@ -362,7 +369,47 @@ namespace ChocolArm64.Instruction
|
||||||
Context.MarkLabel(LblEnd);
|
Context.MarkLabel(LblEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
|
||||||
|
{
|
||||||
|
EmitVectorZeroUpper(Context, Op.Rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitCmtst(AILEmitterCtx Context, bool Scalar)
|
||||||
|
{
|
||||||
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
|
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||||
|
int Elems = (!Scalar ? Bytes >> Op.Size : 1);
|
||||||
|
|
||||||
|
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
|
{
|
||||||
|
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
||||||
|
EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size);
|
||||||
|
|
||||||
|
AILLabel LblTrue = new AILLabel();
|
||||||
|
AILLabel LblEnd = new AILLabel();
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.And);
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(0);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Bne_Un_S, LblTrue);
|
||||||
|
|
||||||
|
EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Br_S, LblEnd);
|
||||||
|
|
||||||
|
Context.MarkLabel(LblTrue);
|
||||||
|
|
||||||
|
EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask);
|
||||||
|
|
||||||
|
Context.MarkLabel(LblEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
|
||||||
{
|
{
|
||||||
EmitVectorZeroUpper(Context, Op.Rd);
|
EmitVectorZeroUpper(Context, Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using ChocolArm64;
|
using ChocolArm64;
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
@ -38,8 +40,8 @@ namespace Ryujinx.Tests.Cpu
|
||||||
public void Teardown()
|
public void Teardown()
|
||||||
{
|
{
|
||||||
Memory.Dispose();
|
Memory.Dispose();
|
||||||
Thread = null;
|
|
||||||
Memory = null;
|
Memory = null;
|
||||||
|
Thread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Reset()
|
protected void Reset()
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define Alu
|
//#define Alu
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("Alu"), Ignore("Tested: first half of 2018.")]
|
[Category("Alu"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestAlu : CpuTest
|
public sealed class CpuTestAlu : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define AluImm
|
//#define AluImm
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("AluImm"), Ignore("Tested: first half of 2018.")]
|
[Category("AluImm"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestAluImm : CpuTest
|
public sealed class CpuTestAluImm : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define AluRs
|
//#define AluRs
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("AluRs"), Ignore("Tested: first half of 2018.")]
|
[Category("AluRs"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestAluRs : CpuTest
|
public sealed class CpuTestAluRs : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define AluRx
|
//#define AluRx
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("AluRx"), Ignore("Tested: first half of 2018.")]
|
[Category("AluRx"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestAluRx : CpuTest
|
public sealed class CpuTestAluRx : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define Bfm
|
//#define Bfm
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("Bfm"), Ignore("Tested: first half of 2018.")]
|
[Category("Bfm"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestBfm : CpuTest
|
public sealed class CpuTestBfm : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define CcmpImm
|
//#define CcmpImm
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("CcmpImm"), Ignore("Tested: first half of 2018.")]
|
[Category("CcmpImm"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestCcmpImm : CpuTest
|
public sealed class CpuTestCcmpImm : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define CcmpReg
|
//#define CcmpReg
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("CcmpReg"), Ignore("Tested: first half of 2018.")]
|
[Category("CcmpReg"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestCcmpReg : CpuTest
|
public sealed class CpuTestCcmpReg : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define Csel
|
//#define Csel
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("Csel"), Ignore("Tested: first half of 2018.")]
|
[Category("Csel"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestCsel : CpuTest
|
public sealed class CpuTestCsel : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define Mov
|
//#define Mov
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("Mov"), Ignore("Tested: first half of 2018.")]
|
[Category("Mov"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestMov : CpuTest
|
public sealed class CpuTestMov : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
//#define Mul
|
//#define Mul
|
||||||
|
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
|
using Tester;
|
||||||
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("Mul"), Ignore("Tested: first half of 2018.")]
|
[Category("Mul"), Ignore("Tested: first half of 2018.")]
|
||||||
public sealed class CpuTestMul : CpuTest
|
public sealed class CpuTestMul : CpuTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
using System.Runtime.Intrinsics.X86;
|
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Cpu
|
|
||||||
{
|
|
||||||
public class CpuTestScalar : CpuTest
|
|
||||||
{
|
|
||||||
[TestCase(0x1E224820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000000000000ul)]
|
|
||||||
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000000000000ul)]
|
|
||||||
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
|
|
||||||
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x000000003DCCCCCDul)]
|
|
||||||
[TestCase(0x1E224820u, 0x000000003DCCCCCDul, 0x000000003C9623B1ul, 0x000000003DCCCCCDul)]
|
|
||||||
[TestCase(0x1E224820u, 0x000000008BA98D27ul, 0x0000000000000076ul, 0x0000000000000076ul)]
|
|
||||||
[TestCase(0x1E224820u, 0x00000000807FFFFFul, 0x000000007F7FFFFFul, 0x000000007F7FFFFFul)]
|
|
||||||
[TestCase(0x1E224820u, 0x000000007F7FFFFFul, 0x00000000807FFFFFul, 0x000000007F7FFFFFul)]
|
|
||||||
[TestCase(0x1E224820u, 0x000000007FC00000ul, 0x000000003F800000ul, 0x000000007FC00000ul)]
|
|
||||||
[TestCase(0x1E224820u, 0x000000003F800000ul, 0x000000007FC00000ul, 0x000000007FC00000ul)]
|
|
||||||
[TestCase(0x1E224820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
|
||||||
[TestCase(0x1E224820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
|
||||||
[TestCase(0x1E224820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul, Ignore = "NaN test.")]
|
|
||||||
[TestCase(0x1E624820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x0000000000000000ul)]
|
|
||||||
[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));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(0x1E225820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000080000000ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x0000000080000000ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x000000003DCCCCCDul, 0x000000003C9623B1ul, 0x000000003C9623B1ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x000000008BA98D27ul, 0x0000000000000076ul, 0x000000008BA98D27ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x00000000807FFFFFul, 0x000000007F7FFFFFul, 0x00000000807FFFFFul)]
|
|
||||||
[TestCase(0x1E225820u, 0x000000007F7FFFFFul, 0x00000000807FFFFFul, 0x00000000807FFFFFul)]
|
|
||||||
[TestCase(0x1E225820u, 0x000000007FC00000ul, 0x000000003F800000ul, 0x000000007FC00000ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x000000003F800000ul, 0x000000007FC00000ul, 0x000000007FC00000ul)]
|
|
||||||
[TestCase(0x1E225820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
|
||||||
[TestCase(0x1E225820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
|
||||||
[TestCase(0x1E225820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul, Ignore = "NaN test.")]
|
|
||||||
[TestCase(0x1E625820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)]
|
|
||||||
[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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
using Tester;
|
using Tester;
|
||||||
using Tester.Types;
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("Simd")]
|
[Category("Simd")/*, Ignore("Tested: first half of 2018.")*/]
|
||||||
public sealed class CpuTestSimd : CpuTest
|
public sealed class CpuTestSimd : CpuTest
|
||||||
{
|
{
|
||||||
#if Simd
|
#if Simd
|
||||||
|
@ -45,6 +45,12 @@ namespace Ryujinx.Tests.Cpu
|
||||||
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ulong[] _8B_()
|
||||||
|
{
|
||||||
|
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul };
|
||||||
|
}
|
||||||
|
|
||||||
private static ulong[] _8B4H_()
|
private static ulong[] _8B4H_()
|
||||||
{
|
{
|
||||||
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
|
||||||
|
@ -297,6 +303,331 @@ namespace Ryujinx.Tests.Cpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMEQ <V><d>, <V><n>, #0")]
|
||||||
|
public void Cmeq_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x5EE09820; // CMEQ D0, D1, #0
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmeq_Zero_S(Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMEQ <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmeq_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x0E209820; // CMEQ V0.8B, V1.8B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmeq_Zero_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMEQ <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmeq_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x4E209820; // CMEQ V0.16B, V1.16B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
SimdFp.Cmeq_Zero_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGE <V><d>, <V><n>, #0")]
|
||||||
|
public void Cmge_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x7EE08820; // CMGE D0, D1, #0
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmge_Zero_S(Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGE <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmge_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E208820; // CMGE V0.8B, V1.8B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmge_Zero_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMGE <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmge_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E208820; // CMGE V0.16B, V1.16B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
SimdFp.Cmge_Zero_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGT <V><d>, <V><n>, #0")]
|
||||||
|
public void Cmgt_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x5EE08820; // CMGT D0, D1, #0
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmgt_Zero_S(Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGT <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmgt_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x0E208820; // CMGT V0.8B, V1.8B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmgt_Zero_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMGT <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmgt_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x4E208820; // CMGT V0.16B, V1.16B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
SimdFp.Cmgt_Zero_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMLE <V><d>, <V><n>, #0")]
|
||||||
|
public void Cmle_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x7EE09820; // CMLE D0, D1, #0
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmle_S(Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMLE <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmle_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E209820; // CMLE V0.8B, V1.8B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmle_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMLE <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmle_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E209820; // CMLE V0.16B, V1.16B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
SimdFp.Cmle_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMLT <V><d>, <V><n>, #0")]
|
||||||
|
public void Cmlt_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x5EE0A820; // CMLT D0, D1, #0
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmlt_S(Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMLT <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmlt_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x0E20A820; // CMLT V0.8B, V1.8B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Cmlt_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMLT <Vd>.<T>, <Vn>.<T>, #0")]
|
||||||
|
public void Cmlt_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x4E20A820; // CMLT V0.16B, V1.16B, #0
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
SimdFp.Cmlt_V(Op[30], Op[23, 22], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Test, Description("NEG <V><d>, <V><n>")]
|
[Test, Description("NEG <V><d>, <V><n>")]
|
||||||
public void Neg_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
public void Neg_S_D([ValueSource("_1D_")] [Random(1)] ulong A)
|
||||||
{
|
{
|
||||||
|
@ -362,6 +693,47 @@ namespace Ryujinx.Tests.Cpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test, Description("NOT <Vd>.<T>, <Vn>.<T>")]
|
||||||
|
public void Not_V_8B([ValueSource("_8B_")] [Random(1)] ulong A)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E205820; // NOT V0.8B, V1.8B
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
SimdFp.Not_V(Op[30], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("NOT <Vd>.<T>, <Vn>.<T>")]
|
||||||
|
public void Not_V_16B([ValueSource("_8B_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B_")] [Random(1)] ulong A1)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E205820; // NOT V0.16B, V1.16B
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
SimdFp.Not_V(Op[30], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Test, Description("SQXTN <Vb><d>, <Va><n>")]
|
[Test, Description("SQXTN <Vb><d>, <Va><n>")]
|
||||||
public void Sqxtn_S_HB_SH_DS([ValueSource("_1H1S1D_")] [Random(1)] ulong A,
|
public void Sqxtn_S_HB_SH_DS([ValueSource("_1H1S1D_")] [Random(1)] ulong A,
|
||||||
[Values(0b00u, 0b01u, 0b10u)] uint size) // <HB, SH, DS>
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <HB, SH, DS>
|
||||||
|
@ -384,7 +756,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
});
|
});
|
||||||
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27])); // FIXME: Temporary solution.
|
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("SQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
[Test, Pairwise, Description("SQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
||||||
|
@ -409,7 +781,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
});
|
});
|
||||||
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27])); // FIXME: Temporary solution.
|
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("SQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
[Test, Pairwise, Description("SQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
||||||
|
@ -435,7 +807,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(_X0));
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(_X0));
|
||||||
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
});
|
});
|
||||||
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27])); // FIXME: Temporary solution.
|
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("UQXTN <Vb><d>, <Va><n>")]
|
[Test, Description("UQXTN <Vb><d>, <Va><n>")]
|
||||||
|
@ -460,7 +832,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
});
|
});
|
||||||
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27])); // FIXME: Temporary solution.
|
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("UQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
[Test, Pairwise, Description("UQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
||||||
|
@ -485,7 +857,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
});
|
});
|
||||||
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27])); // FIXME: Temporary solution.
|
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("UQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
[Test, Pairwise, Description("UQXTN{2} <Vd>.<Tb>, <Vn>.<Ta>")]
|
||||||
|
@ -511,7 +883,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(_X0));
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(_X0));
|
||||||
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
});
|
});
|
||||||
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27])); // FIXME: Temporary solution.
|
Assert.That(((ThreadState.Fpsr >> 27) & 1) != 0, Is.EqualTo(Shared.FPSR[27]));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,32 @@ namespace Ryujinx.Tests.Cpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(0x1E224820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000000000000ul)]
|
||||||
|
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000000000000ul)]
|
||||||
|
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
|
||||||
|
[TestCase(0x1E224820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x000000003DCCCCCDul)]
|
||||||
|
[TestCase(0x1E224820u, 0x000000003DCCCCCDul, 0x000000003C9623B1ul, 0x000000003DCCCCCDul)]
|
||||||
|
[TestCase(0x1E224820u, 0x000000008BA98D27ul, 0x0000000000000076ul, 0x0000000000000076ul)]
|
||||||
|
[TestCase(0x1E224820u, 0x00000000807FFFFFul, 0x000000007F7FFFFFul, 0x000000007F7FFFFFul)]
|
||||||
|
[TestCase(0x1E224820u, 0x000000007F7FFFFFul, 0x00000000807FFFFFul, 0x000000007F7FFFFFul)]
|
||||||
|
[TestCase(0x1E224820u, 0x000000007FC00000ul, 0x000000003F800000ul, 0x000000007FC00000ul)]
|
||||||
|
[TestCase(0x1E224820u, 0x000000003F800000ul, 0x000000007FC00000ul, 0x000000007FC00000ul)]
|
||||||
|
[TestCase(0x1E224820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
||||||
|
[TestCase(0x1E224820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
||||||
|
[TestCase(0x1E224820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul, Ignore = "NaN test.")]
|
||||||
|
[TestCase(0x1E624820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x0000000000000000ul)]
|
||||||
|
[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));
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase(0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u)]
|
[TestCase(0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u)]
|
||||||
[TestCase(0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u)]
|
[TestCase(0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u)]
|
||||||
[TestCase(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u)]
|
[TestCase(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u)]
|
||||||
|
@ -75,6 +101,32 @@ namespace Ryujinx.Tests.Cpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(0x1E225820u, 0x0000000000000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000000000000ul, 0x0000000080000000ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x0000000080000000ul, 0x0000000080000000ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x0000000080000000ul, 0x000000003DCCCCCDul, 0x0000000080000000ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x000000003DCCCCCDul, 0x000000003C9623B1ul, 0x000000003C9623B1ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x000000008BA98D27ul, 0x0000000000000076ul, 0x000000008BA98D27ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x00000000807FFFFFul, 0x000000007F7FFFFFul, 0x00000000807FFFFFul)]
|
||||||
|
[TestCase(0x1E225820u, 0x000000007F7FFFFFul, 0x00000000807FFFFFul, 0x00000000807FFFFFul)]
|
||||||
|
[TestCase(0x1E225820u, 0x000000007FC00000ul, 0x000000003F800000ul, 0x000000007FC00000ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x000000003F800000ul, 0x000000007FC00000ul, 0x000000007FC00000ul)]
|
||||||
|
[TestCase(0x1E225820u, 0x000000007F800001ul, 0x000000007FC00042ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
||||||
|
[TestCase(0x1E225820u, 0x000000007FC00042ul, 0x000000007F800001ul, 0x000000007FC00001ul, Ignore = "NaN test.")]
|
||||||
|
[TestCase(0x1E225820u, 0x000000007FC0000Aul, 0x000000007FC0000Bul, 0x000000007FC0000Aul, Ignore = "NaN test.")]
|
||||||
|
[TestCase(0x1E625820u, 0x0000000000000000ul, 0x8000000000000000ul, 0x8000000000000000ul)]
|
||||||
|
[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));
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase(0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u)]
|
[TestCase(0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u)]
|
||||||
[TestCase(0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u)]
|
[TestCase(0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u)]
|
||||||
[TestCase(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u)]
|
[TestCase(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u)]
|
||||||
|
@ -101,7 +153,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("fmul s6, s1, v0.s[2]")]
|
[Test, Description("FMUL S6, S1, V0.S[2]")]
|
||||||
public void Fmul_Se([Random(10)] float A, [Random(10)] float B)
|
public void Fmul_Se([Random(10)] float A, [Random(10)] float B)
|
||||||
{
|
{
|
||||||
AThreadState ThreadState = SingleOpcode(0x5F809826,
|
AThreadState ThreadState = SingleOpcode(0x5F809826,
|
||||||
|
@ -111,7 +163,15 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(Sse41.Extract(ThreadState.V6, (byte)0), Is.EqualTo(A * B));
|
Assert.That(Sse41.Extract(ThreadState.V6, (byte)0), Is.EqualTo(A * B));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("frecpe v2.4s, v0.4s")]
|
[Test, Description("FRECPE D0, D1")]
|
||||||
|
public void Frecpe_S([Random(100)] double A)
|
||||||
|
{
|
||||||
|
AThreadState ThreadState = SingleOpcode(0x5EE1D820, V1: MakeVectorE0(A));
|
||||||
|
|
||||||
|
Assert.That(VectorExtractDouble(ThreadState.V0, 0), Is.EqualTo(1 / A));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("FRECPE V2.4S, V0.4S")]
|
||||||
public void Frecpe_V([Random(100)] float A)
|
public void Frecpe_V([Random(100)] float A)
|
||||||
{
|
{
|
||||||
AThreadState ThreadState = SingleOpcode(0x4EA1D802, V0: Sse.SetAllVector128(A));
|
AThreadState ThreadState = SingleOpcode(0x4EA1D802, V0: Sse.SetAllVector128(A));
|
||||||
|
@ -122,15 +182,17 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(Sse41.Extract(ThreadState.V2, (byte)3), Is.EqualTo(1 / A));
|
Assert.That(Sse41.Extract(ThreadState.V2, (byte)3), Is.EqualTo(1 / A));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("frecpe d0, d1")]
|
[Test, Description("FRECPS D0, D1, D2")]
|
||||||
public void Frecpe_S([Random(100)] double A)
|
public void Frecps_S([Random(10)] double A, [Random(10)] double B)
|
||||||
{
|
{
|
||||||
AThreadState ThreadState = SingleOpcode(0x5EE1D820, V1: MakeVectorE0(A));
|
AThreadState ThreadState = SingleOpcode(0x5E62FC20,
|
||||||
|
V1: MakeVectorE0(A),
|
||||||
|
V2: MakeVectorE0(B));
|
||||||
|
|
||||||
Assert.That(VectorExtractDouble(ThreadState.V0, 0), Is.EqualTo(1 / A));
|
Assert.That(VectorExtractDouble(ThreadState.V0, 0), Is.EqualTo(2 - (A * B)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("frecps v4.4s, v2.4s, v0.4s")]
|
[Test, Description("FRECPS V4.4S, V2.4S, V0.4S")]
|
||||||
public void Frecps_V([Random(10)] float A, [Random(10)] float B)
|
public void Frecps_V([Random(10)] float A, [Random(10)] float B)
|
||||||
{
|
{
|
||||||
AThreadState ThreadState = SingleOpcode(0x4E20FC44,
|
AThreadState ThreadState = SingleOpcode(0x4E20FC44,
|
||||||
|
@ -143,16 +205,6 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(Sse41.Extract(ThreadState.V4, (byte)3), Is.EqualTo(2 - (A * B)));
|
Assert.That(Sse41.Extract(ThreadState.V4, (byte)3), Is.EqualTo(2 - (A * B)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("frecps d0, d1, d2")]
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(0x3FE66666u, false, 0x40000000u)]
|
[TestCase(0x3FE66666u, false, 0x40000000u)]
|
||||||
[TestCase(0x3F99999Au, false, 0x3F800000u)]
|
[TestCase(0x3F99999Au, false, 0x3F800000u)]
|
||||||
[TestCase(0x404CCCCDu, false, 0x40400000u)]
|
[TestCase(0x404CCCCDu, false, 0x40400000u)]
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
{
|
{
|
||||||
public class CpuTestSimdMove : CpuTest
|
public class CpuTestSimdMove : CpuTest
|
||||||
{
|
{
|
||||||
[Test, Description("trn1 v0.4s, v1.4s, v2.4s")]
|
[Test, Description("TRN1 V0.4S, V1.4S, V2.4S")]
|
||||||
public void Trn1_V_4S([Random(2)] uint A0, [Random(2)] uint A1, [Random(2)] uint A2, [Random(2)] uint A3,
|
public void Trn1_V_4S([Random(2)] uint A0, [Random(2)] uint A1, [Random(2)] uint A2, [Random(2)] uint A3,
|
||||||
[Random(2)] uint B0, [Random(2)] uint B1, [Random(2)] uint B2, [Random(2)] uint B3)
|
[Random(2)] uint B0, [Random(2)] uint B1, [Random(2)] uint B2, [Random(2)] uint B3)
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V0), (byte)3), Is.EqualTo(B2));
|
Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V0), (byte)3), Is.EqualTo(B2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("trn1 v0.8b, v1.8b, v2.8b")]
|
[Test, Description("TRN1 V0.8B, V1.8B, V2.8B")]
|
||||||
public void Trn1_V_8B([Random(2)] byte A0, [Random(1)] byte A1, [Random(2)] byte A2, [Random(1)] byte A3,
|
public void Trn1_V_8B([Random(2)] byte A0, [Random(1)] byte A1, [Random(2)] byte A2, [Random(1)] byte A3,
|
||||||
[Random(2)] byte A4, [Random(1)] byte A5, [Random(2)] byte A6, [Random(1)] byte A7,
|
[Random(2)] byte A4, [Random(1)] byte A5, [Random(2)] byte A6, [Random(1)] byte A7,
|
||||||
[Random(2)] byte B0, [Random(1)] byte B1, [Random(2)] byte B2, [Random(1)] byte B3,
|
[Random(2)] byte B0, [Random(1)] byte B1, [Random(2)] byte B2, [Random(1)] byte B3,
|
||||||
|
@ -49,7 +49,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(Sse41.Extract(Sse.StaticCast<float, byte>(ThreadState.V0), (byte)7), Is.EqualTo(B6));
|
Assert.That(Sse41.Extract(Sse.StaticCast<float, byte>(ThreadState.V0), (byte)7), Is.EqualTo(B6));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("trn2 v0.4s, v1.4s, v2.4s")]
|
[Test, Description("TRN2 V0.4S, V1.4S, V2.4S")]
|
||||||
public void Trn2_V_4S([Random(2)] uint A0, [Random(2)] uint A1, [Random(2)] uint A2, [Random(2)] uint A3,
|
public void Trn2_V_4S([Random(2)] uint A0, [Random(2)] uint A1, [Random(2)] uint A2, [Random(2)] uint A3,
|
||||||
[Random(2)] uint B0, [Random(2)] uint B1, [Random(2)] uint B2, [Random(2)] uint B3)
|
[Random(2)] uint B0, [Random(2)] uint B1, [Random(2)] uint B2, [Random(2)] uint B3)
|
||||||
{
|
{
|
||||||
|
@ -65,7 +65,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V0), (byte)3), Is.EqualTo(B3));
|
Assert.That(Sse41.Extract(Sse.StaticCast<float, uint>(ThreadState.V0), (byte)3), Is.EqualTo(B3));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Description("trn2 v0.8b, v1.8b, v2.8b")]
|
[Test, Description("TRN2 V0.8B, V1.8B, V2.8B")]
|
||||||
public void Trn2_V_8B([Random(1)] byte A0, [Random(2)] byte A1, [Random(1)] byte A2, [Random(2)] byte A3,
|
public void Trn2_V_8B([Random(1)] byte A0, [Random(2)] byte A1, [Random(1)] byte A2, [Random(2)] byte A3,
|
||||||
[Random(1)] byte A4, [Random(2)] byte A5, [Random(1)] byte A6, [Random(2)] byte A7,
|
[Random(1)] byte A4, [Random(2)] byte A5, [Random(1)] byte A6, [Random(2)] byte A7,
|
||||||
[Random(1)] byte B0, [Random(2)] byte B1, [Random(1)] byte B2, [Random(2)] byte B3,
|
[Random(1)] byte B0, [Random(2)] byte B1, [Random(1)] byte B2, [Random(2)] byte B3,
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
using Tester;
|
using Tester;
|
||||||
using Tester.Types;
|
using Tester.Types;
|
||||||
|
|
||||||
[Category("SimdReg")]
|
[Category("SimdReg")/*, Ignore("Tested: first half of 2018.")*/]
|
||||||
public sealed class CpuTestSimdReg : CpuTest
|
public sealed class CpuTestSimdReg : CpuTest
|
||||||
{
|
{
|
||||||
#if SimdReg
|
#if SimdReg
|
||||||
|
@ -514,6 +514,511 @@ namespace Ryujinx.Tests.Cpu
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMEQ <V><d>, <V><n>, <V><m>")]
|
||||||
|
public void Cmeq_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_1D_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x7EE28C20; // CMEQ D0, D1, D2
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmeq_Reg_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMEQ <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmeq_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B4H2S_")] [Random(1)] ulong B,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E228C20; // CMEQ V0.8B, V1.8B, V2.8B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmeq_Reg_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMEQ <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmeq_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E228C20; // CMEQ V0.16B, V1.16B, V2.16B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Cmeq_Reg_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGE <V><d>, <V><n>, <V><m>")]
|
||||||
|
public void Cmge_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_1D_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x5EE23C20; // CMGE D0, D1, D2
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmge_Reg_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGE <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmge_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B4H2S_")] [Random(1)] ulong B,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x0E223C20; // CMGE V0.8B, V1.8B, V2.8B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmge_Reg_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMGE <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmge_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x4E223C20; // CMGE V0.16B, V1.16B, V2.16B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Cmge_Reg_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGT <V><d>, <V><n>, <V><m>")]
|
||||||
|
public void Cmgt_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_1D_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x5EE23420; // CMGT D0, D1, D2
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmgt_Reg_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMGT <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmgt_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B4H2S_")] [Random(1)] ulong B,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x0E223420; // CMGT V0.8B, V1.8B, V2.8B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmgt_Reg_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMGT <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmgt_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x4E223420; // CMGT V0.16B, V1.16B, V2.16B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Cmgt_Reg_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMHI <V><d>, <V><n>, <V><m>")]
|
||||||
|
public void Cmhi_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_1D_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x7EE23420; // CMHI D0, D1, D2
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmhi_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMHI <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmhi_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B4H2S_")] [Random(1)] ulong B,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E223420; // CMHI V0.8B, V1.8B, V2.8B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmhi_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMHI <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmhi_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E223420; // CMHI V0.16B, V1.16B, V2.16B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Cmhi_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMHS <V><d>, <V><n>, <V><m>")]
|
||||||
|
public void Cmhs_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_1D_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x7EE23C20; // CMHS D0, D1, D2
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmhs_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMHS <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmhs_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B4H2S_")] [Random(1)] ulong B,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E223C20; // CMHS V0.8B, V1.8B, V2.8B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmhs_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMHS <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmhs_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E223C20; // CMHS V0.16B, V1.16B, V2.16B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Cmhs_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMTST <V><d>, <V><n>, <V><m>")]
|
||||||
|
public void Cmtst_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_1D_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x5EE28C20; // CMTST D0, D1, D2
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmtst_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("CMTST <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmtst_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B4H2S_")] [Random(1)] ulong B,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x0E228C20; // CMTST V0.8B, V1.8B, V2.8B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Cmtst_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("CMTST <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Cmtst_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
|
||||||
|
{
|
||||||
|
uint Opcode = 0x4E228C20; // CMTST V0.16B, V1.16B, V2.16B
|
||||||
|
Opcode |= ((size & 3) << 22);
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Cmtst_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Description("EOR <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Eor_V_8B([ValueSource("_8B_")] [Random(1)] ulong A,
|
||||||
|
[ValueSource("_8B_")] [Random(1)] ulong B)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x2E221C20; // EOR V0.8B, V1.8B, V2.8B
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V0 = MakeVectorE1(TestContext.CurrentContext.Random.NextULong());
|
||||||
|
Vector128<float> V1 = MakeVectorE0(A);
|
||||||
|
Vector128<float> V2 = MakeVectorE0(B);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.V(1, new Bits(A));
|
||||||
|
AArch64.V(2, new Bits(B));
|
||||||
|
SimdFp.Eor_V(Op[30], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("EOR <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
|
public void Eor_V_16B([ValueSource("_8B_")] [Random(1)] ulong A0,
|
||||||
|
[ValueSource("_8B_")] [Random(1)] ulong A1,
|
||||||
|
[ValueSource("_8B_")] [Random(1)] ulong B0,
|
||||||
|
[ValueSource("_8B_")] [Random(1)] ulong B1)
|
||||||
|
{
|
||||||
|
uint Opcode = 0x6E221C20; // EOR V0.16B, V1.16B, V2.16B
|
||||||
|
Bits Op = new Bits(Opcode);
|
||||||
|
|
||||||
|
Vector128<float> V1 = MakeVectorE0E1(A0, A1);
|
||||||
|
Vector128<float> V2 = MakeVectorE0E1(B0, B1);
|
||||||
|
AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
|
||||||
|
|
||||||
|
AArch64.Vpart(1, 0, new Bits(A0));
|
||||||
|
AArch64.Vpart(1, 1, new Bits(A1));
|
||||||
|
AArch64.Vpart(2, 0, new Bits(B0));
|
||||||
|
AArch64.Vpart(2, 1, new Bits(B1));
|
||||||
|
SimdFp.Eor_V(Op[30], Op[20, 16], Op[9, 5], Op[4, 0]);
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(GetVectorE0(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
|
||||||
|
Assert.That(GetVectorE1(ThreadState.V0), Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Test, Description("ORN <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
[Test, Description("ORN <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
|
||||||
public void Orn_V_8B([ValueSource("_8B_")] [Random(1)] ulong A,
|
public void Orn_V_8B([ValueSource("_8B_")] [Random(1)] ulong A,
|
||||||
[ValueSource("_8B_")] [Random(1)] ulong B)
|
[ValueSource("_8B_")] [Random(1)] ulong B)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,8 @@
|
||||||
// https://github.com/LDj3SNuD/ARM_v8-A_AArch64_Instructions_Tester/blob/master/Tester/Pseudocode.cs
|
// https://github.com/LDj3SNuD/ARM_v8-A_AArch64_Instructions_Tester/blob/master/Tester/Pseudocode.cs
|
||||||
|
|
||||||
// https://meriac.github.io/archex/A64_v83A_ISA/shared_pseudocode.xml
|
// https://developer.arm.com/products/architecture/a-profile/exploration-tools
|
||||||
|
// ..\A64_v83A_ISA_xml_00bet6.1\ISA_v83A_A64_xml_00bet6.1_OPT\xhtml\
|
||||||
|
|
||||||
// https://alastairreid.github.io/asl-lexical-syntax/
|
// https://alastairreid.github.io/asl-lexical-syntax/
|
||||||
|
|
||||||
// | ------------------------|----------------------------------- |
|
// | ------------------------|----------------------------------- |
|
||||||
|
@ -31,7 +33,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
internal static class AArch64
|
internal static class AArch64
|
||||||
{
|
{
|
||||||
#region "exceptions/exceptions/"
|
#region "exceptions/exceptions/"
|
||||||
/* #AArch64.ResetControlRegisters.1 */
|
/* shared_pseudocode.html#AArch64.ResetControlRegisters.1 */
|
||||||
public static void ResetControlRegisters(bool cold_reset)
|
public static void ResetControlRegisters(bool cold_reset)
|
||||||
{
|
{
|
||||||
PSTATE.N = cold_reset;
|
PSTATE.N = cold_reset;
|
||||||
|
@ -76,7 +78,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "functions/registers/"
|
#region "functions/registers/"
|
||||||
/* #AArch64.ResetGeneralRegisters.0 */
|
/* shared_pseudocode.html#AArch64.ResetGeneralRegisters.0 */
|
||||||
public static void ResetGeneralRegisters()
|
public static void ResetGeneralRegisters()
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= 30; i++)
|
for (int i = 0; i <= 30; i++)
|
||||||
|
@ -86,7 +88,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #AArch64.ResetSIMDFPRegisters.0 */
|
/* shared_pseudocode.html#AArch64.ResetSIMDFPRegisters.0 */
|
||||||
public static void ResetSIMDFPRegisters()
|
public static void ResetSIMDFPRegisters()
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= 31; i++)
|
for (int i = 0; i <= 31; i++)
|
||||||
|
@ -96,7 +98,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #AArch64.ResetSpecialRegisters.0 */
|
/* shared_pseudocode.html#AArch64.ResetSpecialRegisters.0 */
|
||||||
public static void ResetSpecialRegisters()
|
public static void ResetSpecialRegisters()
|
||||||
{
|
{
|
||||||
// AArch64 special registers
|
// AArch64 special registers
|
||||||
|
@ -105,10 +107,10 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
/* SP_EL1 = bits(64) UNKNOWN; */
|
/* SP_EL1 = bits(64) UNKNOWN; */
|
||||||
SP_EL1.SetAll(false);
|
SP_EL1.SetAll(false);
|
||||||
|
|
||||||
FPSR.SetAll(false); // FIXME: Temporary solution.
|
FPSR.SetAll(false); // TODO: Add named fields.
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-aarch64.SP.write.0
|
// shared_pseudocode.html#impl-aarch64.SP.write.0
|
||||||
public static void SP(Bits value)
|
public static void SP(Bits value)
|
||||||
{
|
{
|
||||||
/* int width = value.Count; */
|
/* int width = value.Count; */
|
||||||
|
@ -140,7 +142,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-aarch64.SP.read.0
|
// shared_pseudocode.html#impl-aarch64.SP.read.0
|
||||||
public static Bits SP(int width)
|
public static Bits SP(int width)
|
||||||
{
|
{
|
||||||
/* assert width IN {8,16,32,64}; */
|
/* assert width IN {8,16,32,64}; */
|
||||||
|
@ -166,7 +168,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-aarch64.V.write.1
|
// shared_pseudocode.html#impl-aarch64.V.write.1
|
||||||
public static void V(int n, Bits value)
|
public static void V(int n, Bits value)
|
||||||
{
|
{
|
||||||
/* int width = value.Count; */
|
/* int width = value.Count; */
|
||||||
|
@ -177,7 +179,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
_V[n] = ZeroExtend(128, value);
|
_V[n] = ZeroExtend(128, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-aarch64.V.read.1 */
|
/* shared_pseudocode.html#impl-aarch64.V.read.1 */
|
||||||
public static Bits V(int width, int n)
|
public static Bits V(int width, int n)
|
||||||
{
|
{
|
||||||
/* assert n >= 0 && n <= 31; */
|
/* assert n >= 0 && n <= 31; */
|
||||||
|
@ -186,7 +188,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return _V[n][width - 1, 0];
|
return _V[n][width - 1, 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-aarch64.Vpart.read.2 */
|
/* shared_pseudocode.html#impl-aarch64.Vpart.read.2 */
|
||||||
public static Bits Vpart(int width, int n, int part)
|
public static Bits Vpart(int width, int n, int part)
|
||||||
{
|
{
|
||||||
/* assert n >= 0 && n <= 31; */
|
/* assert n >= 0 && n <= 31; */
|
||||||
|
@ -204,7 +206,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-aarch64.Vpart.write.2
|
// shared_pseudocode.html#impl-aarch64.Vpart.write.2
|
||||||
public static void Vpart(int n, int part, Bits value)
|
public static void Vpart(int n, int part, Bits value)
|
||||||
{
|
{
|
||||||
int width = value.Count;
|
int width = value.Count;
|
||||||
|
@ -224,7 +226,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-aarch64.X.write.1
|
// shared_pseudocode.html#impl-aarch64.X.write.1
|
||||||
public static void X(int n, Bits value)
|
public static void X(int n, Bits value)
|
||||||
{
|
{
|
||||||
/* int width = value.Count; */
|
/* int width = value.Count; */
|
||||||
|
@ -238,7 +240,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-aarch64.X.read.1 */
|
/* shared_pseudocode.html#impl-aarch64.X.read.1 */
|
||||||
public static Bits X(int width, int n)
|
public static Bits X(int width, int n)
|
||||||
{
|
{
|
||||||
/* assert n >= 0 && n <= 31; */
|
/* assert n >= 0 && n <= 31; */
|
||||||
|
@ -256,12 +258,12 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "instrs/countop/"
|
#region "instrs/countop/"
|
||||||
// #CountOp
|
// shared_pseudocode.html#CountOp
|
||||||
public enum CountOp {CountOp_CLZ, CountOp_CLS, CountOp_CNT};
|
public enum CountOp {CountOp_CLZ, CountOp_CLS, CountOp_CNT};
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "instrs/extendreg/"
|
#region "instrs/extendreg/"
|
||||||
/* #impl-aarch64.DecodeRegExtend.1 */
|
/* shared_pseudocode.html#impl-aarch64.DecodeRegExtend.1 */
|
||||||
public static ExtendType DecodeRegExtend(Bits op)
|
public static ExtendType DecodeRegExtend(Bits op)
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
|
@ -286,7 +288,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-aarch64.ExtendReg.3 */
|
/* shared_pseudocode.html#impl-aarch64.ExtendReg.3 */
|
||||||
public static Bits ExtendReg(int N, int reg, ExtendType type, int shift)
|
public static Bits ExtendReg(int N, int reg, ExtendType type, int shift)
|
||||||
{
|
{
|
||||||
/* assert shift >= 0 && shift <= 4; */
|
/* assert shift >= 0 && shift <= 4; */
|
||||||
|
@ -335,13 +337,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return Extend(Bits.Concat(val[len - 1, 0], Zeros(shift)), N, unsigned);
|
return Extend(Bits.Concat(val[len - 1, 0], Zeros(shift)), N, unsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #ExtendType
|
// shared_pseudocode.html#ExtendType
|
||||||
public enum ExtendType {ExtendType_SXTB, ExtendType_SXTH, ExtendType_SXTW, ExtendType_SXTX,
|
public enum ExtendType {ExtendType_SXTB, ExtendType_SXTH, ExtendType_SXTW, ExtendType_SXTX,
|
||||||
ExtendType_UXTB, ExtendType_UXTH, ExtendType_UXTW, ExtendType_UXTX};
|
ExtendType_UXTB, ExtendType_UXTH, ExtendType_UXTW, ExtendType_UXTX};
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "instrs/integer/bitmasks/"
|
#region "instrs/integer/bitmasks/"
|
||||||
/* #impl-aarch64.DecodeBitMasks.4 */
|
/* shared_pseudocode.html#impl-aarch64.DecodeBitMasks.4 */
|
||||||
public static (Bits, Bits) DecodeBitMasks(int M, bool immN, Bits imms, Bits immr, bool immediate)
|
public static (Bits, Bits) DecodeBitMasks(int M, bool immN, Bits imms, Bits immr, bool immediate)
|
||||||
{
|
{
|
||||||
Bits tmask, wmask;
|
Bits tmask, wmask;
|
||||||
|
@ -404,7 +406,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "instrs/integer/shiftreg/"
|
#region "instrs/integer/shiftreg/"
|
||||||
/* #impl-aarch64.DecodeShift.1 */
|
/* shared_pseudocode.html#impl-aarch64.DecodeShift.1 */
|
||||||
public static ShiftType DecodeShift(Bits op)
|
public static ShiftType DecodeShift(Bits op)
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
|
@ -421,7 +423,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-aarch64.ShiftReg.3 */
|
/* shared_pseudocode.html#impl-aarch64.ShiftReg.3 */
|
||||||
public static Bits ShiftReg(int N, int reg, ShiftType type, int amount)
|
public static Bits ShiftReg(int N, int reg, ShiftType type, int amount)
|
||||||
{
|
{
|
||||||
Bits result = X(N, reg);
|
Bits result = X(N, reg);
|
||||||
|
@ -446,10 +448,15 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #ShiftType
|
// shared_pseudocode.html#ShiftType
|
||||||
public enum ShiftType {ShiftType_LSL, ShiftType_LSR, ShiftType_ASR, ShiftType_ROR};
|
public enum ShiftType {ShiftType_LSL, ShiftType_LSR, ShiftType_ASR, ShiftType_ROR};
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region "instrs/vector/arithmetic/unary/cmp/compareop/"
|
||||||
|
// shared_pseudocode.html#CompareOp
|
||||||
|
public enum CompareOp {CompareOp_GT, CompareOp_GE, CompareOp_EQ, CompareOp_LE, CompareOp_LT};
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region "instrs/vector/reduce/reduceop/"
|
#region "instrs/vector/reduce/reduceop/"
|
||||||
public static Bits Reduce(ReduceOp op, Bits input, int esize)
|
public static Bits Reduce(ReduceOp op, Bits input, int esize)
|
||||||
{
|
{
|
||||||
|
@ -495,6 +502,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shared_pseudocode.html#ReduceOp
|
||||||
public enum ReduceOp {ReduceOp_FMINNUM, ReduceOp_FMAXNUM,
|
public enum ReduceOp {ReduceOp_FMINNUM, ReduceOp_FMAXNUM,
|
||||||
ReduceOp_FMIN, ReduceOp_FMAX,
|
ReduceOp_FMIN, ReduceOp_FMAX,
|
||||||
ReduceOp_FADD, ReduceOp_ADD};
|
ReduceOp_FADD, ReduceOp_ADD};
|
||||||
|
@ -520,7 +528,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
SP_EL0 = new Bits(64, false);
|
SP_EL0 = new Bits(64, false);
|
||||||
SP_EL1 = new Bits(64, false);
|
SP_EL1 = new Bits(64, false);
|
||||||
|
|
||||||
FPSR = new Bits(32, false); // FIXME: Temporary solution.
|
FPSR = new Bits(32, false); // TODO: Add named fields.
|
||||||
|
|
||||||
PSTATE.N = false;
|
PSTATE.N = false;
|
||||||
PSTATE.Z = false;
|
PSTATE.Z = false;
|
||||||
|
@ -537,7 +545,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return x.And(y);
|
return x.And(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.ASR.2
|
// shared_pseudocode.html#impl-shared.ASR.2
|
||||||
public static Bits ASR(Bits x, int shift)
|
public static Bits ASR(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -558,7 +566,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.ASR_C.2
|
// shared_pseudocode.html#impl-shared.ASR_C.2
|
||||||
public static (Bits, bool) ASR_C(Bits x, int shift)
|
public static (Bits, bool) ASR_C(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -572,13 +580,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (result, carry_out);
|
return (result, carry_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Abs.1
|
// shared_pseudocode.html#impl-shared.Abs.1
|
||||||
public static BigInteger Abs(BigInteger x)
|
public static BigInteger Abs(BigInteger x)
|
||||||
{
|
{
|
||||||
return (x >= 0 ? x : -x);
|
return (x >= 0 ? x : -x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.CountLeadingSignBits.1
|
// shared_pseudocode.html#impl-shared.CountLeadingSignBits.1
|
||||||
public static int CountLeadingSignBits(Bits x)
|
public static int CountLeadingSignBits(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -586,7 +594,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return CountLeadingZeroBits(EOR(x[N - 1, 1], x[N - 2, 0]));
|
return CountLeadingZeroBits(EOR(x[N - 1, 1], x[N - 2, 0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.CountLeadingZeroBits.1
|
// shared_pseudocode.html#impl-shared.CountLeadingZeroBits.1
|
||||||
public static int CountLeadingZeroBits(Bits x)
|
public static int CountLeadingZeroBits(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -594,7 +602,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (N - 1 - HighestSetBit(x));
|
return (N - 1 - HighestSetBit(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Elem.read.3
|
// shared_pseudocode.html#impl-shared.Elem.read.3
|
||||||
public static Bits Elem(/*in */Bits vector, int e, int size)
|
public static Bits Elem(/*in */Bits vector, int e, int size)
|
||||||
{
|
{
|
||||||
/* int N = vector.Count; */
|
/* int N = vector.Count; */
|
||||||
|
@ -604,7 +612,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return vector[e * size + size - 1, e * size];
|
return vector[e * size + size - 1, e * size];
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Elem.write.3
|
// shared_pseudocode.html#impl-shared.Elem.write.3
|
||||||
public static void Elem(/*out */Bits vector, int e, int size, Bits value)
|
public static void Elem(/*out */Bits vector, int e, int size, Bits value)
|
||||||
{
|
{
|
||||||
/* int N = vector.Count; */
|
/* int N = vector.Count; */
|
||||||
|
@ -620,7 +628,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return x.Xor(y);
|
return x.Xor(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Extend.3
|
// shared_pseudocode.html#impl-shared.Extend.3
|
||||||
public static Bits Extend(Bits x, int N, bool unsigned)
|
public static Bits Extend(Bits x, int N, bool unsigned)
|
||||||
{
|
{
|
||||||
if (unsigned)
|
if (unsigned)
|
||||||
|
@ -633,13 +641,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.Extend.2 */
|
/* shared_pseudocode.html#impl-shared.Extend.2 */
|
||||||
public static Bits Extend(int N, Bits x, bool unsigned)
|
public static Bits Extend(int N, Bits x, bool unsigned)
|
||||||
{
|
{
|
||||||
return Extend(x, N, unsigned);
|
return Extend(x, N, unsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.HighestSetBit.1
|
// shared_pseudocode.html#impl-shared.HighestSetBit.1
|
||||||
public static int HighestSetBit(Bits x)
|
public static int HighestSetBit(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -655,13 +663,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Int.2
|
// shared_pseudocode.html#impl-shared.Int.2
|
||||||
public static BigInteger Int(Bits x, bool unsigned)
|
public static BigInteger Int(Bits x, bool unsigned)
|
||||||
{
|
{
|
||||||
return (unsigned ? UInt(x) : SInt(x));
|
return (unsigned ? UInt(x) : SInt(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.IsOnes.1
|
// shared_pseudocode.html#impl-shared.IsOnes.1
|
||||||
public static bool IsOnes(Bits x)
|
public static bool IsOnes(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -669,7 +677,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (x == Ones(N));
|
return (x == Ones(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.IsZero.1
|
// shared_pseudocode.html#impl-shared.IsZero.1
|
||||||
public static bool IsZero(Bits x)
|
public static bool IsZero(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -677,13 +685,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (x == Zeros(N));
|
return (x == Zeros(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.IsZeroBit.1
|
// shared_pseudocode.html#impl-shared.IsZeroBit.1
|
||||||
public static bool IsZeroBit(Bits x)
|
public static bool IsZeroBit(Bits x)
|
||||||
{
|
{
|
||||||
return IsZero(x);
|
return IsZero(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.LSL.2
|
// shared_pseudocode.html#impl-shared.LSL.2
|
||||||
public static Bits LSL(Bits x, int shift)
|
public static Bits LSL(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -704,7 +712,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.LSL_C.2
|
// shared_pseudocode.html#impl-shared.LSL_C.2
|
||||||
public static (Bits, bool) LSL_C(Bits x, int shift)
|
public static (Bits, bool) LSL_C(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -718,7 +726,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (result, carry_out);
|
return (result, carry_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.LSR.2
|
// shared_pseudocode.html#impl-shared.LSR.2
|
||||||
public static Bits LSR(Bits x, int shift)
|
public static Bits LSR(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -739,7 +747,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.LSR_C.2
|
// shared_pseudocode.html#impl-shared.LSR_C.2
|
||||||
public static (Bits, bool) LSR_C(Bits x, int shift)
|
public static (Bits, bool) LSR_C(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -753,7 +761,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (result, carry_out);
|
return (result, carry_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Min.2
|
// shared_pseudocode.html#impl-shared.Min.2
|
||||||
public static int Min(int a, int b)
|
public static int Min(int a, int b)
|
||||||
{
|
{
|
||||||
if (a <= b)
|
if (a <= b)
|
||||||
|
@ -766,13 +774,14 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.NOT.1 */
|
/* shared_pseudocode.html#impl-shared.NOT.1 */
|
||||||
public static Bits NOT(Bits x)
|
public static Bits NOT(Bits x)
|
||||||
{
|
{
|
||||||
return x.Not();
|
return x.Not();
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Ones.1
|
// shared_pseudocode.html#impl-shared.Ones.1
|
||||||
|
/* shared_pseudocode.html#impl-shared.Ones.0 */
|
||||||
public static Bits Ones(int N)
|
public static Bits Ones(int N)
|
||||||
{
|
{
|
||||||
return Replicate(true, N);
|
return Replicate(true, N);
|
||||||
|
@ -790,7 +799,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (decimal)value;
|
return (decimal)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.ROR.2
|
// shared_pseudocode.html#impl-shared.ROR.2
|
||||||
public static Bits ROR(Bits x, int shift)
|
public static Bits ROR(Bits x, int shift)
|
||||||
{
|
{
|
||||||
/* assert shift >= 0; */
|
/* assert shift >= 0; */
|
||||||
|
@ -809,7 +818,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.ROR_C.2
|
// shared_pseudocode.html#impl-shared.ROR_C.2
|
||||||
public static (Bits, bool) ROR_C(Bits x, int shift)
|
public static (Bits, bool) ROR_C(Bits x, int shift)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -823,7 +832,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (result, carry_out);
|
return (result, carry_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.Replicate.1 */
|
/* shared_pseudocode.html#impl-shared.Replicate.1 */
|
||||||
public static Bits Replicate(int N, Bits x)
|
public static Bits Replicate(int N, Bits x)
|
||||||
{
|
{
|
||||||
int M = x.Count;
|
int M = x.Count;
|
||||||
|
@ -833,7 +842,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return Replicate(x, N / M);
|
return Replicate(x, N / M);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.Replicate.2 */
|
/* shared_pseudocode.html#impl-shared.Replicate.2 */
|
||||||
public static Bits Replicate(Bits x, int N)
|
public static Bits Replicate(Bits x, int N)
|
||||||
{
|
{
|
||||||
int M = x.Count;
|
int M = x.Count;
|
||||||
|
@ -848,13 +857,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return new Bits(dst);
|
return new Bits(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.RoundDown.1 */
|
/* shared_pseudocode.html#impl-shared.RoundDown.1 */
|
||||||
public static BigInteger RoundDown(decimal x)
|
public static BigInteger RoundDown(decimal x)
|
||||||
{
|
{
|
||||||
return (BigInteger)Decimal.Floor(x);
|
return (BigInteger)Decimal.Floor(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.RoundTowardsZero.1
|
// shared_pseudocode.html#impl-shared.RoundTowardsZero.1
|
||||||
public static BigInteger RoundTowardsZero(decimal x)
|
public static BigInteger RoundTowardsZero(decimal x)
|
||||||
{
|
{
|
||||||
if (x == 0.0m)
|
if (x == 0.0m)
|
||||||
|
@ -871,13 +880,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.RoundUp.1 */
|
/* shared_pseudocode.html#impl-shared.RoundUp.1 */
|
||||||
public static BigInteger RoundUp(decimal x)
|
public static BigInteger RoundUp(decimal x)
|
||||||
{
|
{
|
||||||
return (BigInteger)Decimal.Ceiling(x);
|
return (BigInteger)Decimal.Ceiling(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.SInt.1
|
// shared_pseudocode.html#impl-shared.SInt.1
|
||||||
public static BigInteger SInt(Bits x)
|
public static BigInteger SInt(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -900,7 +909,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.SignExtend.2
|
// shared_pseudocode.html#impl-shared.SignExtend.2
|
||||||
public static Bits SignExtend(Bits x, int N)
|
public static Bits SignExtend(Bits x, int N)
|
||||||
{
|
{
|
||||||
int M = x.Count;
|
int M = x.Count;
|
||||||
|
@ -910,13 +919,13 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return Bits.Concat(Replicate(x[M - 1], N - M), x);
|
return Bits.Concat(Replicate(x[M - 1], N - M), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.SignExtend.1 */
|
/* shared_pseudocode.html#impl-shared.SignExtend.1 */
|
||||||
public static Bits SignExtend(int N, Bits x)
|
public static Bits SignExtend(int N, Bits x)
|
||||||
{
|
{
|
||||||
return SignExtend(x, N);
|
return SignExtend(x, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.UInt.1
|
// shared_pseudocode.html#impl-shared.UInt.1
|
||||||
public static BigInteger UInt(Bits x)
|
public static BigInteger UInt(Bits x)
|
||||||
{
|
{
|
||||||
int N = x.Count;
|
int N = x.Count;
|
||||||
|
@ -934,7 +943,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.ZeroExtend.2
|
// shared_pseudocode.html#impl-shared.ZeroExtend.2
|
||||||
public static Bits ZeroExtend(Bits x, int N)
|
public static Bits ZeroExtend(Bits x, int N)
|
||||||
{
|
{
|
||||||
int M = x.Count;
|
int M = x.Count;
|
||||||
|
@ -944,14 +953,14 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return Bits.Concat(Zeros(N - M), x);
|
return Bits.Concat(Zeros(N - M), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #impl-shared.ZeroExtend.1 */
|
/* shared_pseudocode.html#impl-shared.ZeroExtend.1 */
|
||||||
public static Bits ZeroExtend(int N, Bits x)
|
public static Bits ZeroExtend(int N, Bits x)
|
||||||
{
|
{
|
||||||
return ZeroExtend(x, N);
|
return ZeroExtend(x, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Zeros.1
|
// shared_pseudocode.html#impl-shared.Zeros.1
|
||||||
/* #impl-shared.Zeros.0 */
|
/* shared_pseudocode.html#impl-shared.Zeros.0 */
|
||||||
public static Bits Zeros(int N)
|
public static Bits Zeros(int N)
|
||||||
{
|
{
|
||||||
return Replicate(false, N);
|
return Replicate(false, N);
|
||||||
|
@ -959,7 +968,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "functions/crc/"
|
#region "functions/crc/"
|
||||||
// #impl-shared.BitReverse.1
|
// shared_pseudocode.html#impl-shared.BitReverse.1
|
||||||
public static Bits BitReverse(Bits data)
|
public static Bits BitReverse(Bits data)
|
||||||
{
|
{
|
||||||
int N = data.Count;
|
int N = data.Count;
|
||||||
|
@ -974,7 +983,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.Poly32Mod2.2
|
// shared_pseudocode.html#impl-shared.Poly32Mod2.2
|
||||||
public static Bits Poly32Mod2(Bits _data, Bits poly)
|
public static Bits Poly32Mod2(Bits _data, Bits poly)
|
||||||
{
|
{
|
||||||
int N = _data.Count;
|
int N = _data.Count;
|
||||||
|
@ -996,7 +1005,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "functions/integer/"
|
#region "functions/integer/"
|
||||||
/* #impl-shared.AddWithCarry.3 */
|
/* shared_pseudocode.html#impl-shared.AddWithCarry.3 */
|
||||||
public static (Bits, Bits) AddWithCarry(int N, Bits x, Bits y, bool carry_in)
|
public static (Bits, Bits) AddWithCarry(int N, Bits x, Bits y, bool carry_in)
|
||||||
{
|
{
|
||||||
BigInteger unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
|
BigInteger unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
|
||||||
|
@ -1021,11 +1030,11 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
public static Bits SP_EL0;
|
public static Bits SP_EL0;
|
||||||
public static Bits SP_EL1;
|
public static Bits SP_EL1;
|
||||||
|
|
||||||
public static Bits FPSR; // FIXME: Temporary solution.
|
public static Bits FPSR; // TODO: Add named fields.
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "functions/system/"
|
#region "functions/system/"
|
||||||
// #impl-shared.ConditionHolds.1
|
// shared_pseudocode.html#impl-shared.ConditionHolds.1
|
||||||
public static bool ConditionHolds(Bits cond)
|
public static bool ConditionHolds(Bits cond)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
|
@ -1070,16 +1079,16 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #EL3
|
// shared_pseudocode.html#EL3
|
||||||
public static readonly Bits EL3 = "11";
|
public static readonly Bits EL3 = "11";
|
||||||
// #EL2
|
// shared_pseudocode.html#EL2
|
||||||
public static readonly Bits EL2 = "10";
|
public static readonly Bits EL2 = "10";
|
||||||
// #EL1
|
// shared_pseudocode.html#EL1
|
||||||
public static readonly Bits EL1 = "01";
|
public static readonly Bits EL1 = "01";
|
||||||
// #EL0
|
// shared_pseudocode.html#EL0
|
||||||
public static readonly Bits EL0 = "00";
|
public static readonly Bits EL0 = "00";
|
||||||
|
|
||||||
/* #impl-shared.HaveEL.1 */
|
/* shared_pseudocode.html#impl-shared.HaveEL.1 */
|
||||||
public static bool HaveEL(Bits el)
|
public static bool HaveEL(Bits el)
|
||||||
{
|
{
|
||||||
if (el == EL1 || el == EL0)
|
if (el == EL1 || el == EL0)
|
||||||
|
@ -1093,7 +1102,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
|
|
||||||
public static ProcState PSTATE;
|
public static ProcState PSTATE;
|
||||||
|
|
||||||
/* #ProcState */
|
/* shared_pseudocode.html#ProcState */
|
||||||
internal struct ProcState
|
internal struct ProcState
|
||||||
{
|
{
|
||||||
public void NZCV(Bits nzcv) // ASL: ".<,,,>".
|
public void NZCV(Bits nzcv) // ASL: ".<,,,>".
|
||||||
|
@ -1122,7 +1131,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "functions/vector/"
|
#region "functions/vector/"
|
||||||
// #impl-shared.SatQ.3
|
// shared_pseudocode.html#impl-shared.SatQ.3
|
||||||
public static (Bits, bool) SatQ(BigInteger i, int N, bool unsigned)
|
public static (Bits, bool) SatQ(BigInteger i, int N, bool unsigned)
|
||||||
{
|
{
|
||||||
(Bits result, bool sat) = (unsigned ? UnsignedSatQ(i, N) : SignedSatQ(i, N));
|
(Bits result, bool sat) = (unsigned ? UnsignedSatQ(i, N) : SignedSatQ(i, N));
|
||||||
|
@ -1130,7 +1139,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (result, sat);
|
return (result, sat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.SignedSatQ.2
|
// shared_pseudocode.html#impl-shared.SignedSatQ.2
|
||||||
public static (Bits, bool) SignedSatQ(BigInteger i, int N)
|
public static (Bits, bool) SignedSatQ(BigInteger i, int N)
|
||||||
{
|
{
|
||||||
BigInteger result;
|
BigInteger result;
|
||||||
|
@ -1155,7 +1164,7 @@ namespace Ryujinx.Tests.Cpu.Tester
|
||||||
return (result.SubBigInteger(N - 1, 0), saturated);
|
return (result.SubBigInteger(N - 1, 0), saturated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #impl-shared.UnsignedSatQ.2
|
// shared_pseudocode.html#impl-shared.UnsignedSatQ.2
|
||||||
public static (Bits, bool) UnsignedSatQ(BigInteger i, int N)
|
public static (Bits, bool) UnsignedSatQ(BigInteger i, int N)
|
||||||
{
|
{
|
||||||
BigInteger result;
|
BigInteger result;
|
||||||
|
|
Loading…
Reference in a new issue