summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/interpreter/armemu.cpp35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index b2f671f94..27467bb5d 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -6503,8 +6503,39 @@ L_stm_s_takeabort:
6503 return 1; 6503 return 1;
6504 } 6504 }
6505 break; 6505 break;
6506 case 0x74: 6506 case 0x74: // SMLALD and SMLSLD
6507 printf ("Unhandled v6 insn: smlald/smlsld\n"); 6507 {
6508 const u8 rm_idx = BITS(8, 11);
6509 const u8 rn_idx = BITS(0, 3);
6510 const u8 rdlo_idx = BITS(12, 15);
6511 const u8 rdhi_idx = BITS(16, 19);
6512 const bool do_swap = (BIT(5) == 1);
6513
6514 const u32 rdlo_val = state->Reg[rdlo_idx];
6515 const u32 rdhi_val = state->Reg[rdhi_idx];
6516 const u32 rn_val = state->Reg[rn_idx];
6517 u32 rm_val = state->Reg[rm_idx];
6518
6519 if (do_swap)
6520 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
6521
6522 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
6523 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
6524 s64 result;
6525
6526 // SMLALD
6527 if (BIT(6) == 0) {
6528 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
6529 }
6530 // SMLSLD
6531 else {
6532 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
6533 }
6534
6535 state->Reg[rdlo_idx] = (result & 0xFFFFFFFF);
6536 state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF);
6537 return 1;
6538 }
6508 break; 6539 break;
6509 case 0x75: 6540 case 0x75:
6510 printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); 6541 printf ("Unhandled v6 insn: smmla/smmls/smmul\n");