aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei <bunneidev@gmail.com>2014-12-17 21:44:13 -0500
committerGravatar bunnei <bunneidev@gmail.com>2014-12-17 21:44:13 -0500
commita968adf50e5aeb1f9d0be0c8fa8152aa691569aa (patch)
treefd695c1d869e61fef65ec99d2602d4f9b1027d52 /src
parent075126247f4dc4230835215f8c86a7de8e8e1b98 (diff)
parent5820dba6b7b24a0f23474ffd1d303961be398687 (diff)
Merge pull request #295 from lioncash/umaal
armemu: Implement UMAAL
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/interpreter/armemu.cpp28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 14330156..a36035e9 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -1356,7 +1356,13 @@ mainswitch:
}
break;
- case 0x04: /* SUB reg */
+ case 0x04: /* SUB reg */
+ // Signifies UMAAL
+ if (state->is_v6 && BITS(4, 7) == 0x09) {
+ if (handle_v6_insn(state, instr))
+ break;
+ }
+
#ifdef MODET
if (BITS (4, 7) == 0xB) {
/* STRH immediate offset, no write-back, down, post indexed. */
@@ -5683,8 +5689,24 @@ L_stm_s_takeabort:
case 0x03:
printf ("Unhandled v6 insn: ldr\n");
break;
- case 0x04:
- printf ("Unhandled v6 insn: umaal\n");
+ case 0x04: // UMAAL
+ {
+ const u8 rm_idx = BITS(8, 11);
+ const u8 rn_idx = BITS(0, 3);
+ const u8 rd_lo_idx = BITS(12, 15);
+ const u8 rd_hi_idx = BITS(16, 19);
+
+ const u32 rm_val = state->Reg[rm_idx];
+ const u32 rn_val = state->Reg[rn_idx];
+ const u32 rd_lo_val = state->Reg[rd_lo_idx];
+ const u32 rd_hi_val = state->Reg[rd_hi_idx];
+
+ const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val;
+
+ state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF);
+ state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF);
+ return 1;
+ }
break;
case 0x06:
printf ("Unhandled v6 insn: mls/str\n");