diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index c032c7168..b9ac8b9ad 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"); @@ -5925,11 +5947,29 @@ L_stm_s_takeabort: b2 = ((u8)(from >> 8) + (u8)(to >> 8)); b3 = ((u8)(from >> 16) + (u8)(to >> 16)); b4 = ((u8)(from >> 24) + (u8)(to >> 24)); - if (b1 & 0xffffff00) state->Cpsr |= (1 << 16); - if (b2 & 0xffffff00) state->Cpsr |= (1 << 17); - if (b3 & 0xffffff00) state->Cpsr |= (1 << 18); - if (b4 & 0xffffff00) state->Cpsr |= (1 << 19); + + if (b1 & 0xffffff00) + state->Cpsr |= (1 << 16); + else + state->Cpsr &= ~(1 << 16); + + if (b2 & 0xffffff00) + state->Cpsr |= (1 << 17); + else + state->Cpsr &= ~(1 << 17); + + if (b3 & 0xffffff00) + state->Cpsr |= (1 << 18); + else + state->Cpsr &= ~(1 << 18); + + + if (b4 & 0xffffff00) + state->Cpsr |= (1 << 19); + else + state->Cpsr &= ~(1 << 19); } + state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); return 1; } |