Prechádzať zdrojové kódy

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
gdkchan 7 rokov pred
rodič
commit
9679896b94

+ 0 - 9
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

+ 72 - 36
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,48 +367,42 @@ namespace ChocolArm64.Instructions
             EmitScalarSetF(context, op.Rd, op.Size);
         }
 
-        public static void Ucvtf_S(ILEmitterCtx context)
+        public static void Ucvtf_Gp_Fixed(ILEmitterCtx context)
         {
-            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
 
-            EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
+            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_V(ILEmitterCtx context)
+        public static void Ucvtf_S(ILEmitterCtx context)
         {
-            EmitVectorCvtf(context, signed: false);
-        }
+            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
 
-        private static int GetFBits(ILEmitterCtx context)
-        {
-            if (context.CurrOp is OpCodeSimdShImm64 op)
-            {
-                return GetImmShr(op);
-            }
+            EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
 
-            return 0;
+            context.Emit(OpCodes.Conv_R_Un);
+
+            EmitFloatCast(context, op.Size);
+
+            EmitScalarSetF(context, op.Rd, op.Size);
         }
 
-        private static void EmitFloatCast(ILEmitterCtx context, int size)
+        public static void Ucvtf_V(ILEmitterCtx context)
         {
-            if (size == 0)
-            {
-                context.Emit(OpCodes.Conv_R4);
-            }
-            else if (size == 1)
-            {
-                context.Emit(OpCodes.Conv_R8);
-            }
-            else
-            {
-                throw new ArgumentOutOfRangeException(nameof(size));
-            }
+            EmitVectorCvtf(context, signed: false);
         }
 
         private static void EmitFcvtn(ILEmitterCtx context, bool signed, bool scalar)
@@ -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)

+ 4 - 2
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));