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 7ed2b4cc39
commit 9679896b94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 47 deletions

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)