From df3cbadcebe48d40a6b8a8e510d21d452d0e0ab3 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Fri, 6 Apr 2018 10:20:17 -0300
Subject: [PATCH] Fix FRSQRTS and FCM* (scalar) instructions

---
 .../Instruction/AInstEmitSimdArithmetic.cs    | 41 +++++++++++++++----
 ChocolArm64/Instruction/AInstEmitSimdCmp.cs   | 32 ++++++++++-----
 2 files changed, 53 insertions(+), 20 deletions(-)

diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
index 772b7955..bf119a18 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
@@ -512,21 +512,33 @@ namespace ChocolArm64.Instruction
 
         public static void Frsqrts_S(AILEmitterCtx Context)
         {
-            EmitScalarBinaryOpF(Context, () => EmitFrsqrts(Context));
+            EmitFrsqrts(Context, 0, Scalar: true);
         }
 
         public static void Frsqrts_V(AILEmitterCtx Context)
         {
-            EmitVectorBinaryOpF(Context, () => EmitFrsqrts(Context));
-        }
-
-        private static void EmitFrsqrts(AILEmitterCtx Context)
-        {
-            IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
+            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
 
             int SizeF = Op.Size & 1;
 
-            Context.Emit(OpCodes.Mul);
+            int Bytes = Context.CurrOp.GetBitsCount() >> 3;
+
+            for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
+            {
+                EmitFrsqrts(Context, Index, Scalar: false);
+            }
+
+            if (Op.RegisterSize == ARegisterSize.SIMD64)
+            {
+                EmitVectorZeroUpper(Context, Op.Rd);
+            }
+        }
+
+        private static void EmitFrsqrts(AILEmitterCtx Context, int Index, bool Scalar)
+        {
+            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
+
+            int SizeF = Op.Size & 1;
 
             if (SizeF == 0)
             {
@@ -537,7 +549,11 @@ namespace ChocolArm64.Instruction
                 Context.EmitLdc_R8(3);
             }
 
-            Context.Emit(OpCodes.Add);
+            EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
+            EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
+
+            Context.Emit(OpCodes.Mul);
+            Context.Emit(OpCodes.Sub);
 
             if (SizeF == 0)
             {
@@ -549,6 +565,13 @@ namespace ChocolArm64.Instruction
             }
 
             Context.Emit(OpCodes.Mul);
+
+            if (Scalar)
+            {
+                EmitVectorZeroAll(Context, Op.Rd);
+            }
+
+            EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
         }
 
         public static void Fsqrt_S(AILEmitterCtx Context)
diff --git a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
index a71b6d42..f155d7e8 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs
@@ -313,13 +313,7 @@ namespace ChocolArm64.Instruction
 
         private static void EmitScalarFcmp(AILEmitterCtx Context, OpCode ILOp)
         {
-            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
-
-            int SizeF = Op.Size & 1;
-
-            EmitFcmp(Context, ILOp, 0);
-
-            EmitScalarSetF(Context, Op.Rd, SizeF);
+            EmitFcmp(Context, ILOp, 0, Scalar: true);
         }
 
         private static void EmitVectorFcmp(AILEmitterCtx Context, OpCode ILOp)
@@ -332,7 +326,7 @@ namespace ChocolArm64.Instruction
 
             for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
             {
-                EmitFcmp(Context, ILOp, Index);
+                EmitFcmp(Context, ILOp, Index, Scalar: false);
             }
 
             if (Op.RegisterSize == ARegisterSize.SIMD64)
@@ -341,7 +335,7 @@ namespace ChocolArm64.Instruction
             }
         }
 
-        private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index)
+        private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index, bool Scalar)
         {
             AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
 
@@ -369,13 +363,29 @@ namespace ChocolArm64.Instruction
 
             Context.Emit(ILOp, LblTrue);
 
-            EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0);
+            if (Scalar)
+            {
+                EmitVectorZeroAll(Context, Op.Rd);
+            }
+            else
+            {
+                EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0);
+            }
 
             Context.Emit(OpCodes.Br_S, LblEnd);
 
             Context.MarkLabel(LblTrue);
 
-            EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask);
+            if (Scalar)
+            {
+                EmitVectorInsert(Context, Op.Rd, Index, 3, (long)SzMask);
+
+                EmitVectorZeroUpper(Context, Op.Rd);
+            }
+            else
+            {
+                EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask);
+            }
 
             Context.MarkLabel(LblEnd);
         }