diff options
| author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2018-10-06 03:45:59 +0200 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-10-05 22:45:59 -0300 |
| commit | bba9bf97d03596b89972cc77390311b9e9472688 (patch) | |
| tree | aa40965478ac88682a2e2ff9f032e42346a471c8 /ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs | |
| parent | 0254a84f90ea03037be15b8fd1f9e0a4be5577e9 (diff) | |
Add 9+7 fast/slow FP inst. impls.; add 14 FP Tests. (#437)
* Update CpuTest.cs
* Delete CpuTestSimdCmp.cs
Obsolete.
* Update CpuTestSimdArithmetic.cs
Superseded.
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Update AInstEmitSimdArithmetic.cs
* Update AInstEmitSimdHelper.cs
* Update ASoftFloat.cs
* Nit.
* Update AOpCodeTable.cs
* Update AOptimizations.cs
* Update AInstEmitSimdArithmetic.cs
* Update ASoftFloat.cs
* Update CpuTest.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Update AOpCodeTable.cs
* Update AInstEmitSimdArithmetic.cs
* Update ASoftFloat.cs
* Update CpuTestSimdReg.cs
* Update AOpCodeTable.cs
* Update AInstEmitSimdArithmetic.cs
* Update ASoftFloat.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
Diffstat (limited to 'ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs')
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs | 506 |
1 files changed, 409 insertions, 97 deletions
diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 811730fc..d11a0b84 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -174,25 +174,33 @@ namespace ChocolArm64.Instruction public static void Fadd_S(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitScalarSseOrSse2OpF(Context, nameof(Sse.AddScalar)); } else { - EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Add)); + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPAdd)); + }); } } public static void Fadd_V(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitVectorSseOrSse2OpF(Context, nameof(Sse.Add)); } else { - EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Add)); + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPAdd)); + }); } } @@ -217,42 +225,50 @@ namespace ChocolArm64.Instruction public static void Fdiv_S(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitScalarSseOrSse2OpF(Context, nameof(Sse.DivideScalar)); } else { - EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Div)); + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPDiv)); + }); } } public static void Fdiv_V(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitVectorSseOrSse2OpF(Context, nameof(Sse.Divide)); } else { - EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Div)); + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPDiv)); + }); } } public static void Fmadd_S(AILEmitterCtx Context) { - if (AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse2) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; if (Op.Size == 0) { + Type[] Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; + Context.EmitLdvec(Op.Ra); Context.EmitLdvec(Op.Rn); Context.EmitLdvec(Op.Rm); - Type[] Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), Types)); Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.AddScalar), Types)); @@ -262,12 +278,12 @@ namespace ChocolArm64.Instruction } else /* if (Op.Size == 1) */ { + Type[] Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; + EmitLdvecWithCastToDouble(Context, Op.Ra); EmitLdvecWithCastToDouble(Context, Op.Rn); EmitLdvecWithCastToDouble(Context, Op.Rm); - Type[] Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), Types)); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AddScalar), Types)); @@ -280,33 +296,48 @@ namespace ChocolArm64.Instruction { EmitScalarTernaryRaOpF(Context, () => { - Context.Emit(OpCodes.Mul); - Context.Emit(OpCodes.Add); + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulAdd)); }); } } public static void Fmax_S(AILEmitterCtx Context) { - EmitScalarBinaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.Max)); - }); + EmitScalarSseOrSse2OpF(Context, nameof(Sse.MaxScalar)); + } + else + { + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax)); + }); + } } public static void Fmax_V(AILEmitterCtx Context) { - EmitVectorBinaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.Max)); - }); + EmitVectorSseOrSse2OpF(Context, nameof(Sse.Max)); + } + else + { + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax)); + }); + } } public static void Fmaxnm_S(AILEmitterCtx Context) { EmitScalarBinaryOpF(Context, () => { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.MaxNum)); + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMaxNum)); }); } @@ -314,36 +345,55 @@ namespace ChocolArm64.Instruction { EmitVectorBinaryOpF(Context, () => { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.MaxNum)); + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMaxNum)); }); } public static void Fmaxp_V(AILEmitterCtx Context) { - EmitVectorPairwiseOpF(Context, () => EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.Max))); + EmitVectorPairwiseOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMax)); + }); } public static void Fmin_S(AILEmitterCtx Context) { - EmitScalarBinaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.Min)); - }); + EmitScalarSseOrSse2OpF(Context, nameof(Sse.MinScalar)); + } + else + { + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin)); + }); + } } public static void Fmin_V(AILEmitterCtx Context) { - EmitVectorBinaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.Min)); - }); + EmitVectorSseOrSse2OpF(Context, nameof(Sse.Min)); + } + else + { + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin)); + }); + } } public static void Fminnm_S(AILEmitterCtx Context) { EmitScalarBinaryOpF(Context, () => { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.MinNum)); + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMinNum)); }); } @@ -351,13 +401,16 @@ namespace ChocolArm64.Instruction { EmitVectorBinaryOpF(Context, () => { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.MinNum)); + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMinNum)); }); } public static void Fminp_V(AILEmitterCtx Context) { - EmitVectorPairwiseOpF(Context, () => EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.Min))); + EmitVectorPairwiseOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMin)); + }); } public static void Fmla_Se(AILEmitterCtx Context) @@ -407,22 +460,63 @@ namespace ChocolArm64.Instruction public static void Fmsub_S(AILEmitterCtx Context) { - EmitScalarTernaryRaOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse2) { - Context.Emit(OpCodes.Mul); - Context.Emit(OpCodes.Sub); - }); + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + if (Op.Size == 0) + { + Type[] Types = 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), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), Types)); + + Context.EmitStvec(Op.Rd); + + EmitVectorZero32_128(Context, Op.Rd); + } + else /* if (Op.Size == 1) */ + { + Type[] Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; + + EmitLdvecWithCastToDouble(Context, Op.Ra); + EmitLdvecWithCastToDouble(Context, Op.Rn); + EmitLdvecWithCastToDouble(Context, Op.Rm); + + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), Types)); + + EmitStvecWithCastFromDouble(Context, Op.Rd); + + EmitVectorZeroUpper(Context, Op.Rd); + } + } + else + { + EmitScalarTernaryRaOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulSub)); + }); + } } public static void Fmul_S(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitScalarSseOrSse2OpF(Context, nameof(Sse.MultiplyScalar)); } else { - EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Mul)); + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMul)); + }); } } @@ -433,13 +527,17 @@ namespace ChocolArm64.Instruction public static void Fmul_V(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitVectorSseOrSse2OpF(Context, nameof(Sse.Multiply)); } else { - EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Mul)); + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMul)); + }); } } @@ -448,6 +546,22 @@ namespace ChocolArm64.Instruction EmitVectorBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul)); } + public static void Fmulx_S(AILEmitterCtx Context) + { + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX)); + }); + } + + public static void Fmulx_V(AILEmitterCtx Context) + { + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPMulX)); + }); + } + public static void Fneg_S(AILEmitterCtx Context) { EmitScalarUnaryOpF(Context, () => Context.Emit(OpCodes.Neg)); @@ -524,17 +638,122 @@ namespace ChocolArm64.Instruction public static void Frecps_S(AILEmitterCtx Context) { - EmitScalarBinaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse2) { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.RecipStep)); - }); + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int SizeF = Op.Size & 1; + + if (SizeF == 0) + { + Type[] Types = new Type[] { typeof(float) }; + + Context.EmitLdc_R4(2f); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), Types)); + + Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; + + Context.EmitLdvec(Op.Rn); + Context.EmitLdvec(Op.Rm); + + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), Types)); + + Context.EmitStvec(Op.Rd); + + EmitVectorZero32_128(Context, Op.Rd); + } + else /* if (SizeF == 1) */ + { + Type[] Types = new Type[] { typeof(double) }; + + Context.EmitLdc_R8(2d); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), Types)); + + Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; + + EmitLdvecWithCastToDouble(Context, Op.Rn); + EmitLdvecWithCastToDouble(Context, Op.Rm); + + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), Types)); + + EmitStvecWithCastFromDouble(Context, Op.Rd); + + EmitVectorZeroUpper(Context, Op.Rd); + } + } + else + { + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecipStepFused)); + }); + } } public static void Frecps_V(AILEmitterCtx Context) { - EmitVectorBinaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse2) { - EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.RecipStep)); + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int SizeF = Op.Size & 1; + + if (SizeF == 0) + { + Type[] Types = new Type[] { typeof(float) }; + + Context.EmitLdc_R4(2f); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), Types)); + + Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; + + Context.EmitLdvec(Op.Rn); + Context.EmitLdvec(Op.Rm); + + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), Types)); + + Context.EmitStvec(Op.Rd); + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + else /* if (SizeF == 1) */ + { + Type[] Types = new Type[] { typeof(double) }; + + Context.EmitLdc_R8(2d); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types)); + + Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; + + EmitLdvecWithCastToDouble(Context, Op.Rn); + EmitLdvecWithCastToDouble(Context, Op.Rm); + + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), Types)); + + EmitStvecWithCastFromDouble(Context, Op.Rd); + } + } + else + { + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecipStepFused)); + }); + } + } + + public static void Frecpx_S(AILEmitterCtx Context) + { + EmitScalarUnaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRecpX)); }); } @@ -728,97 +947,194 @@ namespace ChocolArm64.Instruction public static void Frsqrts_S(AILEmitterCtx Context) { - EmitFrsqrts(Context, 0, Scalar: true); - } + if (AOptimizations.FastFP && AOptimizations.UseSse2) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - public static void Frsqrts_V(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + int SizeF = Op.Size & 1; - int SizeF = Op.Size & 1; + if (SizeF == 0) + { + Type[] Types = new Type[] { typeof(float) }; - int Bytes = Op.GetBitsCount() >> 3; + Context.EmitLdc_R4(0.5f); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), Types)); - for (int Index = 0; Index < Bytes >> SizeF + 2; Index++) - { - EmitFrsqrts(Context, Index, Scalar: false); - } + Context.EmitLdc_R4(3f); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), Types)); - if (Op.RegisterSize == ARegisterSize.SIMD64) + Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; + + Context.EmitLdvec(Op.Rn); + Context.EmitLdvec(Op.Rm); + + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SubtractScalar), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MultiplyScalar), Types)); + + Context.EmitStvec(Op.Rd); + + EmitVectorZero32_128(Context, Op.Rd); + } + else /* if (SizeF == 1) */ + { + Type[] Types = new Type[] { typeof(double) }; + + Context.EmitLdc_R8(0.5d); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), Types)); + + Context.EmitLdc_R8(3d); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetScalarVector128), Types)); + + Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; + + EmitLdvecWithCastToDouble(Context, Op.Rn); + EmitLdvecWithCastToDouble(Context, Op.Rm); + + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SubtractScalar), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MultiplyScalar), Types)); + + EmitStvecWithCastFromDouble(Context, Op.Rd); + + EmitVectorZeroUpper(Context, Op.Rd); + } + } + else { - EmitVectorZeroUpper(Context, Op.Rd); + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused)); + }); } } - private static void EmitFrsqrts(AILEmitterCtx Context, int Index, bool Scalar) + public static void Frsqrts_V(AILEmitterCtx Context) { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + if (AOptimizations.FastFP && AOptimizations.UseSse2) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - int SizeF = Op.Size & 1; + int SizeF = Op.Size & 1; - if (SizeF == 0) - { - Context.EmitLdc_R4(3); - } - else /* if (SizeF == 1) */ - { - Context.EmitLdc_R8(3); - } + if (SizeF == 0) + { + Type[] Types = new Type[] { typeof(float) }; - EmitVectorExtractF(Context, Op.Rn, Index, SizeF); - EmitVectorExtractF(Context, Op.Rm, Index, SizeF); + Context.EmitLdc_R4(0.5f); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), Types)); - Context.Emit(OpCodes.Mul); - Context.Emit(OpCodes.Sub); + Context.EmitLdc_R4(3f); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), Types)); - if (SizeF == 0) - { - Context.EmitLdc_R4(0.5f); + Types = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; + + Context.EmitLdvec(Op.Rn); + Context.EmitLdvec(Op.Rm); + + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Subtract), Types)); + Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), Types)); + + Context.EmitStvec(Op.Rd); + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + else /* if (SizeF == 1) */ + { + Type[] Types = new Type[] { typeof(double) }; + + Context.EmitLdc_R8(0.5d); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types)); + + Context.EmitLdc_R8(3d); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types)); + + Types = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; + + EmitLdvecWithCastToDouble(Context, Op.Rn); + EmitLdvecWithCastToDouble(Context, Op.Rm); + + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Subtract), Types)); + Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), Types)); + + EmitStvecWithCastFromDouble(Context, Op.Rd); + } } - else /* if (SizeF == 1) */ + else { - Context.EmitLdc_R8(0.5); + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused)); + }); } + } - Context.Emit(OpCodes.Mul); - - if (Scalar) + public static void Fsqrt_S(AILEmitterCtx Context) + { + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { - EmitVectorZeroAll(Context, Op.Rd); + EmitScalarSseOrSse2OpF(Context, nameof(Sse.SqrtScalar)); + } + else + { + EmitScalarUnaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt)); + }); } - - EmitVectorInsertF(Context, Op.Rd, Index, SizeF); } - public static void Fsqrt_S(AILEmitterCtx Context) + public static void Fsqrt_V(AILEmitterCtx Context) { - EmitScalarUnaryOpF(Context, () => + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { - EmitUnaryMathCall(Context, nameof(Math.Sqrt)); - }); + EmitVectorSseOrSse2OpF(Context, nameof(Sse.Sqrt)); + } + else + { + EmitVectorUnaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt)); + }); + } } public static void Fsub_S(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitScalarSseOrSse2OpF(Context, nameof(Sse.SubtractScalar)); } else { - EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Sub)); + EmitScalarBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSub)); + }); } } public static void Fsub_V(AILEmitterCtx Context) { - if (AOptimizations.UseSse && AOptimizations.UseSse2) + if (AOptimizations.FastFP && AOptimizations.UseSse + && AOptimizations.UseSse2) { EmitVectorSseOrSse2OpF(Context, nameof(Sse.Subtract)); } else { - EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Sub)); + EmitVectorBinaryOpF(Context, () => + { + EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSub)); + }); } } @@ -1170,7 +1486,6 @@ namespace ChocolArm64.Instruction EmitVectorTernaryOpZx(Context, () => { Context.Emit(OpCodes.Sub); - EmitAbs(Context); Context.Emit(OpCodes.Add); @@ -1182,7 +1497,6 @@ namespace ChocolArm64.Instruction EmitVectorWidenRnRmTernaryOpZx(Context, () => { Context.Emit(OpCodes.Sub); - EmitAbs(Context); Context.Emit(OpCodes.Add); @@ -1194,7 +1508,6 @@ namespace ChocolArm64.Instruction EmitVectorBinaryOpZx(Context, () => { Context.Emit(OpCodes.Sub); - EmitAbs(Context); }); } @@ -1204,7 +1517,6 @@ namespace ChocolArm64.Instruction EmitVectorWidenRnRmBinaryOpZx(Context, () => { Context.Emit(OpCodes.Sub); - EmitAbs(Context); }); } |
