diff --git a/Instructions/InstEmitSimdArithmetic.cs b/Instructions/InstEmitSimdArithmetic.cs index 0e610bb..8cf5c2c 100644 --- a/Instructions/InstEmitSimdArithmetic.cs +++ b/Instructions/InstEmitSimdArithmetic.cs @@ -68,21 +68,7 @@ namespace ChocolArm64.Instructions public static void Addv_V(ILEmitterCtx context) { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - 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); + EmitVectorAcrossVectorOpZx(context, () => context.Emit(OpCodes.Add)); } public static void Cls_V(ILEmitterCtx context) @@ -2388,6 +2374,15 @@ namespace ChocolArm64.Instructions 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) { if (Optimizations.UseSse41) @@ -2429,6 +2424,15 @@ namespace ChocolArm64.Instructions 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) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; @@ -3208,6 +3212,15 @@ namespace ChocolArm64.Instructions 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) { if (Optimizations.UseSse41) @@ -3249,6 +3262,15 @@ namespace ChocolArm64.Instructions 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) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; diff --git a/Instructions/InstEmitSimdHelper.cs b/Instructions/InstEmitSimdHelper.cs index 2bcda35..f343dba 100644 --- a/Instructions/InstEmitSimdHelper.cs +++ b/Instructions/InstEmitSimdHelper.cs @@ -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) { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; diff --git a/OpCodeTable.cs b/OpCodeTable.cs index fb8b19c..a1bbd4b 100644 --- a/OpCodeTable.cs +++ b/OpCodeTable.cs @@ -461,8 +461,12 @@ namespace ChocolArm64 SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", InstEmit.Sli_V, typeof(OpCodeSimdShImm64)); SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstEmit.Smax_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<<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("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Smlal_Ve, typeof(OpCodeSimdRegElem64)); SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstEmit.Smlsl_V, typeof(OpCodeSimdReg64)); @@ -556,8 +560,12 @@ namespace ChocolArm64 SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstEmit.Uhsub_V, typeof(OpCodeSimdReg64)); SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstEmit.Umax_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<<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("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstEmit.Umlal_Ve, typeof(OpCodeSimdRegElem64)); SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstEmit.Umlsl_V, typeof(OpCodeSimdReg64));