Merge branch 'master' into a32-smlaw-smulw

This commit is contained in:
jduncanator 2020-03-01 16:27:40 +11:00 committed by GitHub
commit 3fb42fd402
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 377 additions and 39 deletions

View file

@ -4,7 +4,7 @@ namespace ARMeilleure.Decoders
{
struct InstDescriptor
{
public static InstDescriptor Undefined => new InstDescriptor(InstName.Und, null);
public static InstDescriptor Undefined => new InstDescriptor(InstName.Und, InstEmit.Und);
public InstName Name { get; }
public InstEmitter Emitter { get; }

View file

@ -0,0 +1,22 @@
namespace ARMeilleure.Decoders
{
class OpCode32Sat : OpCode32
{
public int Rn { get; private set; }
public int Imm5 { get; private set; }
public int Rd { get; private set; }
public int SatImm { get; private set; }
public ShiftType ShiftType { get; private set; }
public OpCode32Sat(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rn = (opCode >> 0) & 0xf;
Imm5 = (opCode >> 7) & 0x1f;
Rd = (opCode >> 12) & 0xf;
SatImm = (opCode >> 16) & 0x1f;
ShiftType = (ShiftType)((opCode >> 5) & 2);
}
}
}

View file

@ -0,0 +1,16 @@
namespace ARMeilleure.Decoders
{
class OpCode32Sat16 : OpCode32
{
public int Rn { get; private set; }
public int Rd { get; private set; }
public int SatImm { get; private set; }
public OpCode32Sat16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rn = (opCode >> 0) & 0xf;
Rd = (opCode >> 12) & 0xf;
SatImm = (opCode >> 16) & 0xf;
}
}
}

View file

@ -244,6 +244,10 @@ namespace ARMeilleure.Decoders
SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstName.Fabd_V, InstEmit.Fabd_V, typeof(OpCodeSimdReg));
SetA64("000111100x100000110000xxxxxxxxxx", InstName.Fabs_S, InstEmit.Fabs_S, typeof(OpCodeSimd));
SetA64("0>0011101<100000111110xxxxxxxxxx", InstName.Fabs_V, InstEmit.Fabs_V, typeof(OpCodeSimd));
SetA64("011111100x1xxxxx111011xxxxxxxxxx", InstName.Facge_S, InstEmit.Facge_S, typeof(OpCodeSimdReg));
SetA64("0>1011100<1xxxxx111011xxxxxxxxxx", InstName.Facge_V, InstEmit.Facge_V, typeof(OpCodeSimdReg));
SetA64("011111101x1xxxxx111011xxxxxxxxxx", InstName.Facgt_S, InstEmit.Facgt_S, typeof(OpCodeSimdReg));
SetA64("0>1011101<1xxxxx111011xxxxxxxxxx", InstName.Facgt_V, InstEmit.Facgt_V, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstName.Fadd_S, InstEmit.Fadd_S, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstName.Fadd_V, InstEmit.Fadd_V, typeof(OpCodeSimdReg));
SetA64("011111100x110000110110xxxxxxxxxx", InstName.Faddp_S, InstEmit.Faddp_S, typeof(OpCodeSimd));
@ -701,6 +705,8 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smul__, InstEmit32.Smul__, typeof(OpCode32AluMla));
SetA32("<<<<0000110xxxxxxxxxxxxx1001xxxx", InstName.Smull, InstEmit32.Smull, typeof(OpCode32AluUmull));
SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_, InstEmit32.Smulw_, typeof(OpCode32AluMla));
SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat, InstEmit32.Ssat, typeof(OpCode32Sat));
SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16, InstEmit32.Ssat16, typeof(OpCode32Sat16));
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx));
@ -739,6 +745,8 @@ namespace ARMeilleure.Decoders
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull));
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, typeof(OpCode32Sat));
SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, typeof(OpCode32Sat16));
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, typeof(OpCode32AluUx));
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));

View file

@ -389,6 +389,20 @@ namespace ARMeilleure.Instructions
EmitDiv(context, false);
}
public static void Ssat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
EmitSat(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
}
public static void Ssat16(ArmEmitterContext context)
{
OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;
EmitSat16(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
}
public static void Sub(ArmEmitterContext context)
{
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
@ -460,6 +474,20 @@ namespace ARMeilleure.Instructions
EmitDiv(context, true);
}
public static void Usat(ArmEmitterContext context)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
EmitSat(context, 0, op.SatImm == 32 ? (int)(~0) : (1 << op.SatImm) - 1);
}
public static void Usat16(ArmEmitterContext context)
{
OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;
EmitSat16(context, 0, (1 << op.SatImm) - 1);
}
public static void Uxtb(ArmEmitterContext context)
{
EmitSignExtend(context, false, 8);
@ -553,7 +581,7 @@ namespace ARMeilleure.Instructions
lowAdd = context.ZeroExtend16(OperandType.I32, n);
highAdd = context.ZeroExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
}
low16 = context.Add(low16, lowAdd);
high16 = context.Add(high16, highAdd);
}
@ -615,9 +643,116 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd);
}
private static void EmitSat(ArmEmitterContext context, int intMin, int intMax)
{
OpCode32Sat op = (OpCode32Sat)context.CurrOp;
Operand n = GetIntA32(context, op.Rn);
int shift = DecodeImmShift(op.ShiftType, op.Imm5);
switch (op.ShiftType)
{
case ShiftType.Lsl:
if (shift == 32)
{
n = Const(0);
}
else
{
n = context.ShiftLeft(n, Const(shift));
}
break;
case ShiftType.Asr:
if (shift == 32)
{
n = context.ShiftRightSI(n, Const(31));
}
else
{
n = context.ShiftRightSI(n, Const(shift));
}
break;
}
Operand lblCheckLtIntMin = Label();
Operand lblNoSat = Label();
Operand lblEnd = Label();
context.BranchIfFalse(lblCheckLtIntMin, context.ICompareGreater(n, Const(intMax)));
SetFlag(context, PState.QFlag, Const(1));
SetIntA32(context, op.Rd, Const(intMax));
context.Branch(lblEnd);
context.MarkLabel(lblCheckLtIntMin);
context.BranchIfFalse(lblNoSat, context.ICompareLess(n, Const(intMin)));
SetFlag(context, PState.QFlag, Const(1));
SetIntA32(context, op.Rd, Const(intMin));
context.Branch(lblEnd);
context.MarkLabel(lblNoSat);
SetIntA32(context, op.Rd, n);
context.MarkLabel(lblEnd);
}
private static void EmitSat16(ArmEmitterContext context, int intMin, int intMax)
{
OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;
void SetD(int part, Operand value)
{
if (part == 0)
{
SetIntA32(context, op.Rd, context.ZeroExtend16(OperandType.I32, value));
}
else
{
SetIntA32(context, op.Rd, context.BitwiseOr(GetIntA32(context, op.Rd), context.ShiftLeft(value, Const(16))));
}
}
Operand n = GetIntA32(context, op.Rn);
Operand nLow = context.SignExtend16(OperandType.I32, n);
Operand nHigh = context.ShiftRightSI(n, Const(16));
for (int part = 0; part < 2; part++)
{
Operand nPart = part == 0 ? nLow : nHigh;
Operand lblCheckLtIntMin = Label();
Operand lblNoSat = Label();
Operand lblEnd = Label();
context.BranchIfFalse(lblCheckLtIntMin, context.ICompareGreater(nPart, Const(intMax)));
SetFlag(context, PState.QFlag, Const(1));
SetD(part, Const(intMax));
context.Branch(lblEnd);
context.MarkLabel(lblCheckLtIntMin);
context.BranchIfFalse(lblNoSat, context.ICompareLess(nPart, Const(intMin)));
SetFlag(context, PState.QFlag, Const(1));
SetD(part, Const(intMin));
context.Branch(lblEnd);
context.MarkLabel(lblNoSat);
SetD(part, nPart);
context.MarkLabel(lblEnd);
}
}
private static void EmitAluStore(ArmEmitterContext context, Operand value)
{
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value);
}
}

View file

@ -297,6 +297,21 @@ namespace ARMeilleure.Instructions
return m;
}
public static int DecodeImmShift(ShiftType shiftType, int shift)
{
if (shift == 0)
{
switch (shiftType)
{
case ShiftType.Lsr: shift = 32; break;
case ShiftType.Asr: shift = 32; break;
case ShiftType.Ror: shift = 1; break;
}
}
return shift;
}
public static Operand GetMShiftedByReg(ArmEmitterContext context, OpCode32AluRsReg op, bool setCarry)
{
Operand m = GetIntA32(context, op.Rm);
@ -328,7 +343,7 @@ namespace ARMeilleure.Instructions
if (expected)
{
context.BranchIfFalse(endLabel, boolValue);
}
}
else
{
context.BranchIfTrue(endLabel, boolValue);
@ -411,7 +426,7 @@ namespace ARMeilleure.Instructions
SetFlag(context, PState.CFlag, cOut);
}, false);
}
return context.ConditionalSelect(shiftLarge, Const(0), result);
}

View file

@ -286,6 +286,54 @@ namespace ARMeilleure.Instructions
EmitCmtstOp(context, scalar: false);
}
public static void Facge_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true, absolute: true);
}
else
{
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: true, absolute: true);
}
}
public static void Facge_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false, absolute: true);
}
else
{
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: false, absolute: true);
}
}
public static void Facgt_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: true, absolute: true);
}
else
{
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: true, absolute: true);
}
}
public static void Facgt_V(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)
{
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: false, absolute: true);
}
else
{
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: false, absolute: true);
}
}
public static void Fccmp_S(ArmEmitterContext context)
{
EmitFccmpOrFccmpe(context, signalNaNs: false);
@ -639,7 +687,8 @@ namespace ARMeilleure.Instructions
ArmEmitterContext context,
_F32_F32_F32 f32,
_F64_F64_F64 f64,
bool scalar)
bool scalar,
bool absolute = false)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -665,6 +714,12 @@ namespace ARMeilleure.Instructions
me = sizeF == 0 ? ConstF(0f) : ConstF(0d);
}
if (absolute)
{
ne = EmitUnaryMathCall(context, MathF.Abs, Math.Abs, ne);
me = EmitUnaryMathCall(context, MathF.Abs, Math.Abs, me);
}
Operand e = EmitSoftFloatCall(context, f32, f64, ne, me);
res = context.VectorInsert(res, e, index);
@ -673,7 +728,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res);
}
private static void EmitSse2CmpOpF(ArmEmitterContext context, CmpCondition cond, bool scalar)
private static void EmitSse2CmpOpF(ArmEmitterContext context, CmpCondition cond, bool scalar, bool absolute = false)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -684,6 +739,14 @@ namespace ARMeilleure.Instructions
if (sizeF == 0)
{
if (absolute)
{
Operand mask = scalar ? X86GetScalar(context, int.MaxValue) : X86GetAllElements(context, int.MaxValue);
n = context.AddIntrinsic(Intrinsic.X86Andps, n, mask);
m = context.AddIntrinsic(Intrinsic.X86Andps, m, mask);
}
Intrinsic inst = scalar ? Intrinsic.X86Cmpss : Intrinsic.X86Cmpps;
Operand res = context.AddIntrinsic(inst, n, m, Const((int)cond));
@ -701,6 +764,14 @@ namespace ARMeilleure.Instructions
}
else /* if (sizeF == 1) */
{
if (absolute)
{
Operand mask = scalar ? X86GetScalar(context, long.MaxValue) : X86GetAllElements(context, long.MaxValue);
n = context.AddIntrinsic(Intrinsic.X86Andpd, n, mask);
m = context.AddIntrinsic(Intrinsic.X86Andpd, m, mask);
}
Intrinsic inst = scalar ? Intrinsic.X86Cmpsd : Intrinsic.X86Cmppd;
Operand res = context.AddIntrinsic(inst, n, m, Const((int)cond));

View file

@ -84,6 +84,8 @@ namespace ARMeilleure.Instructions
Smul__,
Smull,
Smulw_,
Ssat,
Ssat16,
Stlr,
Stlxp,
Stlxr,
@ -153,6 +155,10 @@ namespace ARMeilleure.Instructions
Fabd_V,
Fabs_S,
Fabs_V,
Facge_S,
Facge_V,
Facgt_S,
Facgt_V,
Fadd_S,
Fadd_V,
Faddp_S,
@ -517,6 +523,8 @@ namespace ARMeilleure.Instructions
Ubfx,
Umlal,
Umull,
Usat,
Usat16,
Uxtb,
Uxtb16,
Uxth,

View file

@ -14,19 +14,19 @@ namespace Ryujinx.Graphics.OpenGL
int srcDepth = src.DepthOrLayers;
int srcLevels = src.Levels;
srcWidth = Math.Max(1, srcWidth >> dstLevel);
srcHeight = Math.Max(1, srcHeight >> dstLevel);
if (src.Target == Target.Texture3D)
{
srcDepth = Math.Max(1, srcDepth >> dstLevel);
}
int dstWidth = dst.Width;
int dstHeight = dst.Height;
int dstDepth = dst.DepthOrLayers;
int dstLevels = dst.Levels;
dstWidth = Math.Max(1, dstWidth >> dstLevel);
dstHeight = Math.Max(1, dstHeight >> dstLevel);
if (dst.Target == Target.Texture3D)
{
dstDepth = Math.Max(1, dstDepth >> dstLevel);
}
// When copying from a compressed to a non-compressed format,
// the non-compressed texture will have the size of the texture
// in blocks (not in texels), so we must adjust that size to

View file

@ -11,6 +11,26 @@ namespace Ryujinx.Tests.Cpu
#if Alu32
#region "ValueSource (Opcodes)"
private static uint[] _Ssat_Usat_()
{
return new uint[]
{
0xe6a00010u, // SSAT R0, #1, R0, LSL #0
0xe6a00050u, // SSAT R0, #1, R0, ASR #32
0xe6e00010u, // USAT R0, #0, R0, LSL #0
0xe6e00050u // USAT R0, #0, R0, ASR #32
};
}
private static uint[] _Ssat16_Usat16_()
{
return new uint[]
{
0xe6a00f30u, // SSAT16 R0, #1, R0
0xe6e00f30u, // USAT16 R0, #0, R0
};
}
private static uint[] _Lsr_Lsl_Asr_Ror_()
{
return new uint[]
@ -56,6 +76,41 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise]
public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode,
[Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
[Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint shift,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
{
opcode |= ((rn & 15) << 0) | ((shift & 31) << 7) | ((rd & 15) << 12) | ((sat & 31) << 16);
uint w31 = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, sp: w31);
CompareAgainstUnicorn();
}
[Test, Pairwise]
public void Ssat16_Usat16([ValueSource("_Ssat16_Usat16_")] uint opcode,
[Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn,
[Values(0u, 7u, 8u, 0xfu)] uint sat,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
{
opcode |= ((rn & 15) << 0) | ((rd & 15) << 12) | ((sat & 15) << 16);
uint w31 = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, sp: w31);
CompareAgainstUnicorn();
}
#endif
}
}

View file

@ -259,40 +259,48 @@ namespace Ryujinx.Tests.Cpu
};
}
private static uint[] _F_Cm_EqGeGt_S_S_()
private static uint[] _F_AcCm_EqGeGt_S_S_()
{
return new uint[]
{
0x7E22EC20u, // FACGE S0, S1, S2
0x7EA2EC20u, // FACGT S0, S1, S2
0x5E22E420u, // FCMEQ S0, S1, S2
0x7E22E420u, // FCMGE S0, S1, S2
0x7EA2E420u // FCMGT S0, S1, S2
};
}
private static uint[] _F_Cm_EqGeGt_S_D_()
private static uint[] _F_AcCm_EqGeGt_S_D_()
{
return new uint[]
{
0x7E62EC20u, // FACGE D0, D1, D2
0x7EE2EC20u, // FACGT D0, D1, D2
0x5E62E420u, // FCMEQ D0, D1, D2
0x7E62E420u, // FCMGE D0, D1, D2
0x7EE2E420u // FCMGT D0, D1, D2
};
}
private static uint[] _F_Cm_EqGeGt_V_2S_4S_()
private static uint[] _F_AcCm_EqGeGt_V_2S_4S_()
{
return new uint[]
{
0x2E20EC00u, // FACGE V0.2S, V0.2S, V0.2S
0x2EA0EC00u, // FACGT V0.2S, V0.2S, V0.2S
0x0E20E400u, // FCMEQ V0.2S, V0.2S, V0.2S
0x2E20E400u, // FCMGE V0.2S, V0.2S, V0.2S
0x2EA0E400u // FCMGT V0.2S, V0.2S, V0.2S
};
}
private static uint[] _F_Cm_EqGeGt_V_2D_()
private static uint[] _F_AcCm_EqGeGt_V_2D_()
{
return new uint[]
{
0x6E60EC00u, // FACGE V0.2D, V0.2D, V0.2D
0x6EE0EC00u, // FACGT V0.2D, V0.2D, V0.2D
0x4E60E400u, // FCMEQ V0.2D, V0.2D, V0.2D
0x6E60E400u, // FCMGE V0.2D, V0.2D, V0.2D
0x6EE0E400u // FCMGT V0.2D, V0.2D, V0.2D
@ -1429,9 +1437,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cm_EqGeGt_S_S([ValueSource("_F_Cm_EqGeGt_S_S_")] uint opcodes,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b)
public void F_AcCm_EqGeGt_S_S([ValueSource("_F_AcCm_EqGeGt_S_S_")] uint opcodes,
[ValueSource("_1S_F_")] ulong a,
[ValueSource("_1S_F_")] ulong b)
{
ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z);
@ -1448,9 +1456,9 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cm_EqGeGt_S_D([ValueSource("_F_Cm_EqGeGt_S_D_")] uint opcodes,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b)
public void F_AcCm_EqGeGt_S_D([ValueSource("_F_AcCm_EqGeGt_S_D_")] uint opcodes,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b)
{
ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE1(z);
@ -1467,14 +1475,14 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cm_EqGeGt_V_2S_4S([ValueSource("_F_Cm_EqGeGt_V_2S_4S_")] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_2S_F_")] ulong z,
[ValueSource("_2S_F_")] ulong a,
[ValueSource("_2S_F_")] ulong b,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
public void F_AcCm_EqGeGt_V_2S_4S([ValueSource("_F_AcCm_EqGeGt_V_2S_4S_")] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_2S_F_")] ulong z,
[ValueSource("_2S_F_")] ulong a,
[ValueSource("_2S_F_")] ulong b,
[Values(0b0u, 0b1u)] uint q) // <2S, 4S>
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
opcodes |= ((q & 1) << 30);
@ -1493,13 +1501,13 @@ namespace Ryujinx.Tests.Cpu
}
[Test, Pairwise] [Explicit]
public void F_Cm_EqGeGt_V_2D([ValueSource("_F_Cm_EqGeGt_V_2D_")] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_1D_F_")] ulong z,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b)
public void F_AcCm_EqGeGt_V_2D([ValueSource("_F_AcCm_EqGeGt_V_2D_")] uint opcodes,
[Values(0u)] uint rd,
[Values(1u, 0u)] uint rn,
[Values(2u, 0u)] uint rm,
[ValueSource("_1D_F_")] ulong z,
[ValueSource("_1D_F_")] ulong a,
[ValueSource("_1D_F_")] ulong b)
{
opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);