Add FCVTAS and FCVTAU instructions

This commit is contained in:
gdkchan 2018-02-17 18:59:37 -03:00
parent ebddc40550
commit 595e7ee588
4 changed files with 68 additions and 24 deletions

View file

@ -151,6 +151,8 @@ namespace ChocolArm64
Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond)); Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
Set("00011110xx10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd)); Set("00011110xx10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd));
Set("x0011110xx100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt));
Set("x0011110xx100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt));
Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt));
Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt));
Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt));

View file

@ -222,30 +222,7 @@ namespace ChocolArm64.Instruction
EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
Context.EmitLdc_I4((int)MidpointRounding.AwayFromZero); EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
MethodInfo MthdInfo;
Type[] Types = new Type[] { null, typeof(MidpointRounding) };
Types[0] = Op.Size == 0
? typeof(float)
: typeof(double);
if (Op.Size == 0)
{
MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
}
else if (Op.Size == 1)
{
MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
}
else
{
throw new InvalidOperationException();
}
Context.EmitCall(MthdInfo);
EmitScalarSetF(Context, Op.Rd, Op.Size); EmitScalarSetF(Context, Op.Rd, Op.Size);
} }

View file

@ -21,6 +21,16 @@ namespace ChocolArm64.Instruction
EmitScalarSetF(Context, Op.Rd, Op.Opc); EmitScalarSetF(Context, Op.Rd, Op.Opc);
} }
public static void Fcvtas_Gp(AILEmitterCtx Context)
{
Fcvta__Gp(Context, Signed: true);
}
public static void Fcvtau_Gp(AILEmitterCtx Context)
{
Fcvta__Gp(Context, Signed: false);
}
public static void Fcvtms_Gp(AILEmitterCtx Context) public static void Fcvtms_Gp(AILEmitterCtx Context)
{ {
EmitFcvt_s_Gp(Context, nameof(Math.Floor)); EmitFcvt_s_Gp(Context, nameof(Math.Floor));
@ -155,6 +165,31 @@ namespace ChocolArm64.Instruction
} }
} }
private static void Fcvta__Gp(AILEmitterCtx Context, bool Signed)
{
AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
if (Signed)
{
EmitScalarFcvts(Context, Op.Size, 0);
}
else
{
EmitScalarFcvtu(Context, Op.Size, 0);
}
if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
{
Context.Emit(OpCodes.Conv_U8);
}
Context.EmitStintzr(Op.Rd);
}
private static void EmitFcvt_s_Gp(AILEmitterCtx Context, string Name) private static void EmitFcvt_s_Gp(AILEmitterCtx Context, string Name)
{ {
AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

View file

@ -76,6 +76,36 @@ namespace ChocolArm64.Instruction
Context.EmitCall(MthdInfo); Context.EmitCall(MthdInfo);
} }
public static void EmitRoundMathCall(AILEmitterCtx Context, MidpointRounding RoundMode)
{
IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
Context.EmitLdc_I4((int)RoundMode);
MethodInfo MthdInfo;
Type[] Types = new Type[] { null, typeof(MidpointRounding) };
Types[0] = Op.Size == 0
? typeof(float)
: typeof(double);
if (Op.Size == 0)
{
MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
}
else if (Op.Size == 1)
{
MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
}
else
{
throw new InvalidOperationException();
}
Context.EmitCall(MthdInfo);
}
public static void EmitScalarUnaryOpSx(AILEmitterCtx Context, Action Emit) public static void EmitScalarUnaryOpSx(AILEmitterCtx Context, Action Emit)
{ {
EmitScalarOp(Context, Emit, OperFlags.Rn, true); EmitScalarOp(Context, Emit, OperFlags.Rn, true);