Просмотр исходного кода

Add FCVTAS and FCVTAU instructions

gdkchan 8 лет назад
Родитель
Сommit
595e7ee588

+ 2 - 0
Ryujinx/Cpu/AOpCodeTable.cs

@@ -151,6 +151,8 @@ namespace ChocolArm64
             Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S,       typeof(AOpCodeSimdReg));
             Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S,       typeof(AOpCodeSimdFcond));
             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("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp,     typeof(AOpCodeSimdCvt));
             Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp,     typeof(AOpCodeSimdCvt));

+ 1 - 24
Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs

@@ -222,30 +222,7 @@ namespace ChocolArm64.Instruction
 
             EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
 
-            Context.EmitLdc_I4((int)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);
+            EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
 
             EmitScalarSetF(Context, Op.Rd, Op.Size);
         }

+ 35 - 0
Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs

@@ -21,6 +21,16 @@ namespace ChocolArm64.Instruction
             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)
         {
             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)
         {
             AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

+ 30 - 0
Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs

@@ -76,6 +76,36 @@ namespace ChocolArm64.Instruction
             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)
         {
             EmitScalarOp(Context, Emit, OperFlags.Rn, true);