From 873a7cd112d2f1cc84b628344c0ecc426573f636 Mon Sep 17 00:00:00 2001
From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>
Date: Sat, 24 Mar 2018 02:06:05 +0100
Subject: [PATCH] Add Cls Instruction. (#67)

* Update AInstEmitAlu.cs

* Update ASoftFallback.cs

* Update AOpCodeTable.cs
---
 ChocolArm64/AOpCodeTable.cs              |  7 ++++---
 ChocolArm64/Instruction/AInstEmitAlu.cs  | 20 +++++++++++++++++++-
 ChocolArm64/Instruction/ASoftFallback.cs | 10 +++++++++-
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
index ea16ec00..395929d0 100644
--- a/ChocolArm64/AOpCodeTable.cs
+++ b/ChocolArm64/AOpCodeTable.cs
@@ -8,7 +8,7 @@ namespace ChocolArm64
     {
         static AOpCodeTable()
         {
- #region "OpCode Table"
+#region "OpCode Table"
             //Integer
             Set("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc,           typeof(AOpCodeAluRs));
             Set("x0111010000xxxxx000000xxxxxxxxxx", AInstEmit.Adcs,          typeof(AOpCodeAluRs));
@@ -41,6 +41,7 @@ namespace ChocolArm64
             Set("x1111010010xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ccmp,          typeof(AOpCodeCcmpImm));
             Set("x1111010010xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ccmp,          typeof(AOpCodeCcmpReg));
             Set("11010101000000110011xxxx01011111", AInstEmit.Clrex,         typeof(AOpCodeSystem));
+            Set("x101101011000000000101xxxxxxxxxx", AInstEmit.Cls,           typeof(AOpCodeAlu));
             Set("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz,           typeof(AOpCodeAlu));
             Set("x0011010110xxxxx010000xxxxxxxxxx", AInstEmit.Crc32b,        typeof(AOpCodeAluRs));
             Set("x0011010110xxxxx010001xxxxxxxxxx", AInstEmit.Crc32h,        typeof(AOpCodeAluRs));
@@ -68,7 +69,7 @@ namespace ChocolArm64
             Set("xx111000010xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr,           typeof(AOpCodeMemImm));
             Set("xx11100101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr,           typeof(AOpCodeMemImm));
             Set("xx111000011xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr,           typeof(AOpCodeMemReg));
-            Set("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit,        typeof(AOpCodeMemLit));            
+            Set("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit,        typeof(AOpCodeMemLit));
             Set("0x1110001x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs,          typeof(AOpCodeMemImm));
             Set("0x1110011xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs,          typeof(AOpCodeMemImm));
             Set("10111000100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs,          typeof(AOpCodeMemImm));
@@ -442,4 +443,4 @@ namespace ChocolArm64
             return AInst.Undefined;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/ChocolArm64/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs
index 57020364..bacbfc9e 100644
--- a/ChocolArm64/Instruction/AInstEmitAlu.cs
+++ b/ChocolArm64/Instruction/AInstEmitAlu.cs
@@ -100,6 +100,24 @@ namespace ChocolArm64.Instruction
             EmitDataStore(Context, SetFlags);
         }
 
+        public static void Cls(AILEmitterCtx Context)
+        {
+            AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
+
+            Context.EmitLdintzr(Op.Rn);
+
+            if (Op.RegisterSize == ARegisterSize.Int32)
+            {
+                ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingSigns32));
+            }
+            else
+            {
+                ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingSigns64));
+            }
+
+            Context.EmitStintzr(Op.Rd);
+        }
+
         public static void Clz(AILEmitterCtx Context)
         {
             AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp;
@@ -383,4 +401,4 @@ namespace ChocolArm64.Instruction
             Context.EmitStflg((int)APState.CBit);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs
index 705ca4a2..c0594413 100644
--- a/ChocolArm64/Instruction/ASoftFallback.cs
+++ b/ChocolArm64/Instruction/ASoftFallback.cs
@@ -20,6 +20,14 @@ namespace ChocolArm64.Instruction
             Context.EmitCall(typeof(ASoftFallback), MthdName);
         }
 
+        public static uint  CountLeadingSigns32(uint Value)  => (uint)CountLeadingSigns(Value, 32);
+        public static ulong CountLeadingSigns64(ulong Value) => (ulong)CountLeadingSigns(Value, 64);
+
+        private static ulong CountLeadingSigns(ulong Value, int Size)
+        {
+            return CountLeadingZeros((Value >> 1) ^ Value, Size - 1);
+        }
+
         public static uint  CountLeadingZeros32(uint Value)  => (uint)CountLeadingZeros(Value, 32);
         public static ulong CountLeadingZeros64(ulong Value) => (ulong)CountLeadingZeros(Value, 64);
 
@@ -398,4 +406,4 @@ namespace ChocolArm64.Instruction
             throw new ArgumentOutOfRangeException(nameof(Size));
         }
     }
-}
\ No newline at end of file
+}