From 9679896b9471afdebf860c016d3fd360b9af7f80 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 23 Feb 2019 20:52:48 -0300 Subject: [PATCH] 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 --- ChocolArm64/Decoders/OpCodeSimdCvt64.cs | 9 -- ChocolArm64/Instructions/InstEmitSimdCvt.cs | 108 +++++++++++++------- ChocolArm64/OpCodeTable.cs | 6 +- 3 files changed, 76 insertions(+), 47 deletions(-) diff --git a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs index eacd5940..3181a85a 100644 --- a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs +++ b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs @@ -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 diff --git a/ChocolArm64/Instructions/InstEmitSimdCvt.cs b/ChocolArm64/Instructions/InstEmitSimdCvt.cs index 2eac3194..11105d89 100644 --- a/ChocolArm64/Instructions/InstEmitSimdCvt.cs +++ b/ChocolArm64/Instructions/InstEmitSimdCvt.cs @@ -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) diff --git a/ChocolArm64/OpCodeTable.cs b/ChocolArm64/OpCodeTable.cs index 3a8d3948..9fdda87b 100644 --- a/ChocolArm64/OpCodeTable.cs +++ b/ChocolArm64/OpCodeTable.cs @@ -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));