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: | |||
| 1356 | } | 1356 | } |
| 1357 | break; | 1357 | break; |
| 1358 | 1358 | ||
| 1359 | case 0x04: /* SUB reg */ | 1359 | case 0x04: /* SUB reg */ |
| 1360 | // Signifies UMAAL | ||
| 1361 | if (state->is_v6 && BITS(4, 7) == 0x09) { | ||
| 1362 | if (handle_v6_insn(state, instr)) | ||
| 1363 | break; | ||
| 1364 | } | ||
| 1365 | |||
| 1360 | #ifdef MODET | 1366 | #ifdef MODET |
| 1361 | if (BITS (4, 7) == 0xB) { | 1367 | if (BITS (4, 7) == 0xB) { |
| 1362 | /* STRH immediate offset, no write-back, down, post indexed. */ | 1368 | /* STRH immediate offset, no write-back, down, post indexed. */ |
| @@ -5683,8 +5689,24 @@ L_stm_s_takeabort: | |||
| 5683 | case 0x03: | 5689 | case 0x03: |
| 5684 | printf ("Unhandled v6 insn: ldr\n"); | 5690 | printf ("Unhandled v6 insn: ldr\n"); |
| 5685 | break; | 5691 | break; |
| 5686 | case 0x04: | 5692 | case 0x04: // UMAAL |
| 5687 | printf ("Unhandled v6 insn: umaal\n"); | 5693 | { |
| 5694 | const u8 rm_idx = BITS(8, 11); | ||
| 5695 | const u8 rn_idx = BITS(0, 3); | ||
| 5696 | const u8 rd_lo_idx = BITS(12, 15); | ||
| 5697 | const u8 rd_hi_idx = BITS(16, 19); | ||
| 5698 | |||
| 5699 | const u32 rm_val = state->Reg[rm_idx]; | ||
| 5700 | const u32 rn_val = state->Reg[rn_idx]; | ||
| 5701 | const u32 rd_lo_val = state->Reg[rd_lo_idx]; | ||
| 5702 | const u32 rd_hi_val = state->Reg[rd_hi_idx]; | ||
| 5703 | |||
| 5704 | const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val; | ||
| 5705 | |||
| 5706 | state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF); | ||
| 5707 | state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF); | ||
| 5708 | return 1; | ||
| 5709 | } | ||
| 5688 | break; | 5710 | break; |
| 5689 | case 0x06: | 5711 | case 0x06: |
| 5690 | printf ("Unhandled v6 insn: mls/str\n"); | 5712 | printf ("Unhandled v6 insn: mls/str\n"); |
| @@ -5925,11 +5947,29 @@ L_stm_s_takeabort: | |||
| 5925 | b2 = ((u8)(from >> 8) + (u8)(to >> 8)); | 5947 | b2 = ((u8)(from >> 8) + (u8)(to >> 8)); |
| 5926 | b3 = ((u8)(from >> 16) + (u8)(to >> 16)); | 5948 | b3 = ((u8)(from >> 16) + (u8)(to >> 16)); |
| 5927 | b4 = ((u8)(from >> 24) + (u8)(to >> 24)); | 5949 | b4 = ((u8)(from >> 24) + (u8)(to >> 24)); |
| 5928 | if (b1 & 0xffffff00) state->Cpsr |= (1 << 16); | 5950 | |
| 5929 | if (b2 & 0xffffff00) state->Cpsr |= (1 << 17); | 5951 | if (b1 & 0xffffff00) |
| 5930 | if (b3 & 0xffffff00) state->Cpsr |= (1 << 18); | 5952 | state->Cpsr |= (1 << 16); |
| 5931 | if (b4 & 0xffffff00) state->Cpsr |= (1 << 19); | 5953 | else |
| 5954 | state->Cpsr &= ~(1 << 16); | ||
| 5955 | |||
| 5956 | if (b2 & 0xffffff00) | ||
| 5957 | state->Cpsr |= (1 << 17); | ||
| 5958 | else | ||
| 5959 | state->Cpsr &= ~(1 << 17); | ||
| 5960 | |||
| 5961 | if (b3 & 0xffffff00) | ||
| 5962 | state->Cpsr |= (1 << 18); | ||
| 5963 | else | ||
| 5964 | state->Cpsr &= ~(1 << 18); | ||
| 5965 | |||
| 5966 | |||
| 5967 | if (b4 & 0xffffff00) | ||
| 5968 | state->Cpsr |= (1 << 19); | ||
| 5969 | else | ||
| 5970 | state->Cpsr &= ~(1 << 19); | ||
| 5932 | } | 5971 | } |
| 5972 | |||
| 5933 | state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); | 5973 | state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); |
| 5934 | return 1; | 5974 | return 1; |
| 5935 | } | 5975 | } |