diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index ed2de115a..593e0eabd 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -1419,15 +1419,19 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) | |||
| 1419 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); | 1419 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); |
| 1420 | bx_inst *inst_cream = (bx_inst *)inst_base->component; | 1420 | bx_inst *inst_cream = (bx_inst *)inst_base->component; |
| 1421 | 1421 | ||
| 1422 | inst_base->cond = BITS(inst, 28, 31); | 1422 | inst_base->cond = BITS(inst, 28, 31); |
| 1423 | inst_base->idx = index; | 1423 | inst_base->idx = index; |
| 1424 | inst_base->br = INDIRECT_BRANCH; | 1424 | inst_base->br = INDIRECT_BRANCH; |
| 1425 | 1425 | ||
| 1426 | inst_cream->Rm = BITS(inst, 0, 3); | 1426 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1427 | 1427 | ||
| 1428 | return inst_base; | 1428 | return inst_base; |
| 1429 | } | 1429 | } |
| 1430 | ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("BXJ"); } | 1430 | ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) |
| 1431 | { | ||
| 1432 | return INTERPRETER_TRANSLATE(bx)(inst, index); | ||
| 1433 | } | ||
| 1434 | |||
| 1431 | ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index){ | 1435 | ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index){ |
| 1432 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); | 1436 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); |
| 1433 | cdp_inst *inst_cream = (cdp_inst *)inst_base->component; | 1437 | cdp_inst *inst_cream = (cdp_inst *)inst_base->component; |
| @@ -4129,22 +4133,35 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4129 | INC_PC(sizeof(blx_inst)); | 4133 | INC_PC(sizeof(blx_inst)); |
| 4130 | goto DISPATCH; | 4134 | goto DISPATCH; |
| 4131 | } | 4135 | } |
| 4136 | |||
| 4132 | BX_INST: | 4137 | BX_INST: |
| 4138 | BXJ_INST: | ||
| 4133 | { | 4139 | { |
| 4134 | bx_inst *inst_cream = (bx_inst *)inst_base->component; | 4140 | // Note that only the 'fail' case of BXJ is emulated. This is because |
| 4135 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 4141 | // the facilities for Jazelle emulation are not implemented. |
| 4142 | // | ||
| 4143 | // According to the ARM documentation on BXJ, if setting the J bit in the APSR | ||
| 4144 | // fails, then BXJ functions identically like a regular BX instruction. | ||
| 4145 | // | ||
| 4146 | // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle. | ||
| 4147 | |||
| 4148 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||
| 4149 | bx_inst* const inst_cream = (bx_inst*)inst_base->component; | ||
| 4150 | |||
| 4136 | if (inst_cream->Rm == 15) | 4151 | if (inst_cream->Rm == 15) |
| 4137 | LOG_WARNING(Core_ARM11, "BX at pc %x: use of Rm = R15 is discouraged", cpu->Reg[15]); | 4152 | LOG_WARNING(Core_ARM11, "BX at pc %x: use of Rm = R15 is discouraged", cpu->Reg[15]); |
| 4153 | |||
| 4138 | cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; | 4154 | cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; |
| 4139 | cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; | 4155 | cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; |
| 4140 | INC_PC(sizeof(bx_inst)); | 4156 | INC_PC(sizeof(bx_inst)); |
| 4141 | goto DISPATCH; | 4157 | goto DISPATCH; |
| 4142 | } | 4158 | } |
| 4159 | |||
| 4143 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 4160 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 4144 | INC_PC(sizeof(bx_inst)); | 4161 | INC_PC(sizeof(bx_inst)); |
| 4145 | goto DISPATCH; | 4162 | goto DISPATCH; |
| 4146 | } | 4163 | } |
| 4147 | BXJ_INST: | 4164 | |
| 4148 | CDP_INST: | 4165 | CDP_INST: |
| 4149 | { | 4166 | { |
| 4150 | cdp_inst *inst_cream = (cdp_inst *)inst_base->component; | 4167 | cdp_inst *inst_cream = (cdp_inst *)inst_base->component; |