From 0f9e3baf39efdfe8a6604a473405764e936a897d Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Dec 2014 01:59:46 -0500
Subject: [PATCH 1/2] armemu: Join SMUAD, SMUSD, and SMLAD

---
 src/core/arm/interpreter/armemu.cpp | 67 ++++++++++++++---------------
 1 file changed, 32 insertions(+), 35 deletions(-)

diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 33ebc79865..967506f459 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -6222,45 +6222,42 @@ L_stm_s_takeabort:
 			return 1;
 		}
         case 0x70:
-            if ((instr & 0xf0d0) == 0xf010) { //smuad //ichfly
-                u8 tar = BITS(16, 19);
-                u8 src1 = BITS(0, 3);
-                u8 src2 = BITS(8, 11);
-                u8 swap = BIT(5);
-                s16 a1 = (state->Reg[src1] & 0xFFFF);
-                s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
-                s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
-                s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
-                state->Reg[tar] = a1*a2 + b1*b2;
-                return 1;
+            // ichfly
+            // SMUAD, SMUSD, SMLAD
+            if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 || (instr & 0xd0) == 0x10) {
+                const u8 rd_idx = BITS(16, 19);
+                const u8 rn_idx = BITS(0, 3);
+                const u8 rm_idx = BITS(8, 11);
+                const bool do_swap = (BIT(5) == 1);
 
-            } else if ((instr & 0xf0d0) == 0xf050) { //smusd
-                u8 tar = BITS(16, 19);
-                u8 src1 = BITS(0, 3);
-                u8 src2 = BITS(8, 11);
-                u8 swap = BIT(5);
-                s16 a1 = (state->Reg[src1] & 0xFFFF);
-                s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
-                s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
-                s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
-                state->Reg[tar] = a1*a2 - b1*b2;
-                return 1;
-            } else if ((instr & 0xd0) == 0x10) { //smlad
-                u8 tar = BITS(16, 19);
-                u8 src1 = BITS(0, 3);
-                u8 src2 = BITS(8, 11);
-                u8 src3 = BITS(12, 15);
-                u8 swap = BIT(5);
+                u32 rm_val = state->Reg[rm_idx];
+                const u32 rn_val = state->Reg[rn_idx];
 
-                u32 a3 = state->Reg[src3];
+                if (do_swap)
+                    rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
 
-                s16 a1 = (state->Reg[src1] & 0xFFFF);
-                s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
-                s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
-                s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
-                state->Reg[tar] = a1*a2 + b1*b2 + a3;
+                const s16 rm_lo = (rm_val & 0xFFFF);
+                const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
+                const s16 rn_lo = (rn_val & 0xFFFF);
+                const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
+
+                // SMUAD
+                if ((instr & 0xf0d0) == 0xf010) {
+                    state->Reg[rd_idx] = (rn_lo * rn_hi) + (rm_lo * rm_hi);
+                }
+                // SMUSD
+                else if ((instr & 0xf0d0) == 0xf050) {
+                    state->Reg[rd_idx] = (rn_lo * rn_hi) - (rm_lo * rm_hi);
+                }
+                // SMLAD
+                else {
+                    const u8 ra_idx = BITS(12, 15);
+                    state->Reg[rd_idx] = (rn_lo * rn_hi) + (rm_lo * rm_hi) + (s32)state->Reg[ra_idx];
+                }
                 return 1;
-            } else printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n");
+            } else {
+                printf ("Unhandled v6 insn: smlsd\n");
+            }
             break;
         case 0x74:
             printf ("Unhandled v6 insn: smlald/smlsld\n");

From d5bcddb77c9922f8345dd4014031662ab17e2b33 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Dec 2014 02:03:48 -0500
Subject: [PATCH 2/2] armemu: Fix SMUAD, SMUSD, and SMLAD

Wrong values were being multiplied together.
---
 src/core/arm/interpreter/armemu.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 967506f459..e4159ceb0a 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -6243,16 +6243,16 @@ L_stm_s_takeabort:
 
                 // SMUAD
                 if ((instr & 0xf0d0) == 0xf010) {
-                    state->Reg[rd_idx] = (rn_lo * rn_hi) + (rm_lo * rm_hi);
+                    state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi);
                 }
                 // SMUSD
                 else if ((instr & 0xf0d0) == 0xf050) {
-                    state->Reg[rd_idx] = (rn_lo * rn_hi) - (rm_lo * rm_hi);
+                    state->Reg[rd_idx] = (rn_lo * rm_lo) - (rn_hi * rm_hi);
                 }
                 // SMLAD
                 else {
                     const u8 ra_idx = BITS(12, 15);
-                    state->Reg[rd_idx] = (rn_lo * rn_hi) + (rm_lo * rm_hi) + (s32)state->Reg[ra_idx];
+                    state->Reg[rd_idx] = (rn_lo * rm_lo) + (rn_hi * rm_hi) + (s32)state->Reg[ra_idx];
                 }
                 return 1;
             } else {