mirror of
https://github.com/Ryujinx/ChocolArm64.git
synced 2024-12-22 19:35:38 +00:00
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
This commit is contained in:
parent
88af0e2966
commit
f6fa73b965
|
@ -301,6 +301,8 @@ namespace ChocolArm64
|
|||
SetA64("010111111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Se, typeof(AOpCodeSimdRegElemF));
|
||||
SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
|
||||
SetA64("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElemF));
|
||||
SetA64("010111100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmulx_S, typeof(AOpCodeSimdReg));
|
||||
SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmulx_V, typeof(AOpCodeSimdReg));
|
||||
SetA64("000111100x100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimd));
|
||||
SetA64("0>1011101<100000111110xxxxxxxxxx", AInstEmit.Fneg_V, typeof(AOpCodeSimd));
|
||||
SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fnmadd_S, typeof(AOpCodeSimdReg));
|
||||
|
@ -310,6 +312,7 @@ namespace ChocolArm64
|
|||
SetA64("0>0011101<100001110110xxxxxxxxxx", AInstEmit.Frecpe_V, typeof(AOpCodeSimd));
|
||||
SetA64("010111100x1xxxxx111111xxxxxxxxxx", AInstEmit.Frecps_S, typeof(AOpCodeSimdReg));
|
||||
SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Frecps_V, typeof(AOpCodeSimdReg));
|
||||
SetA64("010111101x100001111110xxxxxxxxxx", AInstEmit.Frecpx_S, typeof(AOpCodeSimd));
|
||||
SetA64("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
||||
SetA64("0>1011100<100001100010xxxxxxxxxx", AInstEmit.Frinta_V, typeof(AOpCodeSimd));
|
||||
SetA64("000111100x100111110000xxxxxxxxxx", AInstEmit.Frinti_S, typeof(AOpCodeSimd));
|
||||
|
@ -327,6 +330,7 @@ namespace ChocolArm64
|
|||
SetA64("010111101x1xxxxx111111xxxxxxxxxx", AInstEmit.Frsqrts_S, typeof(AOpCodeSimdReg));
|
||||
SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", AInstEmit.Frsqrts_V, typeof(AOpCodeSimdReg));
|
||||
SetA64("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
|
||||
SetA64("0>1011101<100001111110xxxxxxxxxx", AInstEmit.Fsqrt_V, typeof(AOpCodeSimd));
|
||||
SetA64("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
|
||||
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
||||
SetA64("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
||||
|
|
|
@ -2,6 +2,8 @@ using System.Runtime.Intrinsics.X86;
|
|||
|
||||
public static class AOptimizations
|
||||
{
|
||||
internal static bool FastFP = true;
|
||||
|
||||
private static bool UseAllSseIfAvailable = true;
|
||||
|
||||
private static bool UseSseIfAvailable = true;
|
||||
|
@ -13,4 +15,4 @@ public static class AOptimizations
|
|||
internal static bool UseSse2 = (UseAllSseIfAvailable && UseSse2IfAvailable) && Sse2.IsSupported;
|
||||
internal static bool UseSse41 = (UseAllSseIfAvailable && UseSse41IfAvailable) && Sse41.IsSupported;
|
||||
internal static bool UseSse42 = (UseAllSseIfAvailable && UseSse42IfAvailable) && Sse42.IsSupported;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
Type[] Types = new Type[] { typeof(float) };
|
||||
|
||||
Context.EmitLdc_R4(0.5f);
|
||||
Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetScalarVector128), Types));
|
||||
|
||||
Context.EmitLdc_R4(3f);
|
||||
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.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
|
||||
{
|
||||
EmitScalarBinaryOpF(Context, () =>
|
||||
{
|
||||
EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Frsqrts_V(AILEmitterCtx Context)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
int Bytes = Op.GetBitsCount() >> 3;
|
||||
|
||||
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
||||
if (AOptimizations.FastFP && AOptimizations.UseSse2)
|
||||
{
|
||||
EmitFrsqrts(Context, Index, Scalar: false);
|
||||
}
|
||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||
|
||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
Type[] Types = new Type[] { typeof(float) };
|
||||
|
||||
Context.EmitLdc_R4(0.5f);
|
||||
Context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.SetAllVector128), Types));
|
||||
|
||||
Context.EmitLdc_R4(3f);
|
||||
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.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
|
||||
{
|
||||
EmitVectorZeroUpper(Context, Op.Rd);
|
||||
EmitVectorBinaryOpF(Context, () =>
|
||||
{
|
||||
EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPRSqrtStepFused));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitFrsqrts(AILEmitterCtx Context, int Index, bool Scalar)
|
||||
{
|
||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
Context.EmitLdc_R4(3);
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
Context.EmitLdc_R8(3);
|
||||
}
|
||||
|
||||
EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
|
||||
EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
|
||||
|
||||
Context.Emit(OpCodes.Mul);
|
||||
Context.Emit(OpCodes.Sub);
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
Context.EmitLdc_R4(0.5f);
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
Context.EmitLdc_R8(0.5);
|
||||
}
|
||||
|
||||
Context.Emit(OpCodes.Mul);
|
||||
|
||||
if (Scalar)
|
||||
{
|
||||
EmitVectorZeroAll(Context, Op.Rd);
|
||||
}
|
||||
|
||||
EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
|
||||
}
|
||||
|
||||
public static void Fsqrt_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarUnaryOpF(Context, () =>
|
||||
if (AOptimizations.FastFP && AOptimizations.UseSse
|
||||
&& AOptimizations.UseSse2)
|
||||
{
|
||||
EmitUnaryMathCall(Context, nameof(Math.Sqrt));
|
||||
});
|
||||
EmitScalarSseOrSse2OpF(Context, nameof(Sse.SqrtScalar));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF(Context, () =>
|
||||
{
|
||||
EmitSoftFloatCall(Context, nameof(ASoftFloat_32.FPSqrt));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fsqrt_V(AILEmitterCtx Context)
|
||||
{
|
||||
if (AOptimizations.FastFP && AOptimizations.UseSse
|
||||
&& AOptimizations.UseSse2)
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -306,25 +306,19 @@ namespace ChocolArm64.Instruction
|
|||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
Context.EmitLdc_I4((int)RoundMode);
|
||||
|
||||
MethodInfo MthdInfo;
|
||||
|
||||
Type[] Types = new Type[] { null, typeof(MidpointRounding) };
|
||||
|
||||
Types[0] = SizeF == 0
|
||||
? typeof(float)
|
||||
: typeof(double);
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
|
||||
MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), new Type[] { typeof(float), typeof(MidpointRounding) });
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
|
||||
MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
}
|
||||
|
||||
Context.EmitLdc_I4((int)RoundMode);
|
||||
|
||||
Context.EmitCall(MthdInfo);
|
||||
}
|
||||
|
||||
|
@ -348,24 +342,17 @@ namespace ChocolArm64.Instruction
|
|||
Context.EmitCall(MthdInfo);
|
||||
}
|
||||
|
||||
public static void EmitBinarySoftFloatCall(AILEmitterCtx Context, string Name)
|
||||
public static void EmitSoftFloatCall(AILEmitterCtx Context, string Name)
|
||||
{
|
||||
IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
Type Type = (Op.Size & 1) == 0
|
||||
? typeof(ASoftFloat_32)
|
||||
: typeof(ASoftFloat_64);
|
||||
|
||||
MethodInfo MthdInfo;
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
MthdInfo = typeof(ASoftFloat).GetMethod(Name, new Type[] { typeof(float), typeof(float) });
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
MthdInfo = typeof(ASoftFloat).GetMethod(Name, new Type[] { typeof(double), typeof(double) });
|
||||
}
|
||||
|
||||
Context.EmitCall(MthdInfo);
|
||||
Context.EmitCall(Type, Name);
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpByElemF(AILEmitterCtx Context, Action Emit)
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue