From 16869402bf81716ba3d1410621a3b1847bee389c Mon Sep 17 00:00:00 2001 From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Date: Fri, 4 Oct 2019 16:43:20 +0200 Subject: [PATCH] Add Tbx Inst. (fast & slow paths), with Tests. (#782) * Update OpCodeTable.cs * Update InstName.cs * Update InstEmitSimdMove.cs * Update SoftFallback.cs * Update DelegateTypes.cs * Update CpuTestSimdTbl.cs * Update CpuTest.cs * Update Ryujinx.Tests.csproj * Nit. --- ARMeilleure/Decoders/OpCodeTable.cs | 1 + ARMeilleure/Instructions/DelegateTypes.cs | 12 +- ARMeilleure/Instructions/InstEmitSimdMove.cs | 190 ++++++++++++------- ARMeilleure/Instructions/InstName.cs | 3 +- ARMeilleure/Instructions/SoftFallback.cs | 42 ++-- Ryujinx.Tests/Cpu/CpuTest.cs | 32 ++-- Ryujinx.Tests/Cpu/CpuTestSimdTbl.cs | 163 ++++++++-------- Ryujinx.Tests/Ryujinx.Tests.csproj | 4 +- 8 files changed, 255 insertions(+), 192 deletions(-) diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 22c762d623..55cd5cb610 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -518,6 +518,7 @@ namespace ARMeilleure.Decoders SetA64("01011110xx100000001110xxxxxxxxxx", InstName.Suqadd_S, InstEmit.Suqadd_S, typeof(OpCodeSimd)); SetA64("0>001110<<100000001110xxxxxxxxxx", InstName.Suqadd_V, InstEmit.Suqadd_V, typeof(OpCodeSimd)); SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", InstName.Tbl_V, InstEmit.Tbl_V, typeof(OpCodeSimdTbl)); + SetA64("0x001110000xxxxx0xx100xxxxxxxxxx", InstName.Tbx_V, InstEmit.Tbx_V, typeof(OpCodeSimdTbl)); SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", InstName.Trn1_V, InstEmit.Trn1_V, typeof(OpCodeSimdReg)); SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", InstName.Trn2_V, InstEmit.Trn2_V, typeof(OpCodeSimdReg)); SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", InstName.Uaba_V, InstEmit.Uaba_V, typeof(OpCodeSimdReg)); diff --git a/ARMeilleure/Instructions/DelegateTypes.cs b/ARMeilleure/Instructions/DelegateTypes.cs index e90e4d77a1..424203ffae 100644 --- a/ARMeilleure/Instructions/DelegateTypes.cs +++ b/ARMeilleure/Instructions/DelegateTypes.cs @@ -61,11 +61,17 @@ namespace ARMeilleure.Instructions delegate V128 _V128_U64(ulong a1); delegate V128 _V128_V128(V128 a1); + delegate V128 _V128_V128_S32_V128(V128 a1, int a2, V128 a3); + delegate V128 _V128_V128_S32_V128_V128(V128 a1, int a2, V128 a3, V128 a4); + delegate V128 _V128_V128_S32_V128_V128_V128(V128 a1, int a2, V128 a3, V128 a4, V128 a5); + delegate V128 _V128_V128_S32_V128_V128_V128_V128(V128 a1, int a2, V128 a3, V128 a4, V128 a5, V128 a6); delegate V128 _V128_V128_U32_V128(V128 a1, uint a2, V128 a3); delegate V128 _V128_V128_V128(V128 a1, V128 a2); + delegate V128 _V128_V128_V128_S32_V128(V128 a1, V128 a2, int a3, V128 a4); + delegate V128 _V128_V128_V128_S32_V128_V128(V128 a1, V128 a2, int a3, V128 a4, V128 a5); + delegate V128 _V128_V128_V128_S32_V128_V128_V128(V128 a1, V128 a2, int a3, V128 a4, V128 a5, V128 a6); + delegate V128 _V128_V128_V128_S32_V128_V128_V128_V128(V128 a1, V128 a2, int a3, V128 a4, V128 a5, V128 a6, V128 a7); delegate V128 _V128_V128_V128_V128(V128 a1, V128 a2, V128 a3); - delegate V128 _V128_V128_V128_V128_V128(V128 a1, V128 a2, V128 a3, V128 a4); - delegate V128 _V128_V128_V128_V128_V128_V128(V128 a1, V128 a2, V128 a3, V128 a4, V128 a5); delegate void _Void(); delegate void _Void_U64(ulong a1); @@ -75,4 +81,4 @@ namespace ARMeilleure.Instructions delegate void _Void_U64_U64(ulong a1, ulong a2); delegate void _Void_U64_U8(ulong a1, byte a2); delegate void _Void_U64_V128(ulong a1, V128 a2); -} \ No newline at end of file +} diff --git a/ARMeilleure/Instructions/InstEmitSimdMove.cs b/ARMeilleure/Instructions/InstEmitSimdMove.cs index 47359161fb..9d2aeb3bde 100644 --- a/ARMeilleure/Instructions/InstEmitSimdMove.cs +++ b/ARMeilleure/Instructions/InstEmitSimdMove.cs @@ -2,6 +2,7 @@ using ARMeilleure.Decoders; using ARMeilleure.IntermediateRepresentation; using ARMeilleure.Translation; using System; +using System.Collections.Generic; using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper; @@ -384,79 +385,12 @@ namespace ARMeilleure.Instructions public static void Tbl_V(ArmEmitterContext context) { - OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp; + EmitTableVectorLookup(context, isTbl: true); + } - if (Optimizations.UseSsse3) - { - Operand n = GetVec(op.Rn); - Operand m = GetVec(op.Rm); - - Operand mask = X86GetAllElements(context, 0x0F0F0F0F0F0F0F0FL); - - Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, mask); - - mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, m); - - Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mMask); - - for (int index = 1; index < op.Size; index++) - { - Operand ni = GetVec((op.Rn + index) & 0x1f); - - Operand indexMask = X86GetAllElements(context, 0x1010101010101010L * index); - - Operand mMinusMask = context.AddIntrinsic(Intrinsic.X86Psubb, m, indexMask); - - Operand mMask2 = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, mMinusMask, mask); - - mMask2 = context.AddIntrinsic(Intrinsic.X86Por, mMask2, mMinusMask); - - Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, ni, mMask2); - - res = context.AddIntrinsic(Intrinsic.X86Por, res, res2); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - res = context.VectorZeroUpper64(res); - } - - context.Copy(GetVec(op.Rd), res); - } - else - { - Operand[] args = new Operand[1 + op.Size]; - - args[0] = GetVec(op.Rm); - - for (int index = 0; index < op.Size; index++) - { - args[1 + index] = GetVec((op.Rn + index) & 0x1f); - } - - Delegate dlg = null; - - switch (op.Size) - { - case 1: dlg = op.RegisterSize == RegisterSize.Simd64 - ? (Delegate)new _V128_V128_V128(SoftFallback.Tbl1_V64) - : (Delegate)new _V128_V128_V128(SoftFallback.Tbl1_V128); break; - - case 2: dlg = op.RegisterSize == RegisterSize.Simd64 - ? (Delegate)new _V128_V128_V128_V128(SoftFallback.Tbl2_V64) - : (Delegate)new _V128_V128_V128_V128(SoftFallback.Tbl2_V128); break; - - case 3: dlg = op.RegisterSize == RegisterSize.Simd64 - ? (Delegate)new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V64) - : (Delegate)new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V128); break; - - case 4: dlg = op.RegisterSize == RegisterSize.Simd64 - ? (Delegate)new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V64) - : (Delegate)new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V128); break; - } - - context.Copy(GetVec(op.Rd), context.Call(dlg, args)); - } + public static void Tbx_V(ArmEmitterContext context) + { + EmitTableVectorLookup(context, isTbl: false); } public static void Trn1_V(ArmEmitterContext context) @@ -577,6 +511,116 @@ namespace ARMeilleure.Instructions context.Copy(GetVec(op.Rd), mask); } + private static void EmitTableVectorLookup(ArmEmitterContext context, bool isTbl) + { + OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp; + + if (Optimizations.UseSsse3) + { + Operand d = GetVec(op.Rd); + Operand m = GetVec(op.Rm); + + Operand res; + + Operand mask = X86GetAllElements(context, 0x0F0F0F0F0F0F0F0FL); + + // Fast path for single register table. + { + Operand n = GetVec(op.Rn); + + Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, mask); + mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, m); + + res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mMask); + } + + for (int index = 1; index < op.Size; index++) + { + Operand ni = GetVec((op.Rn + index) & 0x1F); + + Operand idxMask = X86GetAllElements(context, 0x1010101010101010L * index); + + Operand mSubMask = context.AddIntrinsic(Intrinsic.X86Psubb, m, idxMask); + + Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, mSubMask, mask); + mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, mSubMask); + + Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, ni, mMask); + + res = context.AddIntrinsic(Intrinsic.X86Por, res, res2); + } + + if (!isTbl) + { + Operand idxMask = X86GetAllElements(context, (0x1010101010101010L * op.Size) - 0x0101010101010101L); + Operand zeroMask = context.VectorZero(); + + Operand mPosMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, idxMask); + Operand mNegMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, zeroMask, m); + + Operand mMask = context.AddIntrinsic(Intrinsic.X86Por, mPosMask, mNegMask); + + Operand dMask = context.AddIntrinsic(Intrinsic.X86Pand, d, mMask); + + res = context.AddIntrinsic(Intrinsic.X86Por, res, dMask); + } + + if (op.RegisterSize == RegisterSize.Simd64) + { + res = context.VectorZeroUpper64(res); + } + + context.Copy(d, res); + } + else + { + Operand d = GetVec(op.Rd); + + List args = new List(); + + if (!isTbl) + { + args.Add(d); + } + + args.Add(GetVec(op.Rm)); + + args.Add(Const(op.RegisterSize == RegisterSize.Simd64 ? 8 : 16)); + + for (int index = 0; index < op.Size; index++) + { + args.Add(GetVec((op.Rn + index) & 0x1F)); + } + + Delegate dlg = null; + + switch (op.Size) + { + case 1: dlg = isTbl + ? (Delegate)new _V128_V128_S32_V128 (SoftFallback.Tbl1) + : (Delegate)new _V128_V128_V128_S32_V128(SoftFallback.Tbx1); + break; + + case 2: dlg = isTbl + ? (Delegate)new _V128_V128_S32_V128_V128 (SoftFallback.Tbl2) + : (Delegate)new _V128_V128_V128_S32_V128_V128(SoftFallback.Tbx2); + break; + + case 3: dlg = isTbl + ? (Delegate)new _V128_V128_S32_V128_V128_V128 (SoftFallback.Tbl3) + : (Delegate)new _V128_V128_V128_S32_V128_V128_V128(SoftFallback.Tbx3); + break; + + case 4: dlg = isTbl + ? (Delegate)new _V128_V128_S32_V128_V128_V128_V128 (SoftFallback.Tbl4) + : (Delegate)new _V128_V128_V128_S32_V128_V128_V128_V128(SoftFallback.Tbx4); + break; + } + + context.Copy(d, context.Call(dlg, args.ToArray())); + } + } + private static void EmitVectorTranspose(ArmEmitterContext context, int part) { OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; @@ -791,4 +835,4 @@ namespace ARMeilleure.Instructions } } } -} \ No newline at end of file +} diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index e70ca34bcd..e03ab6166a 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -375,6 +375,7 @@ namespace ARMeilleure.Instructions Suqadd_S, Suqadd_V, Tbl_V, + Tbx_V, Trn1_V, Trn2_V, Uaba_V, @@ -456,4 +457,4 @@ namespace ARMeilleure.Instructions Strd, Strh } -} \ No newline at end of file +} diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs index dc0309218b..8d48c34f66 100644 --- a/ARMeilleure/Instructions/SoftFallback.cs +++ b/ARMeilleure/Instructions/SoftFallback.cs @@ -837,49 +837,55 @@ namespace ARMeilleure.Instructions #endregion #region "Table" - public static V128 Tbl1_V64(V128 vector, V128 tb0) + public static V128 Tbl1(V128 vector, int bytes, V128 tb0) { - return Tbl(vector, 8, tb0); + return TblOrTbx(default, vector, bytes, tb0); } - public static V128 Tbl1_V128(V128 vector, V128 tb0) + public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1) { - return Tbl(vector, 16, tb0); + return TblOrTbx(default, vector, bytes, tb0, tb1); } - public static V128 Tbl2_V64(V128 vector, V128 tb0, V128 tb1) + public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2) { - return Tbl(vector, 8, tb0, tb1); + return TblOrTbx(default, vector, bytes, tb0, tb1, tb2); } - public static V128 Tbl2_V128(V128 vector, V128 tb0, V128 tb1) + public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3) { - return Tbl(vector, 16, tb0, tb1); + return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3); } - public static V128 Tbl3_V64(V128 vector, V128 tb0, V128 tb1, V128 tb2) + public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0) { - return Tbl(vector, 8, tb0, tb1, tb2); + return TblOrTbx(dest, vector, bytes, tb0); } - public static V128 Tbl3_V128(V128 vector, V128 tb0, V128 tb1, V128 tb2) + public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1) { - return Tbl(vector, 16, tb0, tb1, tb2); + return TblOrTbx(dest, vector, bytes, tb0, tb1); } - public static V128 Tbl4_V64(V128 vector, V128 tb0, V128 tb1, V128 tb2, V128 tb3) + public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2) { - return Tbl(vector, 8, tb0, tb1, tb2, tb3); + return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2); } - public static V128 Tbl4_V128(V128 vector, V128 tb0, V128 tb1, V128 tb2, V128 tb3) + public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3) { - return Tbl(vector, 16, tb0, tb1, tb2, tb3); + return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3); } - private static V128 Tbl(V128 vector, int bytes, params V128[] tb) + private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params V128[] tb) { - byte[] res = new byte[16]; + byte[] res = new byte[16]; + + if (dest != default) + { + Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes); + } + byte[] table = new byte[tb.Length * 16]; for (byte index = 0; index < tb.Length; index++) diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index 1e7b75c616..4b7b0f6ba9 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -99,14 +99,14 @@ namespace Ryujinx.Tests.Cpu ulong x2 = 0, ulong x3 = 0, ulong x31 = 0, - V128 v0 = default(V128), - V128 v1 = default(V128), - V128 v2 = default(V128), - V128 v3 = default(V128), - V128 v4 = default(V128), - V128 v5 = default(V128), - V128 v30 = default(V128), - V128 v31 = default(V128), + V128 v0 = default, + V128 v1 = default, + V128 v2 = default, + V128 v3 = default, + V128 v4 = default, + V128 v5 = default, + V128 v30 = default, + V128 v31 = default, bool overflow = false, bool carry = false, bool zero = false, @@ -182,14 +182,14 @@ namespace Ryujinx.Tests.Cpu ulong x2 = 0, ulong x3 = 0, ulong x31 = 0, - V128 v0 = default(V128), - V128 v1 = default(V128), - V128 v2 = default(V128), - V128 v3 = default(V128), - V128 v4 = default(V128), - V128 v5 = default(V128), - V128 v30 = default(V128), - V128 v31 = default(V128), + V128 v0 = default, + V128 v1 = default, + V128 v2 = default, + V128 v3 = default, + V128 v4 = default, + V128 v5 = default, + V128 v30 = default, + V128 v31 = default, bool overflow = false, bool carry = false, bool zero = false, diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdTbl.cs b/Ryujinx.Tests/Cpu/CpuTestSimdTbl.cs index 5e6546abac..0daeab618b 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdTbl.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdTbl.cs @@ -98,55 +98,60 @@ namespace Ryujinx.Tests.Cpu #endregion #region "ValueSource (Opcodes)" - private static uint[] _SingleRegTbl_V_8B_16B_() + private static uint[] _SingleRegisterTable_V_8B_16B_() { return new uint[] { 0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B + 0x0E001000u // TBX V0.8B, { V0.16B }, V0.8B }; } - private static uint[] _TwoRegTbl_V_8B_16B_() + private static uint[] _TwoRegisterTable_V_8B_16B_() { return new uint[] { 0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B + 0x0E003000u // TBX V0.8B, { V0.16B, V1.16B }, V0.8B }; } - private static uint[] _ThreeRegTbl_V_8B_16B_() + private static uint[] _ThreeRegisterTable_V_8B_16B_() { return new uint[] { 0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B + 0x0E005000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B }; } - private static uint[] _FourRegTbl_V_8B_16B_() + private static uint[] _FourRegisterTable_V_8B_16B_() { return new uint[] { 0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B + 0x0E006000u // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B }; } #endregion + private const int RndCntDest = 2; private const int RndCntTbls = 2; private const int RndCntIdxs = 2; - [Test, Pairwise, Description("TBL ., { .16B }, .")] - public void SingleRegTbl_V_8B_16B([ValueSource("_SingleRegTbl_V_8B_16B_")] uint opcodes, - [Values(0u)] uint rd, - [Values(1u)] uint rn, - [Values(2u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_GenIdxsForTbl1_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void SingleRegisterTable_V_8B_16B([ValueSource("_SingleRegisterTable_V_8B_16B_")] uint opcodes, + [Values(0u)] uint rd, + [Values(1u)] uint rn, + [Values(2u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_GenIdxsForTbl1_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v0 = MakeVectorE0E1(z, z); V128 v1 = MakeVectorE0E1(table0, table0); V128 v2 = MakeVectorE0E1(indexes, q == 1u ? indexes : 0ul); @@ -156,20 +161,20 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("TBL ., { .16B, .16B }, .")] - public void TwoRegTbl_V_8B_16B([ValueSource("_TwoRegTbl_V_8B_16B_")] uint opcodes, - [Values(0u)] uint rd, - [Values(1u)] uint rn, - [Values(3u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, - [ValueSource("_GenIdxsForTbl2_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void TwoRegisterTable_V_8B_16B([ValueSource("_TwoRegisterTable_V_8B_16B_")] uint opcodes, + [Values(0u)] uint rd, + [Values(1u)] uint rn, + [Values(3u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, + [ValueSource("_GenIdxsForTbl2_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v0 = MakeVectorE0E1(z, z); V128 v1 = MakeVectorE0E1(table0, table0); V128 v2 = MakeVectorE0E1(table1, table1); @@ -180,20 +185,20 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("TBL ., { .16B, .16B }, .")] - public void Mod_TwoRegTbl_V_8B_16B([ValueSource("_TwoRegTbl_V_8B_16B_")] uint opcodes, - [Values(30u, 1u)] uint rd, - [Values(31u)] uint rn, - [Values(1u, 30u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, - [ValueSource("_GenIdxsForTbl2_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void Mod_TwoRegisterTable_V_8B_16B([ValueSource("_TwoRegisterTable_V_8B_16B_")] uint opcodes, + [Values(30u, 1u)] uint rd, + [Values(31u)] uint rn, + [Values(1u, 30u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, + [ValueSource("_GenIdxsForTbl2_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v30 = MakeVectorE0E1(z, z); V128 v31 = MakeVectorE0E1(table0, table0); V128 v0 = MakeVectorE0E1(table1, table1); @@ -204,21 +209,21 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("TBL ., { .16B, .16B, .16B }, .")] - public void ThreeRegTbl_V_8B_16B([ValueSource("_ThreeRegTbl_V_8B_16B_")] uint opcodes, - [Values(0u)] uint rd, - [Values(1u)] uint rn, - [Values(4u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, - [ValueSource("_GenIdxsForTbl3_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void ThreeRegisterTable_V_8B_16B([ValueSource("_ThreeRegisterTable_V_8B_16B_")] uint opcodes, + [Values(0u)] uint rd, + [Values(1u)] uint rn, + [Values(4u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, + [ValueSource("_GenIdxsForTbl3_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v0 = MakeVectorE0E1(z, z); V128 v1 = MakeVectorE0E1(table0, table0); V128 v2 = MakeVectorE0E1(table1, table1); @@ -230,21 +235,21 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("TBL ., { .16B, .16B, .16B }, .")] - public void Mod_ThreeRegTbl_V_8B_16B([ValueSource("_ThreeRegTbl_V_8B_16B_")] uint opcodes, - [Values(30u, 2u)] uint rd, - [Values(31u)] uint rn, - [Values(2u, 30u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, - [ValueSource("_GenIdxsForTbl3_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void Mod_ThreeRegisterTable_V_8B_16B([ValueSource("_ThreeRegisterTable_V_8B_16B_")] uint opcodes, + [Values(30u, 2u)] uint rd, + [Values(31u)] uint rn, + [Values(2u, 30u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, + [ValueSource("_GenIdxsForTbl3_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v30 = MakeVectorE0E1(z, z); V128 v31 = MakeVectorE0E1(table0, table0); V128 v0 = MakeVectorE0E1(table1, table1); @@ -256,22 +261,22 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("TBL ., { .16B, .16B, .16B, .16B }, .")] - public void FourRegTbl_V_8B_16B([ValueSource("_FourRegTbl_V_8B_16B_")] uint opcodes, - [Values(0u)] uint rd, - [Values(1u)] uint rn, - [Values(5u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table3, - [ValueSource("_GenIdxsForTbl4_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void FourRegisterTable_V_8B_16B([ValueSource("_FourRegisterTable_V_8B_16B_")] uint opcodes, + [Values(0u)] uint rd, + [Values(1u)] uint rn, + [Values(5u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table3, + [ValueSource("_GenIdxsForTbl4_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v0 = MakeVectorE0E1(z, z); V128 v1 = MakeVectorE0E1(table0, table0); V128 v2 = MakeVectorE0E1(table1, table1); @@ -284,22 +289,22 @@ namespace Ryujinx.Tests.Cpu CompareAgainstUnicorn(); } - [Test, Pairwise, Description("TBL ., { .16B, .16B, .16B, .16B }, .")] - public void Mod_FourRegTbl_V_8B_16B([ValueSource("_FourRegTbl_V_8B_16B_")] uint opcodes, - [Values(30u, 3u)] uint rd, - [Values(31u)] uint rn, - [Values(3u, 30u)] uint rm, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, - [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table3, - [ValueSource("_GenIdxsForTbl4_")] ulong indexes, - [Values(0b0u, 0b1u)] uint q) // <8B, 16B> + [Test, Pairwise] + public void Mod_FourRegisterTable_V_8B_16B([ValueSource("_FourRegisterTable_V_8B_16B_")] uint opcodes, + [Values(30u, 3u)] uint rd, + [Values(31u)] uint rn, + [Values(3u, 30u)] uint rm, + [ValueSource("_8B_")] [Random(RndCntDest)] ulong z, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table0, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table1, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table2, + [ValueSource("_8B_")] [Random(RndCntTbls)] ulong table3, + [ValueSource("_GenIdxsForTbl4_")] ulong indexes, + [Values(0b0u, 0b1u)] uint q) // <8B, 16B> { opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0); opcodes |= ((q & 1) << 30); - ulong z = TestContext.CurrentContext.Random.NextULong(); V128 v30 = MakeVectorE0E1(z, z); V128 v31 = MakeVectorE0E1(table0, table0); V128 v0 = MakeVectorE0E1(table1, table1); diff --git a/Ryujinx.Tests/Ryujinx.Tests.csproj b/Ryujinx.Tests/Ryujinx.Tests.csproj index 0ebc819606..9608422e52 100644 --- a/Ryujinx.Tests/Ryujinx.Tests.csproj +++ b/Ryujinx.Tests/Ryujinx.Tests.csproj @@ -27,9 +27,9 @@ - + - +