forked from Mirror/Ryujinx
Add FMaxNmV & FMinNmV Inst.s with Test. (#1279)
Successful unit testing on Windows (debug and release mode).
This commit is contained in:
parent
5795bb1528
commit
83d94b21d0
5 changed files with 71 additions and 0 deletions
|
@ -332,11 +332,13 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg));
|
||||||
|
SetA64("0110111000110000110010xxxxxxxxxx", InstName.Fmaxnmv_V, InstEmit.Fmaxnmv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, typeof(OpCodeSimdReg));
|
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, InstEmit.Fmin_S, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, InstEmit.Fmin_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, typeof(OpCodeSimdReg));
|
||||||
|
SetA64("0110111010110000110010xxxxxxxxxx", InstName.Fminnmv_V, InstEmit.Fminnmv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, typeof(OpCodeSimdReg));
|
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF));
|
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, InstEmit.Fmla_V, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, InstEmit.Fmla_V, typeof(OpCodeSimdReg));
|
||||||
|
|
|
@ -534,6 +534,14 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Fmaxnmv_V(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
|
{
|
||||||
|
return context.Call(new _F32_F32_F32(SoftFloat32.FPMaxNum), op1, op2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static void Fmaxp_V(ArmEmitterContext context)
|
public static void Fmaxp_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||||
|
@ -609,6 +617,14 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Fminnmv_V(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
|
{
|
||||||
|
return context.Call(new _F32_F32_F32(SoftFloat32.FPMinNum), op1, op2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static void Fminp_V(ArmEmitterContext context)
|
public static void Fminp_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||||
|
|
|
@ -1103,6 +1103,26 @@ namespace ARMeilleure.Instructions
|
||||||
context.Copy(GetVec(op.Rd), d);
|
context.Copy(GetVec(op.Rd), d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorAcrossVectorOpF(ArmEmitterContext context, Func2I emit)
|
||||||
|
{
|
||||||
|
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
|
Debug.Assert((op.Size & 1) == 0 && op.RegisterSize == RegisterSize.Simd128);
|
||||||
|
|
||||||
|
Operand res = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
||||||
|
|
||||||
|
for (int index = 1; index < 4; index++)
|
||||||
|
{
|
||||||
|
Operand n = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), index);
|
||||||
|
|
||||||
|
res = emit(res, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand d = context.VectorInsert(context.VectorZero(), res, 0);
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), d);
|
||||||
|
}
|
||||||
|
|
||||||
public static void EmitVectorPairwiseOpF(ArmEmitterContext context, Func2I emit)
|
public static void EmitVectorPairwiseOpF(ArmEmitterContext context, Func2I emit)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||||
|
|
|
@ -212,11 +212,13 @@ namespace ARMeilleure.Instructions
|
||||||
Fmax_V,
|
Fmax_V,
|
||||||
Fmaxnm_S,
|
Fmaxnm_S,
|
||||||
Fmaxnm_V,
|
Fmaxnm_V,
|
||||||
|
Fmaxnmv_V,
|
||||||
Fmaxp_V,
|
Fmaxp_V,
|
||||||
Fmin_S,
|
Fmin_S,
|
||||||
Fmin_V,
|
Fmin_V,
|
||||||
Fminnm_S,
|
Fminnm_S,
|
||||||
Fminnm_V,
|
Fminnm_V,
|
||||||
|
Fminnmv_V,
|
||||||
Fminp_V,
|
Fminp_V,
|
||||||
Fmla_Se,
|
Fmla_Se,
|
||||||
Fmla_V,
|
Fmla_V,
|
||||||
|
|
|
@ -913,6 +913,15 @@ namespace Ryujinx.Tests.Cpu
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static uint[] _F_Max_Min_Nm_V_V_4SS_()
|
||||||
|
{
|
||||||
|
return new uint[]
|
||||||
|
{
|
||||||
|
0x6E30C800u, // FMAXNMV S0, V0.4S
|
||||||
|
0x6EB0C800u // FMINNMV S0, V0.4S
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static uint[] _F_Mov_Ftoi_SW_()
|
private static uint[] _F_Mov_Ftoi_SW_()
|
||||||
{
|
{
|
||||||
return new uint[]
|
return new uint[]
|
||||||
|
@ -2142,6 +2151,28 @@ namespace Ryujinx.Tests.Cpu
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise] [Explicit]
|
||||||
|
public void F_Max_Min_Nm_V_V_4SS([ValueSource("_F_Max_Min_Nm_V_V_4SS_")] uint opcodes,
|
||||||
|
[Values(0u)] uint rd,
|
||||||
|
[Values(1u, 0u)] uint rn,
|
||||||
|
[ValueSource("_2S_F_")] ulong z,
|
||||||
|
[ValueSource("_2S_F_")] ulong a)
|
||||||
|
{
|
||||||
|
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
|
|
||||||
|
V128 v0 = MakeVectorE0E1(z, z);
|
||||||
|
V128 v1 = MakeVectorE0E1(a, a);
|
||||||
|
|
||||||
|
int rnd = (int)TestContext.CurrentContext.Random.NextUInt();
|
||||||
|
|
||||||
|
int fpcr = rnd & (1 << (int)Fpcr.Fz);
|
||||||
|
fpcr |= rnd & (1 << (int)Fpcr.Dn);
|
||||||
|
|
||||||
|
SingleOpcode(opcodes, v0: v0, v1: v1, fpcr: fpcr);
|
||||||
|
|
||||||
|
CompareAgainstUnicorn(fpsrMask: Fpsr.Ioc | Fpsr.Idc);
|
||||||
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise] [Explicit]
|
||||||
public void F_Mov_Ftoi_SW([ValueSource("_F_Mov_Ftoi_SW_")] uint opcodes,
|
public void F_Mov_Ftoi_SW([ValueSource("_F_Mov_Ftoi_SW_")] uint opcodes,
|
||||||
[Values(0u, 31u)] uint rd,
|
[Values(0u, 31u)] uint rd,
|
||||||
|
|
Loading…
Reference in a new issue