From 31b35a9645524ce25f4bcbcd5f0df8b9784e6b52 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 24 Feb 2018 18:47:08 -0300
Subject: [PATCH] Add FABD (scalar), ADCS, SBCS instructions, update config
 with better default control mappings, update readme with the new mappings

---
 ChocolArm64/AOpCodeTable.cs                   |  3 ++
 ChocolArm64/ATranslator.cs                    |  6 +--
 ChocolArm64/Instruction/AInstEmitAlu.cs       | 30 +++++++++++--
 ChocolArm64/Instruction/AInstEmitAluHelper.cs | 19 ++++++++
 .../Instruction/AInstEmitSimdArithmetic.cs    | 45 +++++++++++--------
 .../Instruction/AInstEmitSimdHelper.cs        | 32 ++++++-------
 README.md                                     | 44 +++++++++++-------
 Ryujinx/Ryujinx.conf                          | 40 ++++++++---------
 8 files changed, 138 insertions(+), 81 deletions(-)

diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
index 71a944cf87..14ca231baf 100644
--- a/ChocolArm64/AOpCodeTable.cs
+++ b/ChocolArm64/AOpCodeTable.cs
@@ -11,6 +11,7 @@ namespace ChocolArm64
  #region "OpCode Table"
             //Integer
             Set("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc,           typeof(AOpCodeAluRs));
+            Set("x0111010000xxxxx000000xxxxxxxxxx", AInstEmit.Adcs,          typeof(AOpCodeAluRs));
             Set("x00100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add,           typeof(AOpCodeAluImm));
             Set("x0001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add,           typeof(AOpCodeAluRs));
             Set("x0001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add,           typeof(AOpCodeAluRx));
@@ -90,6 +91,7 @@ namespace ChocolArm64
             Set("1101101011000000000011xxxxxxxxxx", AInstEmit.Rev64,         typeof(AOpCodeAlu));
             Set("x0011010110xxxxx001011xxxxxxxxxx", AInstEmit.Rorv,          typeof(AOpCodeAluRs));
             Set("x1011010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbc,           typeof(AOpCodeAluRs));
+            Set("x1111010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbcs,          typeof(AOpCodeAluRs));
             Set("x00100110xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sbfm,          typeof(AOpCodeBfm));
             Set("x0011010110xxxxx000011xxxxxxxxxx", AInstEmit.Sdiv,          typeof(AOpCodeAluRs));
             Set("10011011001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smaddl,        typeof(AOpCodeMul));
@@ -145,6 +147,7 @@ namespace ChocolArm64
             Set("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S,         typeof(AOpCodeSimdIns));
             Set("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V,         typeof(AOpCodeSimdIns));
             Set("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V,         typeof(AOpCodeSimdReg));
+            Set("011111101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fabd_S,        typeof(AOpCodeSimdReg));
             Set("000111100x100000110000xxxxxxxxxx", AInstEmit.Fabs_S,        typeof(AOpCodeSimd));
             Set("000111100x1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S,        typeof(AOpCodeSimdReg));
             Set("0>0011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V,        typeof(AOpCodeSimdReg));
diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs
index 04cef44f12..96bbc89ead 100644
--- a/ChocolArm64/ATranslator.cs
+++ b/ChocolArm64/ATranslator.cs
@@ -6,7 +6,7 @@ using System.Reflection.Emit;
 
 namespace ChocolArm64
 {
-    public class ATranslator
+    class ATranslator
     {
         public AThread Thread { get; private set; }
 
@@ -41,7 +41,7 @@ namespace ChocolArm64
             while (Position != 0 && KeepRunning);
         }
 
-        internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
+        public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
         {
             if (OpCode.Emitter != AInstEmit.Bl)
             {
@@ -53,7 +53,7 @@ namespace ChocolArm64
             return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub);
         }
 
-        internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
+        public bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
         {
             return CachedSubs.TryGetValue(Position, out Sub);
         }
diff --git a/ChocolArm64/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs
index 72903f5b32..71d9a66077 100644
--- a/ChocolArm64/Instruction/AInstEmitAlu.cs
+++ b/ChocolArm64/Instruction/AInstEmitAlu.cs
@@ -11,7 +11,10 @@ namespace ChocolArm64.Instruction
 {
     static partial class AInstEmit
     {
-        public static void Adc(AILEmitterCtx Context)
+        public static void Adc(AILEmitterCtx Context)  => EmitAdc(Context, false);
+        public static void Adcs(AILEmitterCtx Context) => EmitAdc(Context, true);
+
+        private static void EmitAdc(AILEmitterCtx Context, bool SetFlags)
         {
             EmitDataLoadOpers(Context);
 
@@ -27,11 +30,19 @@ namespace ChocolArm64.Instruction
 
             if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
             {
-                Context.Emit(OpCodes.Conv_I8);
+                Context.Emit(OpCodes.Conv_U8);
             }
 
             Context.Emit(OpCodes.Add);
 
+            if (SetFlags)
+            {
+                Context.EmitZNFlagCheck();
+
+                EmitAddsCCheck(Context);
+                EmitAddsVCheck(Context);
+            }
+
             EmitDataStore(Context);
         }
 
@@ -145,7 +156,10 @@ namespace ChocolArm64.Instruction
         public static void Lslv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shl);
         public static void Lsrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr_Un);
 
-        public static void Sbc(AILEmitterCtx Context)
+        public static void Sbc(AILEmitterCtx Context)  => EmitSbc(Context, false);
+        public static void Sbcs(AILEmitterCtx Context) => EmitSbc(Context, true);
+
+        private static void EmitSbc(AILEmitterCtx Context, bool SetFlags)
         {
             EmitDataLoadOpers(Context);
 
@@ -165,11 +179,19 @@ namespace ChocolArm64.Instruction
 
             if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
             {
-                Context.Emit(OpCodes.Conv_I8);
+                Context.Emit(OpCodes.Conv_U8);
             }
 
             Context.Emit(OpCodes.Sub);
 
+            if (SetFlags)
+            {
+                Context.EmitZNFlagCheck();
+
+                EmitSbcsCCheck(Context);
+                EmitSubsVCheck(Context);
+            }
+
             EmitDataStore(Context);
         }
 
diff --git a/ChocolArm64/Instruction/AInstEmitAluHelper.cs b/ChocolArm64/Instruction/AInstEmitAluHelper.cs
index e848742d0b..b2ea92a65c 100644
--- a/ChocolArm64/Instruction/AInstEmitAluHelper.cs
+++ b/ChocolArm64/Instruction/AInstEmitAluHelper.cs
@@ -41,6 +41,25 @@ namespace ChocolArm64.Instruction
             Context.EmitStflg((int)APState.VBit);
         }
 
+        public static void EmitSbcsCCheck(AILEmitterCtx Context)
+        {
+            //C = (Rn == Rm && CIn) || Rn > Rm
+            EmitDataLoadOpers(Context);
+
+            Context.Emit(OpCodes.Ceq);
+
+            Context.EmitLdflg((int)APState.CBit);
+
+            Context.Emit(OpCodes.And);
+
+            EmitDataLoadOpers(Context);
+
+            Context.Emit(OpCodes.Cgt_Un);
+            Context.Emit(OpCodes.Or);
+
+            Context.EmitStflg((int)APState.CBit);
+        }
+
         public static void EmitSubsCCheck(AILEmitterCtx Context)
         {
             //C = Rn == Rm || Rn > Rm = !(Rn < Rm)
diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
index e1fd56e003..e790d67865 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs
@@ -101,6 +101,16 @@ namespace ChocolArm64.Instruction
             }
         }
 
+        public static void Fabd_S(AILEmitterCtx Context)
+        {
+            EmitScalarBinaryOpF(Context, () =>
+            {
+                Context.Emit(OpCodes.Sub);
+
+                EmitUnaryMathCall(Context, nameof(Math.Abs));
+            });
+        }
+
         public static void Fabs_S(AILEmitterCtx Context)
         {
             EmitScalarUnaryOpF(Context, () =>
@@ -269,26 +279,25 @@ namespace ChocolArm64.Instruction
         {
             AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
 
-            EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
-
-            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
-
-            Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
-
-            if (Op.Size == 0)
+            EmitScalarUnaryOpF(Context, () =>
             {
-                ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
-            }
-            else if (Op.Size == 1)
-            {
-                ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
-            }
-            else
-            {
-                throw new InvalidOperationException();
-            }
+                Context.EmitLdarg(ATranslatedSub.StateArgIdx);
 
-            EmitScalarSetF(Context, Op.Rd, Op.Size);
+                Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
+
+                if (Op.Size == 0)
+                {
+                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
+                }
+                else if (Op.Size == 1)
+                {
+                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
+                }
+                else
+                {
+                    throw new InvalidOperationException();
+                }
+            });
         }
 
         public static void Fsqrt_S(AILEmitterCtx Context)
diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
index 20c8be26dc..68ee3d3e4e 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs
@@ -36,20 +36,18 @@ namespace ChocolArm64.Instruction
         {
             IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
 
+            int SizeF = Op.Size & 1;
+
             MethodInfo MthdInfo;
 
-            if (Op.Size == 0)
+            if (SizeF == 0)
             {
                 MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float) });
             }
-            else if (Op.Size == 1)
+            else /* if (SizeF == 1) */
             {
                 MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double) });
             }
-            else
-            {
-                throw new InvalidOperationException();
-            }
 
             Context.EmitCall(MthdInfo);
         }
@@ -58,20 +56,18 @@ namespace ChocolArm64.Instruction
         {
             IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
 
+            int SizeF = Op.Size & 1;
+
             MethodInfo MthdInfo;
 
-            if (Op.Size == 0)
+            if (SizeF == 0)
             {
                 MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float), typeof(float) });
             }
-            else if (Op.Size == 1)
+            else /* if (SizeF == 1) */
             {
                 MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double), typeof(double) });
             }
-            else
-            {
-                throw new InvalidOperationException();
-            }
 
             Context.EmitCall(MthdInfo);
         }
@@ -80,28 +76,26 @@ namespace ChocolArm64.Instruction
         {
             IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
 
+            int SizeF = Op.Size & 1;
+
             Context.EmitLdc_I4((int)RoundMode);
 
             MethodInfo MthdInfo;
 
             Type[] Types = new Type[] { null, typeof(MidpointRounding) };
 
-            Types[0] = Op.Size == 0
+            Types[0] = SizeF == 0
                 ? typeof(float)
                 : typeof(double);
 
-            if (Op.Size == 0)
+            if (SizeF == 0)
             {
                 MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
             }
-            else if (Op.Size == 1)
+            else /* if (SizeF == 1) */
             {
                 MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
             }
-            else
-            {
-                throw new InvalidOperationException();
-            }
 
             Context.EmitCall(MthdInfo);
         }
diff --git a/README.md b/README.md
index d2199244d3..6a24112796 100644
--- a/README.md
+++ b/README.md
@@ -18,23 +18,33 @@ Or just drag'n'drop the *.NRO / *.NSO or the game folder on the executable if yo
 https://openal.org/downloads/OpenAL11CoreSDK.zip
 
  - Keyboard Input is partially supported:
-   - Arrows.
-   - Enter > "Start" & Tab > "Select"
-   - Qwerty: 
-     - A > "A" (QWERTY) / Q > "A" (AZERTY)
-     - S > "B"
-     - Z > "X" (QWERTY) / W > "X" (AZERTY)
-     - X > "Y"
-     - Key_Up > "Right Stick Up"
-     - Key_Down > "Right Stick Down"
-     - Key_Left > "Right Stick Left"
-     - Key_Right > "Right Stick Right"
-     - I > "Left Stick Up"
-     - K > "Left Stick Down"
-     - J > "Left Stick Left"
-     - L > "Left Stick Right"
-     - Tab > "Minus"
-     - Enter > "Plus"
+   - Left Joycon:
+	 - Stick Up = W
+	 - Stick Down = S
+	 - Stick Left = A
+	 - Stick Right = D
+	 - Stick Button = F
+	 - DPad Up = Up
+	 - DPad Down = Down
+	 - DPad Left = Left
+	 - DPad Right = Right
+	 - Minus = -
+	 - L = E
+	 - ZL = Q
+
+   - Right Joycon:
+	 - Stick Up = I
+	 - Stick Down = K
+	 - Stick Left = J
+	 - Stick Right = L
+	 - Stick Button = H
+	 - A = Z
+	 - B = X
+	 - X = C
+	 - Y = V
+	 - Plus = +
+	 - R = U
+	 - ZR = O
 
  - Config File: `Ryujinx.conf` should be present in executable folder.
    For more informations [you can go here](CONFIG.md).
diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf
index 8f791df311..7b9af87acf 100644
--- a/Ryujinx/Ryujinx.conf
+++ b/Ryujinx/Ryujinx.conf
@@ -20,28 +20,28 @@ Logging_Enable_Fatal = true
 Logging_Enable_LogFile = false
 
 #https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs
-Controls_Left_FakeJoycon_Stick_Up = 91
-Controls_Left_FakeJoycon_Stick_Down = 93
-Controls_Left_FakeJoycon_Stick_Left = 92
-Controls_Left_FakeJoycon_Stick_Right = 94
-Controls_Left_FakeJoycon_Stick_Button = 0
+Controls_Left_FakeJoycon_Stick_Up = 105
+Controls_Left_FakeJoycon_Stick_Down = 101
+Controls_Left_FakeJoycon_Stick_Left = 83
+Controls_Left_FakeJoycon_Stick_Right = 86
+Controls_Left_FakeJoycon_Stick_Button = 88
 Controls_Left_FakeJoycon_DPad_Up = 45
 Controls_Left_FakeJoycon_DPad_Down = 46
 Controls_Left_FakeJoycon_DPad_Left = 47
 Controls_Left_FakeJoycon_DPad_Right = 48
-Controls_Left_FakeJoycon_Button_Minus = 52
-Controls_Left_FakeJoycon_Button_L = 0
-Controls_Left_FakeJoycon_Button_ZL = 0
+Controls_Left_FakeJoycon_Button_Minus = 120
+Controls_Left_FakeJoycon_Button_L = 87
+Controls_Left_FakeJoycon_Button_ZL = 99
 
-Controls_Right_FakeJoycon_Stick_Up = 45
-Controls_Right_FakeJoycon_Stick_Down = 46
-Controls_Right_FakeJoycon_Stick_Left = 47
-Controls_Right_FakeJoycon_Stick_Right = 48
-Controls_Right_FakeJoycon_Stick_Button = 0
-Controls_Right_FakeJoycon_Button_A = 83
-Controls_Right_FakeJoycon_Button_B = 101
-Controls_Right_FakeJoycon_Button_X = 106
-Controls_Right_FakeJoycon_Button_Y = 108
-Controls_Right_FakeJoycon_Button_Plus = 49
-Controls_Right_FakeJoycon_Button_R = 0
-Controls_Right_FakeJoycon_Button_ZR = 0
+Controls_Right_FakeJoycon_Stick_Up = 91
+Controls_Right_FakeJoycon_Stick_Down = 93
+Controls_Right_FakeJoycon_Stick_Left = 92
+Controls_Right_FakeJoycon_Stick_Right = 94
+Controls_Right_FakeJoycon_Stick_Button = 90
+Controls_Right_FakeJoycon_Button_A = 108
+Controls_Right_FakeJoycon_Button_B = 106
+Controls_Right_FakeJoycon_Button_X = 85
+Controls_Right_FakeJoycon_Button_Y = 104
+Controls_Right_FakeJoycon_Button_Plus = 121
+Controls_Right_FakeJoycon_Button_R = 103
+Controls_Right_FakeJoycon_Button_ZR = 97