diff options
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 64335b9c2..e3a8b1f6e 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -2369,7 +2369,25 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) | |||
| 2369 | } | 2369 | } |
| 2370 | 2370 | ||
| 2371 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } | 2371 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } |
| 2372 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLAW"); } | 2372 | |
| 2373 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) | ||
| 2374 | { | ||
| 2375 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); | ||
| 2376 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 2377 | |||
| 2378 | inst_base->cond = BITS(inst, 28, 31); | ||
| 2379 | inst_base->idx = index; | ||
| 2380 | inst_base->br = NON_BRANCH; | ||
| 2381 | inst_base->load_r15 = 0; | ||
| 2382 | |||
| 2383 | inst_cream->Ra = BITS(inst, 12, 15); | ||
| 2384 | inst_cream->Rm = BITS(inst, 8, 11); | ||
| 2385 | inst_cream->Rn = BITS(inst, 0, 3); | ||
| 2386 | inst_cream->Rd = BITS(inst, 16, 19); | ||
| 2387 | inst_cream->m = BIT(inst, 6); | ||
| 2388 | |||
| 2389 | return inst_base; | ||
| 2390 | } | ||
| 2373 | 2391 | ||
| 2374 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) | 2392 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) |
| 2375 | { | 2393 | { |
| @@ -5552,7 +5570,31 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 5552 | } | 5570 | } |
| 5553 | 5571 | ||
| 5554 | SMLALXY_INST: | 5572 | SMLALXY_INST: |
| 5573 | |||
| 5555 | SMLAW_INST: | 5574 | SMLAW_INST: |
| 5575 | { | ||
| 5576 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||
| 5577 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 5578 | |||
| 5579 | const u32 rm_val = RM; | ||
| 5580 | const u32 rn_val = RN; | ||
| 5581 | const u32 ra_val = cpu->Reg[inst_cream->Ra]; | ||
| 5582 | const bool high = (inst_cream->m == 1); | ||
| 5583 | |||
| 5584 | const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); | ||
| 5585 | const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); | ||
| 5586 | |||
| 5587 | RD = (result & (0xFFFFFFFFFFFFFFFFLL >> 15)) >> 16; | ||
| 5588 | |||
| 5589 | if ((result >> 16) != (s32)RD) | ||
| 5590 | cpu->Cpsr |= (1 << 27); | ||
| 5591 | } | ||
| 5592 | |||
| 5593 | cpu->Reg[15] += GET_INST_SIZE(cpu); | ||
| 5594 | INC_PC(sizeof(smlad_inst)); | ||
| 5595 | FETCH_INST; | ||
| 5596 | GOTO_NEXT_INST; | ||
| 5597 | } | ||
| 5556 | 5598 | ||
| 5557 | SMLALD_INST: | 5599 | SMLALD_INST: |
| 5558 | SMLSLD_INST: | 5600 | SMLSLD_INST: |