summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp75
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
975typedef 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
975typedef struct _mla_inst { 985typedef 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
2362ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } 2372ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); }
2363ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALD"); }
2364ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLAW"); } 2373ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLAW"); }
2365ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLSLD"); } 2374
2375ARM_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}
2395ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index)
2396{
2397 return INTERPRETER_TRANSLATE(smlald)(inst, index);
2398}
2366 2399
2367ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) 2400ARM_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: