diff options
Diffstat (limited to 'ChocolArm64/Instructions/InstEmitSimdArithmetic.cs')
| -rw-r--r-- | ChocolArm64/Instructions/InstEmitSimdArithmetic.cs | 3797 |
1 files changed, 0 insertions, 3797 deletions
diff --git a/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs b/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs deleted file mode 100644 index fa9666eb..00000000 --- a/ChocolArm64/Instructions/InstEmitSimdArithmetic.cs +++ /dev/null @@ -1,3797 +0,0 @@ -// https://github.com/intel/ARM_NEON_2_x86_SSE/blob/master/NEON_2_SSE.h -// https://www.agner.org/optimize/#vectorclass @ vectori128.h - -using ChocolArm64.Decoders; -using ChocolArm64.IntermediateRepresentation; -using ChocolArm64.State; -using ChocolArm64.Translation; -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -using static ChocolArm64.Instructions.InstEmitSimdHelper; - -namespace ChocolArm64.Instructions -{ - static partial class InstEmit - { - public static void Abs_S(ILEmitterCtx context) - { - EmitScalarUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Abs_V(ILEmitterCtx context) - { - EmitVectorUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Add_S(ILEmitterCtx context) - { - EmitScalarBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Add_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.Add)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Addhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Add), round: false); - } - - public static void Addp_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - EmitVectorExtractZx(context, op.Rn, 0, op.Size); - EmitVectorExtractZx(context, op.Rn, 1, op.Size); - - context.Emit(OpCodes.Add); - - EmitScalarSet(context, op.Rd, op.Size); - } - - public static void Addp_V(ILEmitterCtx context) - { - EmitVectorPairwiseOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Addv_V(ILEmitterCtx context) - { - EmitVectorAcrossVectorOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Cls_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - int eSize = 8 << op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - - context.EmitLdc_I4(eSize); - - SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingSigns)); - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Clz_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int bytes = op.GetBitsCount() >> 3; - int elems = bytes >> op.Size; - - int eSize = 8 << op.Size; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size); - - if (Lzcnt.IsSupported && eSize == 32) - { - context.Emit(OpCodes.Conv_U4); - - context.EmitCall(typeof(Lzcnt).GetMethod(nameof(Lzcnt.LeadingZeroCount), new Type[] { typeof(uint) })); - - context.Emit(OpCodes.Conv_U8); - } - else - { - context.EmitLdc_I4(eSize); - - SoftFallback.EmitCall(context, nameof(SoftFallback.CountLeadingZeros)); - } - - EmitVectorInsert(context, op.Rd, index, op.Size); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Cnt_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8; - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, 0); - - if (Popcnt.IsSupported) - { - context.EmitCall(typeof(Popcnt).GetMethod(nameof(Popcnt.PopCount), new Type[] { typeof(ulong) })); - } - else - { - SoftFallback.EmitCall(context, nameof(SoftFallback.CountSetBits8)); - } - - EmitVectorInsert(context, op.Rd, index, 0); - } - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - public static void Fabd_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesSubAnt)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesSubAnt)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fabd_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesSubAnt)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesSubAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAnt)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesSubAnt)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fabs_S(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fabs_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesAnt = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesAnt = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Abs)); - }); - } - } - - public static void Fadd_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.AddScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - }); - } - } - - public static void Fadd_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Add)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - }); - } - } - - public static void Faddp_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse3) - { - if (sizeF == 0) - { - Type[] typesAddH = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse3).GetMethod(nameof(Sse3.HorizontalAdd), typesAddH)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesAddH = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse3).GetMethod(nameof(Sse3.HorizontalAdd), typesAddH)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorExtractF(context, op.Rn, 0, sizeF); - EmitVectorExtractF(context, op.Rn, 1, sizeF); - - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - - EmitScalarSetF(context, op.Rd, sizeF); - } - } - - public static void Faddp_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorPairwiseSseOrSse2OpF(context, nameof(Sse.Add)); - } - else - { - EmitVectorPairwiseOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd)); - }); - } - } - - public static void Fdiv_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.DivideScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv)); - }); - } - } - - public static void Fdiv_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Divide)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv)); - }); - } - } - - public static void Fmadd_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulAdd)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AddScalar), typesMulAdd)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AddScalar), typesMulAdd)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarTernaryRaOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd)); - }); - } - } - - public static void Fmax_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.MaxScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax)); - }); - } - } - - public static void Fmax_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Max)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax)); - }); - } - } - - public static void Fmaxnm_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum)); - }); - } - - public static void Fmaxnm_V(ILEmitterCtx context) - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum)); - }); - } - - public static void Fmaxp_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorPairwiseSseOrSse2OpF(context, nameof(Sse.Max)); - } - else - { - EmitVectorPairwiseOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax)); - }); - } - } - - public static void Fmin_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.MinScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin)); - }); - } - } - - public static void Fmin_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Min)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin)); - }); - } - } - - public static void Fminnm_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum)); - }); - } - - public static void Fminnm_V(ILEmitterCtx context) - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum)); - }); - } - - public static void Fminp_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorPairwiseSseOrSse2OpF(context, nameof(Sse.Min)); - } - else - { - EmitVectorPairwiseOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin)); - }); - } - } - - public static void Fmla_Se(ILEmitterCtx context) - { - EmitScalarTernaryOpByElemF(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Fmla_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd)); - }); - } - } - - public static void Fmla_Ve(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] typesMulAdd = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 2 | op.Index << 4 | op.Index << 6); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>), typeof(byte) }; - Type[] typesMulAdd = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd)); - }); - } - } - - public static void Fmls_Se(ILEmitterCtx context) - { - EmitScalarTernaryOpByElemF(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Fmls_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub)); - }); - } - } - - public static void Fmls_Ve(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 2 | op.Index << 4 | op.Index << 6); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>), typeof(byte) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorTernaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub)); - }); - } - } - - public static void Fmsub_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Ra); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarTernaryRaOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub)); - }); - } - } - - public static void Fmul_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.MultiplyScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul)); - }); - } - } - - public static void Fmul_Se(ILEmitterCtx context) - { - EmitScalarBinaryOpByElemF(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Fmul_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Multiply)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul)); - }); - } - } - - public static void Fmul_Ve(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdRegElemF64 op = (OpCodeSimdRegElemF64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSfl = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>), typeof(byte) }; - Type[] typesMul = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 2 | op.Index << 4 | op.Index << 6); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMul)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSfl = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>), typeof(byte) }; - Type[] typesMul = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rm); - - context.EmitLdc_I4(op.Index | op.Index << 1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Shuffle), typesSfl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMul)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul)); - }); - } - } - - public static void Fmulx_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fmulx_Se(ILEmitterCtx context) - { - EmitScalarBinaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fmulx_V(ILEmitterCtx context) - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fmulx_Ve(ILEmitterCtx context) - { - EmitVectorBinaryOpByElemF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX)); - }); - } - - public static void Fneg_S(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (op.Size == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesXor = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Xor), typesXor)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (op.Size == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesXor = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXor)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarUnaryOpF(context, () => context.Emit(OpCodes.Neg)); - } - } - - public static void Fneg_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesXor = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(-0f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Xor), typesXor)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesXor = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(-0d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXor)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => context.Emit(OpCodes.Neg)); - } - } - - public static void Fnmadd_S(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - EmitVectorExtractF(context, op.Rn, 0, sizeF); - - context.Emit(OpCodes.Neg); - - EmitVectorExtractF(context, op.Rm, 0, sizeF); - - context.Emit(OpCodes.Mul); - - EmitVectorExtractF(context, op.Ra, 0, sizeF); - - context.Emit(OpCodes.Sub); - - EmitScalarSetF(context, op.Rd, sizeF); - } - - public static void Fnmsub_S(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - EmitVectorExtractF(context, op.Rn, 0, sizeF); - EmitVectorExtractF(context, op.Rm, 0, sizeF); - - context.Emit(OpCodes.Mul); - - EmitVectorExtractF(context, op.Ra, 0, sizeF); - - context.Emit(OpCodes.Sub); - - EmitScalarSetF(context, op.Rd, sizeF); - } - - public static void Fnmul_S(ILEmitterCtx context) - { - EmitScalarBinaryOpF(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Neg); - }); - } - - public static void Frecpe_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.ReciprocalScalar)); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate)); - }); - } - } - - public static void Frecpe_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Reciprocal)); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate)); - }); - } - } - - public static void Frecps_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(2f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(2d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused)); - }); - } - } - - public static void Frecps_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(2f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(2d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused)); - }); - } - } - - public static void Frecpx_S(ILEmitterCtx context) - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecpX)); - }); - } - - public static void Frinta_S(ILEmitterCtx context) - { - EmitScalarUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.AwayFromZero); - }); - } - - public static void Frinta_V(ILEmitterCtx context) - { - EmitVectorUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.AwayFromZero); - }); - } - - public static void Frinti_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (Optimizations.UseSse41) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRound)); - } - - context.EmitStvec(op.Rd); - } - else - { - EmitScalarUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frinti_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse41) - { - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRound)); - } - - context.EmitStvec(op.Rd); - - if (sizeF == 0 && op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frintm_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsMinusInfinity, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Floor)); - }); - } - } - - public static void Frintm_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsMinusInfinity, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Floor)); - }); - } - } - - public static void Frintn_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.ToNearest, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.ToEven); - }); - } - } - - public static void Frintn_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.ToNearest, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitRoundMathCall(context, MidpointRounding.ToEven); - }); - } - } - - public static void Frintp_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsPlusInfinity, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Ceiling)); - }); - } - } - - public static void Frintp_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsPlusInfinity, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Ceiling)); - }); - } - } - - public static void Frintx_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (Optimizations.UseSse41) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41ScalarRound)); - } - - context.EmitStvec(op.Rd); - } - else - { - EmitScalarUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (op.Size == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (op.Size == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frintx_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.UseSse41) - { - context.EmitLdvec(op.Rn); - - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Sse41VectorRound)); - } - - context.EmitStvec(op.Rd); - - if (sizeF == 0 && op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpF(context, () => - { - context.EmitLdarg(TranslatedSub.StateArgIdx); - - if (sizeF == 0) - { - VectorHelper.EmitCall(context, nameof(VectorHelper.RoundF)); - } - else /* if (sizeF == 1) */ - { - VectorHelper.EmitCall(context, nameof(VectorHelper.Round)); - } - }); - } - } - - public static void Frintz_S(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsZero, scalar: true); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Truncate)); - }); - } - } - - public static void Frintz_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Frint(context, RoundMode.TowardsZero, scalar: false); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitUnaryMathCall(context, nameof(Math.Truncate)); - }); - } - } - - public static void Frsqrte_S(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.ReciprocalSqrtScalar)); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate)); - }); - } - } - - public static void Frsqrte_V(ILEmitterCtx context) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (Optimizations.FastFP && Optimizations.UseSse && sizeF == 0) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.ReciprocalSqrt)); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate)); - }); - } - } - - public static void Frsqrts_S(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSsv = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(0.5f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdc_R4(3f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZero32_128(context, op.Rd); - } - else /* if (sizeF == 1) */ - { - Type[] typesSsv = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(0.5d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdc_R8(3d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), typesSsv)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), typesMulSub)); - - context.EmitStvec(op.Rd); - - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStepFused)); - }); - } - } - - public static void Frsqrts_V(ILEmitterCtx context) // Fused. - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int sizeF = op.Size & 1; - - if (sizeF == 0) - { - Type[] typesSav = new Type[] { typeof(float) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - - context.EmitLdc_R4(0.5f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdc_R4(3f); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), typesMulSub)); - context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else /* if (sizeF == 1) */ - { - Type[] typesSav = new Type[] { typeof(double) }; - Type[] typesMulSub = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - context.EmitLdc_R8(0.5d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdc_R8(3d); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesMulSub)); - - context.EmitStvec(op.Rd); - } - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStepFused)); - }); - } - } - - public static void Fsqrt_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.SqrtScalar)); - } - else - { - EmitScalarUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt)); - }); - } - } - - public static void Fsqrt_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Sqrt)); - } - else - { - EmitVectorUnaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt)); - }); - } - } - - public static void Fsub_S(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitScalarSseOrSse2OpF(context, nameof(Sse.SubtractScalar)); - } - else - { - EmitScalarBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - }); - } - } - - public static void Fsub_V(ILEmitterCtx context) - { - if (Optimizations.FastFP && Optimizations.UseSse2) - { - EmitVectorSseOrSse2OpF(context, nameof(Sse.Subtract)); - } - else - { - EmitVectorBinaryOpF(context, () => - { - EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub)); - }); - } - } - - public static void Mla_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Mul_AddSub(context, nameof(Sse2.Add)); - } - else - { - EmitVectorTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - } - - public static void Mla_Ve(ILEmitterCtx context) - { - EmitVectorTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Mls_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Mul_AddSub(context, nameof(Sse2.Subtract)); - } - else - { - EmitVectorTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - } - - public static void Mls_Ve(ILEmitterCtx context) - { - EmitVectorTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Mul_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - EmitSse41Mul_AddSub(context); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Mul)); - } - } - - public static void Mul_Ve(ILEmitterCtx context) - { - EmitVectorBinaryOpByElemZx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Neg_S(ILEmitterCtx context) - { - EmitScalarUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - - public static void Neg_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - Type[] typesSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - } - - public static void Raddhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Add), round: true); - } - - public static void Rsubhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Sub), round: true); - } - - public static void Saba_V(ILEmitterCtx context) - { - EmitVectorTernaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Sabal_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmTernaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Sabd_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), typesCmpSub)); - - context.EmitStvectmp(); // Cmp mask - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Sabdl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitStvectmp2(); // Long Rm - context.EmitStvectmp(); // Long Rn - - context.EmitLdvectmp(); // Long Rn - context.EmitLdvectmp2(); // Long Rm - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThan), typesCmpSub)); - - context.EmitStvectmp3(); // Cmp mask - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp(); // Long Rn - context.EmitLdvectmp2(); // Long Rm - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp2(); // Long Rm - context.EmitLdvectmp(); // Long Rn - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Sadalp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: true, accumulate: true); - } - - public static void Saddl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Saddlp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: true, accumulate: false); - } - - public static void Saddlv_V(ILEmitterCtx context) - { - EmitVectorLongAcrossVectorOpSx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Saddw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpSx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Shadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSra = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndXorAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndXorAdd)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesAndXorAdd)); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAndXorAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - }); - } - } - - public static void Shsub_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesSav = new Type[] { IntTypesPerSizeLog2[op.Size] }; - Type[] typesAddSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAvg = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdc_I4(op.Size == 0 ? sbyte.MinValue : short.MinValue); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp(); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAddSub)); - - context.Emit(OpCodes.Dup); - - context.EmitLdvec(op.Rm); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAddSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesAddSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Sub); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - }); - } - } - - public static void Smax_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMax = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 1 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorBinaryOpSx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Smaxp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - 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) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMin = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 1 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Min), typesMin)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorBinaryOpSx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Sminp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(long), typeof(long) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - 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; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulAdd = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulAdd)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - } - - public static void Smlal_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Smlsl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - } - - public static void Smlsl_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemSx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Smull_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Smull_Ve(ILEmitterCtx context) - { - EmitVectorWidenBinaryOpByElemSx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Sqabs_S(ILEmitterCtx context) - { - EmitScalarSaturatingUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Sqabs_V(ILEmitterCtx context) - { - EmitVectorSaturatingUnaryOpSx(context, () => EmitAbs(context)); - } - - public static void Sqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpSx(context, SaturatingFlags.Add); - } - - public static void Sqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpSx(context, SaturatingFlags.Add); - } - - public static void Sqdmulh_S(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: false), SaturatingFlags.ScalarSx); - } - - public static void Sqdmulh_V(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: false), SaturatingFlags.VectorSx); - } - - public static void Sqneg_S(ILEmitterCtx context) - { - EmitScalarSaturatingUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - - public static void Sqneg_V(ILEmitterCtx context) - { - EmitVectorSaturatingUnaryOpSx(context, () => context.Emit(OpCodes.Neg)); - } - - public static void Sqrdmulh_S(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: true), SaturatingFlags.ScalarSx); - } - - public static void Sqrdmulh_V(ILEmitterCtx context) - { - EmitSaturatingBinaryOp(context, () => EmitDoublingMultiplyHighHalf(context, round: true), SaturatingFlags.VectorSx); - } - - public static void Sqsub_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpSx(context, SaturatingFlags.Sub); - } - - public static void Sqsub_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpSx(context, SaturatingFlags.Sub); - } - - public static void Sqxtn_S(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.ScalarSxSx); - } - - public static void Sqxtn_V(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.VectorSxSx); - } - - public static void Sqxtun_S(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.ScalarSxZx); - } - - public static void Sqxtun_V(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.VectorSxZx); - } - - public static void Srhadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesSav = new Type[] { IntTypesPerSizeLog2[op.Size] }; - Type[] typesSubAdd = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAvg = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdc_I4(op.Size == 0 ? sbyte.MinValue : short.MinValue); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitStvectmp(); - context.EmitLdvectmp(); - - context.EmitLdvec(op.Rn); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAdd)); - - context.EmitLdvec(op.Rm); - context.EmitLdvectmp(); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSubAdd)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesSubAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpSx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr); - }); - } - } - - public static void Ssubl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpSx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Ssubw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size + 1], - VectorIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpSx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Sub_S(ILEmitterCtx context) - { - EmitScalarBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - - public static void Sub_V(ILEmitterCtx context) - { - if (Optimizations.UseSse2) - { - EmitSse2Op(context, nameof(Sse2.Subtract)); - } - else - { - EmitVectorBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Subhn_V(ILEmitterCtx context) - { - EmitHighNarrow(context, () => context.Emit(OpCodes.Sub), round: false); - } - - public static void Suqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpSx(context, SaturatingFlags.Accumulate); - } - - public static void Suqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpSx(context, SaturatingFlags.Accumulate); - } - - public static void Uaba_V(ILEmitterCtx context) - { - EmitVectorTernaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Uabal_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmTernaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - - context.Emit(OpCodes.Add); - }); - } - - public static void Uabd_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesSav = new Type[] { typeof(long) }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmpSub)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitStvectmp(); // Cmp mask - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp(); // Cmp mask - - context.EmitLdvec(op.Rm); - context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Uabdl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - Type[] typesCmpSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size + 1], - VectorIntTypesPerSizeLog2 [op.Size + 1] }; - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndOr = new Type[] { typeof(Vector128<long>), typeof(Vector128<long>) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesSav = new Type[] { typeof(long) }; - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitStvectmp2(); // Long Rm - context.EmitStvectmp(); // Long Rn - - context.EmitLdvectmp2(); // Long Rm - context.EmitLdvectmp(); // Long Rn - - context.EmitCall(typeof(Sse41).GetMethod(nameof(Sse41.Max), typesMax)); - - context.EmitLdvectmp2(); // Long Rm - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmpSub)); - - context.EmitLdc_I8(-1L); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitStvectmp3(); // Cmp mask - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp(); // Long Rn - context.EmitLdvectmp2(); // Long Rm - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndOr)); - - context.EmitLdvectmp3(); // Cmp mask - - context.EmitLdvectmp2(); // Long Rm - context.EmitLdvectmp(); // Long Rn - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesCmpSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndOr)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAndOr)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - EmitAbs(context); - }); - } - } - - public static void Uadalp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: false, accumulate: true); - } - - public static void Uaddl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Uaddlp_V(ILEmitterCtx context) - { - EmitAddLongPairwise(context, signed: false, accumulate: false); - } - - public static void Uaddlv_V(ILEmitterCtx context) - { - EmitVectorLongAcrossVectorOpZx(context, () => context.Emit(OpCodes.Add)); - } - - public static void Uaddw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpZx(context, () => context.Emit(OpCodes.Add)); - } - } - - public static void Uhadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size > 0) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesAndXorAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAndXorAdd)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesAndXorAdd)); - - context.Emit(OpCodes.Ldc_I4_1); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAndXorAdd)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr_Un); - }); - } - } - - public static void Uhsub_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesAvgSub = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvgSub)); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesAvgSub)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Sub); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr_Un); - }); - } - } - - public static void Umax_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - EmitVectorBinaryOpZx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Umaxp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Max), types); - - 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) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesMin = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.Min), typesMin)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - EmitVectorBinaryOpZx(context, () => context.EmitCall(mthdInfo)); - } - } - - public static void Uminp_V(ILEmitterCtx context) - { - Type[] types = new Type[] { typeof(ulong), typeof(ulong) }; - - MethodInfo mthdInfo = typeof(Math).GetMethod(nameof(Math.Min), types); - - 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; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulAdd = new Type[] { VectorIntTypesPerSizeLog2 [op.Size + 1], - VectorIntTypesPerSizeLog2 [op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulAdd)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesMulAdd)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - } - - public static void Umlal_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Add); - }); - } - - public static void Umlsl_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse41 && op.Size < 2) - { - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesMulSub = new Type[] { VectorIntTypesPerSizeLog2 [op.Size + 1], - VectorIntTypesPerSizeLog2 [op.Size + 1] }; - - Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41); - - string nameCvt = op.Size == 0 - ? nameof(Sse41.ConvertToVector128Int16) - : nameof(Sse41.ConvertToVector128Int32); - - context.EmitLdvec(op.Rd); - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(nameCvt, typesCvt)); - - context.EmitCall(typeSse.GetMethod(nameof(Sse2.MultiplyLow), typesMulSub)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesMulSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmTernaryOpZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - } - - public static void Umlsl_Ve(ILEmitterCtx context) - { - EmitVectorWidenTernaryOpByElemZx(context, () => - { - context.Emit(OpCodes.Mul); - context.Emit(OpCodes.Sub); - }); - } - - public static void Umull_V(ILEmitterCtx context) - { - EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Umull_Ve(ILEmitterCtx context) - { - EmitVectorWidenBinaryOpByElemZx(context, () => context.Emit(OpCodes.Mul)); - } - - public static void Uqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpZx(context, SaturatingFlags.Add); - } - - public static void Uqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpZx(context, SaturatingFlags.Add); - } - - public static void Uqsub_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpZx(context, SaturatingFlags.Sub); - } - - public static void Uqsub_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpZx(context, SaturatingFlags.Sub); - } - - public static void Uqxtn_S(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.ScalarZxZx); - } - - public static void Uqxtn_V(ILEmitterCtx context) - { - EmitSaturatingNarrowOp(context, SaturatingNarrowFlags.VectorZxZx); - } - - public static void Urhadd_V(ILEmitterCtx context) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (Optimizations.UseSse2 && op.Size < 2) - { - Type[] typesAvg = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Average), typesAvg)); - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - else - { - EmitVectorBinaryOpZx(context, () => - { - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Add); - - context.Emit(OpCodes.Ldc_I4_1); - context.Emit(OpCodes.Shr_Un); - }); - } - } - - public static void Usqadd_S(ILEmitterCtx context) - { - EmitScalarSaturatingBinaryOpZx(context, SaturatingFlags.Accumulate); - } - - public static void Usqadd_V(ILEmitterCtx context) - { - EmitVectorSaturatingBinaryOpZx(context, SaturatingFlags.Accumulate); - } - - public static void Usubl_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRnRmBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - } - - public static void Usubw_V(ILEmitterCtx context) - { - if (Optimizations.UseSse41) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) }; - Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] }; - Type[] typesSub = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], - VectorUIntTypesPerSizeLog2[op.Size + 1] }; - - string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16), - nameof(Sse41.ConvertToVector128Int32), - nameof(Sse41.ConvertToVector128Int64) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - if (op.RegisterSize == RegisterSize.Simd128) - { - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSrl)); - } - - context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), typesSub)); - - context.EmitStvec(op.Rd); - } - else - { - EmitVectorWidenRmBinaryOpZx(context, () => context.Emit(OpCodes.Sub)); - } - } - - private static void EmitAbs(ILEmitterCtx context) - { - ILLabel lblTrue = new ILLabel(); - - context.Emit(OpCodes.Dup); - context.Emit(OpCodes.Ldc_I4_0); - context.Emit(OpCodes.Bge_S, lblTrue); - - context.Emit(OpCodes.Neg); - - context.MarkLabel(lblTrue); - } - - private static void EmitAddLongPairwise(ILEmitterCtx context, bool signed, bool accumulate) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - int words = op.GetBitsCount() >> 4; - int pairs = words >> op.Size; - - for (int index = 0; index < pairs; index++) - { - int idx = index << 1; - - EmitVectorExtract(context, op.Rn, idx, op.Size, signed); - EmitVectorExtract(context, op.Rn, idx + 1, op.Size, signed); - - context.Emit(OpCodes.Add); - - if (accumulate) - { - EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed); - - context.Emit(OpCodes.Add); - } - - EmitVectorInsertTmp(context, index, op.Size + 1); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitDoublingMultiplyHighHalf(ILEmitterCtx context, bool round) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int eSize = 8 << op.Size; - - context.Emit(OpCodes.Mul); - - if (!round) - { - context.EmitAsr(eSize - 1); - } - else - { - long roundConst = 1L << (eSize - 1); - - ILLabel lblTrue = new ILLabel(); - - context.EmitLsl(1); - - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - - context.EmitAsr(eSize); - - context.Emit(OpCodes.Dup); - context.EmitLdc_I8((long)int.MinValue); - context.Emit(OpCodes.Bne_Un_S, lblTrue); - - context.Emit(OpCodes.Neg); - - context.MarkLabel(lblTrue); - } - } - - private static void EmitHighNarrow(ILEmitterCtx context, Action emit, bool round) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - int elems = 8 >> op.Size; - - int eSize = 8 << op.Size; - - int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; - - long roundConst = 1L << (eSize - 1); - - if (part != 0) - { - context.EmitLdvec(op.Rd); - context.EmitStvectmp(); - } - - for (int index = 0; index < elems; index++) - { - EmitVectorExtractZx(context, op.Rn, index, op.Size + 1); - EmitVectorExtractZx(context, op.Rm, index, op.Size + 1); - - emit(); - - if (round) - { - context.EmitLdc_I8(roundConst); - - context.Emit(OpCodes.Add); - } - - context.EmitLsr(eSize); - - EmitVectorInsertTmp(context, part + index, op.Size); - } - - context.EmitLdvectmp(); - context.EmitStvec(op.Rd); - - if (part == 0) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - - private static void EmitSse41Frint(ILEmitterCtx context, RoundMode roundMode, bool scalar) - { - OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - - if (scalar) - { - Type[] typesRnd = op.Size == 0 - ? new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) } - : new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - - VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse41).GetMethod(GetScalarSse41NameRnd(roundMode), typesRnd)); - - context.EmitStvec(op.Rd); - } - else - { - int sizeF = op.Size & 1; - - Type[] typesRnd = sizeF == 0 - ? new Type[] { typeof(Vector128<float>) } - : new Type[] { typeof(Vector128<double>) }; - - context.EmitLdvec(op.Rn); - - context.EmitCall(typeof(Sse41).GetMethod(GetVectorSse41NameRnd(roundMode), typesRnd)); - - context.EmitStvec(op.Rd); - - if (sizeF == 0 && op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } - - private static void EmitSse41Mul_AddSub(ILEmitterCtx context, string nameAddSub = null) - { - OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; - - if (nameAddSub != null) - { - context.EmitLdvec(op.Rd); - } - - if (op.Size == 0) - { - Type[] typesBle = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) }; - Type[] typesMul = new Type[] { typeof(Vector128<short>), typeof(Vector128<short>) }; - Type[] typesShs = new Type[] { typeof(Vector128<short>), typeof(byte) }; - Type[] typesSav = new Type[] { typeof(int) }; - - context.EmitLdvec(op.Rn); - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitLdvec(op.Rm); - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesShs)); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyLow), typesMul)); - - context.Emit(OpCodes.Ldc_I4_8); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesShs)); - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyLow), typesMul)); - - context.EmitLdc_I4(0x00FF00FF); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav)); - - context.EmitCall(typeof(Sse41).GetMethod(nameof(Sse41.BlendVariable), typesBle)); - } - else if (op.Size == 1) - { - Type[] typesMul = new Type[] { typeof(Vector128<short>), typeof(Vector128<short>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyLow), typesMul)); - } - else /* if (op.Size == 2) */ - { - Type[] typesMul = new Type[] { typeof(Vector128<int>), typeof(Vector128<int>) }; - - context.EmitLdvec(op.Rn); - context.EmitLdvec(op.Rm); - - context.EmitCall(typeof(Sse41).GetMethod(nameof(Sse41.MultiplyLow), typesMul)); - } - - if (nameAddSub != null) - { - Type[] typesAddSub = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] }; - - context.EmitCall(typeof(Sse2).GetMethod(nameAddSub, typesAddSub)); - } - - context.EmitStvec(op.Rd); - - if (op.RegisterSize == RegisterSize.Simd64) - { - EmitVectorZeroUpper(context, op.Rd); - } - } - } -} |
