forked from Mirror/Ryujinx
Add Smaxv_V, Sminv_V, Umaxv_V, Uminv_V Inst.; add Tests. (#691)
* Update InstEmitSimdHelper.cs * Update InstEmitSimdArithmetic.cs * Update OpCodeTable.cs * Update CpuTestSimd.cs
This commit is contained in:
parent
12badfffb9
commit
51ea6fa583
4 changed files with 118 additions and 35 deletions
|
@ -68,21 +68,7 @@ namespace ChocolArm64.Instructions
|
||||||
|
|
||||||
public static void Addv_V(ILEmitterCtx context)
|
public static void Addv_V(ILEmitterCtx context)
|
||||||
{
|
{
|
||||||
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
|
EmitVectorAcrossVectorOpZx(context, () => context.Emit(OpCodes.Add));
|
||||||
|
|
||||||
int bytes = op.GetBitsCount() >> 3;
|
|
||||||
int elems = bytes >> op.Size;
|
|
||||||
|
|
||||||
EmitVectorExtractZx(context, op.Rn, 0, op.Size);
|
|
||||||
|
|
||||||
for (int index = 1; index < elems; index++)
|
|
||||||
{
|
|
||||||
EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
|
||||||
|
|
||||||
context.Emit(OpCodes.Add);
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitScalarSet(context, op.Rd, op.Size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cls_V(ILEmitterCtx context)
|
public static void Cls_V(ILEmitterCtx context)
|
||||||
|
@ -2388,6 +2374,15 @@ namespace ChocolArm64.Instructions
|
||||||
EmitVectorPairwiseOpSx(context, () => context.EmitCall(mthdInfo));
|
EmitVectorPairwiseOpSx(context, () => context.EmitCall(mthdInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Smaxv_V(ILEmitterCtx context)
|
||||||
|
{
|
||||||
|
Type[] types = new Type[] { typeof(long), typeof(long) };
|
||||||
|
|
||||||
|
MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types);
|
||||||
|
|
||||||
|
EmitVectorAcrossVectorOpSx(context, () => context.EmitCall(mthdInfo));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Smin_V(ILEmitterCtx context)
|
public static void Smin_V(ILEmitterCtx context)
|
||||||
{
|
{
|
||||||
if (Optimizations.UseSse41)
|
if (Optimizations.UseSse41)
|
||||||
|
@ -2429,6 +2424,15 @@ namespace ChocolArm64.Instructions
|
||||||
EmitVectorPairwiseOpSx(context, () => context.EmitCall(mthdInfo));
|
EmitVectorPairwiseOpSx(context, () => context.EmitCall(mthdInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Sminv_V(ILEmitterCtx context)
|
||||||
|
{
|
||||||
|
Type[] types = new Type[] { typeof(long), typeof(long) };
|
||||||
|
|
||||||
|
MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types);
|
||||||
|
|
||||||
|
EmitVectorAcrossVectorOpSx(context, () => context.EmitCall(mthdInfo));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Smlal_V(ILEmitterCtx context)
|
public static void Smlal_V(ILEmitterCtx context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
|
OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
|
||||||
|
@ -3208,6 +3212,15 @@ namespace ChocolArm64.Instructions
|
||||||
EmitVectorPairwiseOpZx(context, () => context.EmitCall(mthdInfo));
|
EmitVectorPairwiseOpZx(context, () => context.EmitCall(mthdInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Umaxv_V(ILEmitterCtx context)
|
||||||
|
{
|
||||||
|
Type[] types = new Type[] { typeof(ulong), typeof(ulong) };
|
||||||
|
|
||||||
|
MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types);
|
||||||
|
|
||||||
|
EmitVectorAcrossVectorOpZx(context, () => context.EmitCall(mthdInfo));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Umin_V(ILEmitterCtx context)
|
public static void Umin_V(ILEmitterCtx context)
|
||||||
{
|
{
|
||||||
if (Optimizations.UseSse41)
|
if (Optimizations.UseSse41)
|
||||||
|
@ -3249,6 +3262,15 @@ namespace ChocolArm64.Instructions
|
||||||
EmitVectorPairwiseOpZx(context, () => context.EmitCall(mthdInfo));
|
EmitVectorPairwiseOpZx(context, () => context.EmitCall(mthdInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Uminv_V(ILEmitterCtx context)
|
||||||
|
{
|
||||||
|
Type[] types = new Type[] { typeof(ulong), typeof(ulong) };
|
||||||
|
|
||||||
|
MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types);
|
||||||
|
|
||||||
|
EmitVectorAcrossVectorOpZx(context, () => context.EmitCall(mthdInfo));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Umlal_V(ILEmitterCtx context)
|
public static void Umlal_V(ILEmitterCtx context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
|
OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
|
||||||
|
|
|
@ -821,6 +821,35 @@ namespace ChocolArm64.Instructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorAcrossVectorOpSx(ILEmitterCtx context, Action emit)
|
||||||
|
{
|
||||||
|
EmitVectorAcrossVectorOp(context, emit, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorAcrossVectorOpZx(ILEmitterCtx context, Action emit)
|
||||||
|
{
|
||||||
|
EmitVectorAcrossVectorOp(context, emit, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorAcrossVectorOp(ILEmitterCtx context, Action emit, bool signed)
|
||||||
|
{
|
||||||
|
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
|
||||||
|
|
||||||
|
int bytes = op.GetBitsCount() >> 3;
|
||||||
|
int elems = bytes >> op.Size;
|
||||||
|
|
||||||
|
EmitVectorExtract(context, op.Rn, 0, op.Size, signed);
|
||||||
|
|
||||||
|
for (int index = 1; index < elems; index++)
|
||||||
|
{
|
||||||
|
EmitVectorExtract(context, op.Rn, index, op.Size, signed);
|
||||||
|
|
||||||
|
emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitScalarSet(context, op.Rd, op.Size);
|
||||||
|
}
|
||||||
|
|
||||||
public static void EmitVectorPairwiseOpF(ILEmitterCtx context, Action emit)
|
public static void EmitVectorPairwiseOpF(ILEmitterCtx context, Action emit)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
|
OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
|
||||||
|
|
|
@ -461,8 +461,12 @@ namespace ChocolArm64
|
||||||
SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", InstEmit.Sli_V, typeof(OpCodeSimdShImm64));
|
SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", InstEmit.Sli_V, typeof(OpCodeSimdShImm64));
|
||||||
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstEmit.Smax_V, typeof(OpCodeSimdReg64));
|
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstEmit.Smax_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstEmit.Smaxp_V, typeof(OpCodeSimdReg64));
|
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstEmit.Smaxp_V, typeof(OpCodeSimdReg64));
|
||||||
|
SetA64("000011100x110000101010xxxxxxxxxx", InstEmit.Smaxv_V, typeof(OpCodeSimd64));
|
||||||
|
SetA64("01001110<<110000101010xxxxxxxxxx", InstEmit.Smaxv_V, typeof(OpCodeSimd64));
|
||||||
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstEmit.Smin_V, typeof(OpCodeSimdReg64));
|
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstEmit.Smin_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstEmit.Sminp_V, typeof(OpCodeSimdReg64));
|
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstEmit.Sminp_V, typeof(OpCodeSimdReg64));
|
||||||
|
SetA64("000011100x110001101010xxxxxxxxxx", InstEmit.Sminv_V, typeof(OpCodeSimd64));
|
||||||
|
SetA64("01001110<<110001101010xxxxxxxxxx", InstEmit.Sminv_V, typeof(OpCodeSimd64));
|
||||||
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstEmit.Smlal_V, typeof(OpCodeSimdReg64));
|
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstEmit.Smlal_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Smlal_Ve, typeof(OpCodeSimdRegElem64));
|
SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Smlal_Ve, typeof(OpCodeSimdRegElem64));
|
||||||
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstEmit.Smlsl_V, typeof(OpCodeSimdReg64));
|
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstEmit.Smlsl_V, typeof(OpCodeSimdReg64));
|
||||||
|
@ -556,8 +560,12 @@ namespace ChocolArm64
|
||||||
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstEmit.Uhsub_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstEmit.Uhsub_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstEmit.Umax_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstEmit.Umax_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstEmit.Umaxp_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstEmit.Umaxp_V, typeof(OpCodeSimdReg64));
|
||||||
|
SetA64("001011100x110000101010xxxxxxxxxx", InstEmit.Umaxv_V, typeof(OpCodeSimd64));
|
||||||
|
SetA64("01101110<<110000101010xxxxxxxxxx", InstEmit.Umaxv_V, typeof(OpCodeSimd64));
|
||||||
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstEmit.Umin_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstEmit.Umin_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstEmit.Uminp_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstEmit.Uminp_V, typeof(OpCodeSimdReg64));
|
||||||
|
SetA64("001011100x110001101010xxxxxxxxxx", InstEmit.Uminv_V, typeof(OpCodeSimd64));
|
||||||
|
SetA64("01101110<<110001101010xxxxxxxxxx", InstEmit.Uminv_V, typeof(OpCodeSimd64));
|
||||||
SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstEmit.Umlal_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstEmit.Umlal_V, typeof(OpCodeSimdReg64));
|
||||||
SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Umlal_Ve, typeof(OpCodeSimdRegElem64));
|
SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Umlal_Ve, typeof(OpCodeSimdRegElem64));
|
||||||
SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstEmit.Umlsl_V, typeof(OpCodeSimdReg64));
|
SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstEmit.Umlsl_V, typeof(OpCodeSimdReg64));
|
||||||
|
|
|
@ -445,6 +445,30 @@ namespace Ryujinx.Tests.Cpu
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "ValueSource (Opcodes)"
|
#region "ValueSource (Opcodes)"
|
||||||
|
private static uint[] _SU_Add_Max_Min_V_V_8BB_4HH_()
|
||||||
|
{
|
||||||
|
return new uint[]
|
||||||
|
{
|
||||||
|
0x0E31B800u, // ADDV B0, V0.8B
|
||||||
|
0x0E30A800u, // SMAXV B0, V0.8B
|
||||||
|
0x0E31A800u, // SMINV B0, V0.8B
|
||||||
|
0x2E30A800u, // UMAXV B0, V0.8B
|
||||||
|
0x2E31A800u // UMINV B0, V0.8B
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint[] _SU_Add_Max_Min_V_V_16BB_8HH_4SS_()
|
||||||
|
{
|
||||||
|
return new uint[]
|
||||||
|
{
|
||||||
|
0x4E31B800u, // ADDV B0, V0.16B
|
||||||
|
0x4E30A800u, // SMAXV B0, V0.16B
|
||||||
|
0x4E31A800u, // SMINV B0, V0.16B
|
||||||
|
0x6E30A800u, // UMAXV B0, V0.16B
|
||||||
|
0x6E31A800u // UMINV B0, V0.16B
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static uint[] _F_Abs_Neg_Recpx_Sqrt_S_S_()
|
private static uint[] _F_Abs_Neg_Recpx_Sqrt_S_S_()
|
||||||
{
|
{
|
||||||
return new uint[]
|
return new uint[]
|
||||||
|
@ -913,40 +937,40 @@ namespace Ryujinx.Tests.Cpu
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("ADDV <V><d>, <Vn>.<T>")]
|
[Test, Pairwise]
|
||||||
public void Addv_V_8BB_4HH([Values(0u)] uint rd,
|
public void SU_Add_Max_Min_V_V_8BB_4HH([ValueSource("_SU_Add_Max_Min_V_V_8BB_4HH_")] uint opcodes,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(0u)] uint rd,
|
||||||
[ValueSource("_8B4H_")] [Random(RndCnt)] ulong z,
|
[Values(1u, 0u)] uint rn,
|
||||||
[ValueSource("_8B4H_")] [Random(RndCnt)] ulong a,
|
[ValueSource("_8B4H_")] [Random(RndCnt)] ulong z,
|
||||||
[Values(0b00u, 0b01u)] uint size) // <8BB, 4HH>
|
[ValueSource("_8B4H_")] [Random(RndCnt)] ulong a,
|
||||||
|
[Values(0b00u, 0b01u)] uint size) // <8BB, 4HH>
|
||||||
{
|
{
|
||||||
uint opcode = 0x0E31B800; // ADDV B0, V0.8B
|
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
opcodes |= ((size & 3) << 22);
|
||||||
opcode |= ((size & 3) << 22);
|
|
||||||
|
|
||||||
Vector128<float> v0 = MakeVectorE0E1(z, z);
|
Vector128<float> v0 = MakeVectorE0E1(z, z);
|
||||||
Vector128<float> v1 = MakeVectorE0(a);
|
Vector128<float> v1 = MakeVectorE0(a);
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1);
|
SingleOpcode(opcodes, v0: v0, v1: v1);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("ADDV <V><d>, <Vn>.<T>")]
|
[Test, Pairwise]
|
||||||
public void Addv_V_16BB_8HH_4SS([Values(0u)] uint rd,
|
public void SU_Add_Max_Min_V_V_16BB_8HH_4SS([ValueSource("_SU_Add_Max_Min_V_V_16BB_8HH_4SS_")] uint opcodes,
|
||||||
[Values(1u, 0u)] uint rn,
|
[Values(0u)] uint rd,
|
||||||
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z,
|
[Values(1u, 0u)] uint rn,
|
||||||
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong a,
|
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong z,
|
||||||
[Values(0b00u, 0b01u, 0b10u)] uint size) // <16BB, 8HH, 4SS>
|
[ValueSource("_8B4H2S_")] [Random(RndCnt)] ulong a,
|
||||||
|
[Values(0b00u, 0b01u, 0b10u)] uint size) // <16BB, 8HH, 4SS>
|
||||||
{
|
{
|
||||||
uint opcode = 0x4E31B800; // ADDV B0, V0.16B
|
opcodes |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
||||||
opcode |= ((rn & 31) << 5) | ((rd & 31) << 0);
|
opcodes |= ((size & 3) << 22);
|
||||||
opcode |= ((size & 3) << 22);
|
|
||||||
|
|
||||||
Vector128<float> v0 = MakeVectorE0E1(z, z);
|
Vector128<float> v0 = MakeVectorE0E1(z, z);
|
||||||
Vector128<float> v1 = MakeVectorE0E1(a, a);
|
Vector128<float> v1 = MakeVectorE0E1(a, a);
|
||||||
|
|
||||||
SingleOpcode(opcode, v0: v0, v1: v1);
|
SingleOpcode(opcodes, v0: v0, v1: v1);
|
||||||
|
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue