Implement fixed-point variant of the UCVTF and SCVTF instructions (#578)

* Add fixed-point variant of the UCVTF instruction

* Change encoding of some fixed-point instructions to not allow invalid encodings

* Fix Fcvtzu_Gp_Fixed encoding

* Add SCVTF (fixed-point GP to Scalar) instruction

* Simplify *Fixed encodings
This commit is contained in:
gdkchan 2019-02-23 20:52:48 -03:00 committed by GitHub
parent 0be1f5b45a
commit 5ba8c8bedc
3 changed files with 76 additions and 47 deletions

View file

@ -8,18 +8,9 @@ namespace ChocolArm64.Decoders
public OpCodeSimdCvt64(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
//TODO:
//Und of Fixed Point variants.
int scale = (opCode >> 10) & 0x3f;
int sf = (opCode >> 31) & 0x1;
/*if (Type != SF && !(Type == 2 && SF == 1))
{
Emitter = AInstEmit.Und;
return;
}*/
FBits = 64 - scale;
RegisterSize = sf != 0

View file

@ -244,7 +244,7 @@ namespace ChocolArm64.Instructions
public static void Fcvtzs_Gp_Fixed(ILEmitterCtx context)
{
EmitFcvtzs_Gp_Fix(context);
EmitFcvtzs_Gp_Fixed(context);
}
public static void Fcvtzs_S(ILEmitterCtx context)
@ -264,7 +264,7 @@ namespace ChocolArm64.Instructions
public static void Fcvtzu_Gp_Fixed(ILEmitterCtx context)
{
EmitFcvtzu_Gp_Fix(context);
EmitFcvtzu_Gp_Fixed(context);
}
public static void Fcvtzu_S(ILEmitterCtx context)
@ -293,6 +293,24 @@ namespace ChocolArm64.Instructions
EmitScalarSetF(context, op.Rd, op.Size);
}
public static void Scvtf_Gp_Fixed(ILEmitterCtx context)
{
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
context.EmitLdintzr(op.Rn);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
context.Emit(OpCodes.Conv_I4);
}
EmitFloatCast(context, op.Size);
EmitI2fFBitsMul(context, op.Size, op.FBits);
EmitScalarSetF(context, op.Rd, op.Size);
}
public static void Scvtf_S(ILEmitterCtx context)
{
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
@ -349,6 +367,26 @@ namespace ChocolArm64.Instructions
EmitScalarSetF(context, op.Rd, op.Size);
}
public static void Ucvtf_Gp_Fixed(ILEmitterCtx context)
{
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
context.EmitLdintzr(op.Rn);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
context.Emit(OpCodes.Conv_U4);
}
context.Emit(OpCodes.Conv_R_Un);
EmitFloatCast(context, op.Size);
EmitI2fFBitsMul(context, op.Size, op.FBits);
EmitScalarSetF(context, op.Rd, op.Size);
}
public static void Ucvtf_S(ILEmitterCtx context)
{
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
@ -367,32 +405,6 @@ namespace ChocolArm64.Instructions
EmitVectorCvtf(context, signed: false);
}
private static int GetFBits(ILEmitterCtx context)
{
if (context.CurrOp is OpCodeSimdShImm64 op)
{
return GetImmShr(op);
}
return 0;
}
private static void EmitFloatCast(ILEmitterCtx context, int size)
{
if (size == 0)
{
context.Emit(OpCodes.Conv_R4);
}
else if (size == 1)
{
context.Emit(OpCodes.Conv_R8);
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
private static void EmitFcvtn(ILEmitterCtx context, bool signed, bool scalar)
{
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
@ -476,17 +488,17 @@ namespace ChocolArm64.Instructions
context.EmitStintzr(op.Rd);
}
private static void EmitFcvtzs_Gp_Fix(ILEmitterCtx context)
private static void EmitFcvtzs_Gp_Fixed(ILEmitterCtx context)
{
EmitFcvtz__Gp_Fix(context, true);
EmitFcvtz__Gp_Fixed(context, true);
}
private static void EmitFcvtzu_Gp_Fix(ILEmitterCtx context)
private static void EmitFcvtzu_Gp_Fixed(ILEmitterCtx context)
{
EmitFcvtz__Gp_Fix(context, false);
EmitFcvtz__Gp_Fixed(context, false);
}
private static void EmitFcvtz__Gp_Fix(ILEmitterCtx context, bool signed)
private static void EmitFcvtz__Gp_Fixed(ILEmitterCtx context, bool signed)
{
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
@ -530,9 +542,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Conv_R_Un);
}
context.Emit(sizeF == 0
? OpCodes.Conv_R4
: OpCodes.Conv_R8);
EmitFloatCast(context, sizeF);
EmitI2fFBitsMul(context, sizeF, fBits);
@ -644,6 +654,32 @@ namespace ChocolArm64.Instructions
}
}
private static int GetFBits(ILEmitterCtx context)
{
if (context.CurrOp is OpCodeSimdShImm64 op)
{
return GetImmShr(op);
}
return 0;
}
private static void EmitFloatCast(ILEmitterCtx context, int size)
{
if (size == 0)
{
context.Emit(OpCodes.Conv_R4);
}
else if (size == 1)
{
context.Emit(OpCodes.Conv_R8);
}
else
{
throw new ArgumentOutOfRangeException(nameof(size));
}
}
private static void EmitScalarFcvts(ILEmitterCtx context, int size, int fBits)
{
if (size < 0 || size > 1)

View file

@ -310,12 +310,12 @@ namespace ChocolArm64
SetA64("x00111100x101000000000xxxxxxxxxx", InstEmit.Fcvtps_Gp, typeof(OpCodeSimdCvt64));
SetA64("x00111100x101001000000xxxxxxxxxx", InstEmit.Fcvtpu_Gp, typeof(OpCodeSimdCvt64));
SetA64("x00111100x111000000000xxxxxxxxxx", InstEmit.Fcvtzs_Gp, typeof(OpCodeSimdCvt64));
SetA64("x00111100x011000xxxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64(">00111100x011000>xxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("010111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzs_S, typeof(OpCodeSimd64));
SetA64("0>0011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimd64));
SetA64("0x0011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimdShImm64));
SetA64("x00111100x111001000000xxxxxxxxxx", InstEmit.Fcvtzu_Gp, typeof(OpCodeSimdCvt64));
SetA64("x00111100x011001xxxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64(">00111100x011001>xxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("011111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzu_S, typeof(OpCodeSimd64));
SetA64("0>1011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimd64));
SetA64("0x1011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimdShImm64));
@ -434,6 +434,7 @@ namespace ChocolArm64
SetA64("0x001110<<100000001010xxxxxxxxxx", InstEmit.Saddlp_V, typeof(OpCodeSimd64));
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstEmit.Saddw_V, typeof(OpCodeSimdReg64));
SetA64("x00111100x100010000000xxxxxxxxxx", InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt64));
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("010111100x100001110110xxxxxxxxxx", InstEmit.Scvtf_S, typeof(OpCodeSimd64));
SetA64("0>0011100<100001110110xxxxxxxxxx", InstEmit.Scvtf_V, typeof(OpCodeSimd64));
SetA64("01011110000xxxxx000000xxxxxxxxxx", InstEmit.Sha1c_V, typeof(OpCodeSimdReg64));
@ -542,6 +543,7 @@ namespace ChocolArm64
SetA64("01101110<<110000001110xxxxxxxxxx", InstEmit.Uaddlv_V, typeof(OpCodeSimd64));
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstEmit.Uaddw_V, typeof(OpCodeSimdReg64));
SetA64("x00111100x100011000000xxxxxxxxxx", InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt64));
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("011111100x100001110110xxxxxxxxxx", InstEmit.Ucvtf_S, typeof(OpCodeSimd64));
SetA64("0>1011100<100001110110xxxxxxxxxx", InstEmit.Ucvtf_V, typeof(OpCodeSimd64));
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstEmit.Uhadd_V, typeof(OpCodeSimdReg64));