aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-10-06 03:45:59 +0200
committergdkchan <gab.dark.100@gmail.com>2018-10-05 22:45:59 -0300
commitbba9bf97d03596b89972cc77390311b9e9472688 (patch)
treeaa40965478ac88682a2e2ff9f032e42346a471c8 /ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
parent0254a84f90ea03037be15b8fd1f9e0a4be5577e9 (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.cs506
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);
});
}