diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 75 |
1 files changed, 72 insertions, 3 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index a37e6c94e..6ef270d71 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -972,6 +972,16 @@ typedef struct _smlal_inst { | |||
| 972 | unsigned int RdLo; | 972 | unsigned int RdLo; |
| 973 | } smlal_inst; | 973 | } smlal_inst; |
| 974 | 974 | ||
| 975 | typedef struct smlald_inst { | ||
| 976 | unsigned int RdLo; | ||
| 977 | unsigned int RdHi; | ||
| 978 | unsigned int Rm; | ||
| 979 | unsigned int Rn; | ||
| 980 | unsigned int swap; | ||
| 981 | unsigned int op1; | ||
| 982 | unsigned int op2; | ||
| 983 | } smlald_inst; | ||
| 984 | |||
| 975 | typedef struct _mla_inst { | 985 | typedef struct _mla_inst { |
| 976 | unsigned int S; | 986 | unsigned int S; |
| 977 | unsigned int Rn; | 987 | unsigned int Rn; |
| @@ -2360,9 +2370,32 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) | |||
| 2360 | } | 2370 | } |
| 2361 | 2371 | ||
| 2362 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } | 2372 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } |
| 2363 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALD"); } | ||
| 2364 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLAW"); } | 2373 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLAW"); } |
| 2365 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLSLD"); } | 2374 | |
| 2375 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) | ||
| 2376 | { | ||
| 2377 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); | ||
| 2378 | smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; | ||
| 2379 | |||
| 2380 | inst_base->cond = BITS(inst, 28, 31); | ||
| 2381 | inst_base->idx = index; | ||
| 2382 | inst_base->br = NON_BRANCH; | ||
| 2383 | inst_base->load_r15 = 0; | ||
| 2384 | |||
| 2385 | inst_cream->Rm = BITS(inst, 8, 11); | ||
| 2386 | inst_cream->Rn = BITS(inst, 0, 3); | ||
| 2387 | inst_cream->RdLo = BITS(inst, 12, 15); | ||
| 2388 | inst_cream->RdHi = BITS(inst, 16, 19); | ||
| 2389 | inst_cream->swap = BIT(inst, 5); | ||
| 2390 | inst_cream->op1 = BITS(inst, 20, 22); | ||
| 2391 | inst_cream->op2 = BITS(inst, 5, 7); | ||
| 2392 | |||
| 2393 | return inst_base; | ||
| 2394 | } | ||
| 2395 | ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) | ||
| 2396 | { | ||
| 2397 | return INTERPRETER_TRANSLATE(smlald)(inst, index); | ||
| 2398 | } | ||
| 2366 | 2399 | ||
| 2367 | ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) | 2400 | ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) |
| 2368 | { | 2401 | { |
| @@ -5519,9 +5552,45 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 5519 | } | 5552 | } |
| 5520 | 5553 | ||
| 5521 | SMLALXY_INST: | 5554 | SMLALXY_INST: |
| 5522 | SMLALD_INST: | ||
| 5523 | SMLAW_INST: | 5555 | SMLAW_INST: |
| 5556 | |||
| 5557 | SMLALD_INST: | ||
| 5524 | SMLSLD_INST: | 5558 | SMLSLD_INST: |
| 5559 | { | ||
| 5560 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||
| 5561 | smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; | ||
| 5562 | |||
| 5563 | const bool do_swap = (inst_cream->swap == 1); | ||
| 5564 | const u32 rdlo_val = RDLO; | ||
| 5565 | const u32 rdhi_val = RDHI; | ||
| 5566 | const u32 rn_val = RN; | ||
| 5567 | u32 rm_val = RM; | ||
| 5568 | |||
| 5569 | if (do_swap) | ||
| 5570 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); | ||
| 5571 | |||
| 5572 | const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); | ||
| 5573 | const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); | ||
| 5574 | s64 result; | ||
| 5575 | |||
| 5576 | // SMLALD | ||
| 5577 | if (BIT(inst_cream->op2, 1) == 0) { | ||
| 5578 | result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 5579 | } | ||
| 5580 | // SMLSLD | ||
| 5581 | else { | ||
| 5582 | result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 5583 | } | ||
| 5584 | |||
| 5585 | RDLO = (result & 0xFFFFFFFF); | ||
| 5586 | RDHI = ((result >> 32) & 0xFFFFFFFF); | ||
| 5587 | } | ||
| 5588 | |||
| 5589 | cpu->Reg[15] += GET_INST_SIZE(cpu); | ||
| 5590 | INC_PC(sizeof(smlald_inst)); | ||
| 5591 | FETCH_INST; | ||
| 5592 | GOTO_NEXT_INST; | ||
| 5593 | } | ||
| 5525 | 5594 | ||
| 5526 | SMMLA_INST: | 5595 | SMMLA_INST: |
| 5527 | SMMLS_INST: | 5596 | SMMLS_INST: |