summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp83
1 files changed, 57 insertions, 26 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 5f8826034..9ed61947e 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -36,7 +36,8 @@ enum {
36 CALL = (1 << 4), 36 CALL = (1 << 4),
37 RET = (1 << 5), 37 RET = (1 << 5),
38 END_OF_PAGE = (1 << 6), 38 END_OF_PAGE = (1 << 6),
39 THUMB = (1 << 7) 39 THUMB = (1 << 7),
40 SINGLE_STEP = (1 << 8)
40}; 41};
41 42
42#define RM BITS(sht_oper, 0, 3) 43#define RM BITS(sht_oper, 0, 3)
@@ -3466,7 +3467,35 @@ enum {
3466 3467
3467MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); 3468MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
3468 3469
3469static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { 3470static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) {
3471 unsigned int inst_size = 4;
3472 unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
3473
3474 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
3475 if (cpu->TFlag) {
3476 u32 arm_inst;
3477 ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
3478
3479 // We have translated the Thumb branch instruction in the Thumb decoder
3480 if (state == ThumbDecodeStatus::BRANCH) {
3481 return inst_size;
3482 }
3483 inst = arm_inst;
3484 }
3485
3486 int idx;
3487 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
3488 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
3489 LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst);
3490 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
3491 CITRA_IGNORE_EXIT(-1);
3492 }
3493 inst_base = arm_instruction_trans[idx](inst, idx);
3494
3495 return inst_size;
3496}
3497
3498static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) {
3470 Common::Profiling::ScopeTimer timer_decode(profile_decode); 3499 Common::Profiling::ScopeTimer timer_decode(profile_decode);
3471 MICROPROFILE_SCOPE(DynCom_Decode); 3500 MICROPROFILE_SCOPE(DynCom_Decode);
3472 3501
@@ -3475,8 +3504,6 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
3475 // Go on next, until terminal instruction 3504 // Go on next, until terminal instruction
3476 // Save start addr of basicblock in CreamCache 3505 // Save start addr of basicblock in CreamCache
3477 ARM_INST_PTR inst_base = nullptr; 3506 ARM_INST_PTR inst_base = nullptr;
3478 unsigned int inst, inst_size = 4;
3479 int idx;
3480 int ret = NON_BRANCH; 3507 int ret = NON_BRANCH;
3481 int size = 0; // instruction size of basic block 3508 int size = 0; // instruction size of basic block
3482 bb_start = top; 3509 bb_start = top;
@@ -3485,30 +3512,10 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
3485 u32 pc_start = cpu->Reg[15]; 3512 u32 pc_start = cpu->Reg[15];
3486 3513
3487 while (ret == NON_BRANCH) { 3514 while (ret == NON_BRANCH) {
3488 inst = Memory::Read32(phys_addr & 0xFFFFFFFC); 3515 unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
3489 3516
3490 size++; 3517 size++;
3491 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
3492 if (cpu->TFlag) {
3493 u32 arm_inst;
3494 ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
3495
3496 // We have translated the Thumb branch instruction in the Thumb decoder
3497 if (state == ThumbDecodeStatus::BRANCH) {
3498 goto translated;
3499 }
3500 inst = arm_inst;
3501 }
3502
3503 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
3504 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
3505 LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst);
3506 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
3507 CITRA_IGNORE_EXIT(-1);
3508 }
3509 inst_base = arm_instruction_trans[idx](inst, idx);
3510 3518
3511translated:
3512 phys_addr += inst_size; 3519 phys_addr += inst_size;
3513 3520
3514 if ((phys_addr & 0xfff) == 0) { 3521 if ((phys_addr & 0xfff) == 0) {
@@ -3522,6 +3529,27 @@ translated:
3522 return KEEP_GOING; 3529 return KEEP_GOING;
3523} 3530}
3524 3531
3532static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) {
3533 Common::Profiling::ScopeTimer timer_decode(profile_decode);
3534 MICROPROFILE_SCOPE(DynCom_Decode);
3535
3536 ARM_INST_PTR inst_base = nullptr;
3537 bb_start = top;
3538
3539 u32 phys_addr = addr;
3540 u32 pc_start = cpu->Reg[15];
3541
3542 InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
3543
3544 if (inst_base->br == NON_BRANCH) {
3545 inst_base->br = SINGLE_STEP;
3546 }
3547
3548 cpu->instruction_cache[pc_start] = bb_start;
3549
3550 return KEEP_GOING;
3551}
3552
3525static int clz(unsigned int x) { 3553static int clz(unsigned int x) {
3526 int n; 3554 int n;
3527 if (x == 0) return (32); 3555 if (x == 0) return (32);
@@ -3871,8 +3899,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
3871 auto itr = cpu->instruction_cache.find(cpu->Reg[15]); 3899 auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
3872 if (itr != cpu->instruction_cache.end()) { 3900 if (itr != cpu->instruction_cache.end()) {
3873 ptr = itr->second; 3901 ptr = itr->second;
3902 } else if (cpu->NumInstrsToExecute != 1) {
3903 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
3904 goto END;
3874 } else { 3905 } else {
3875 if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) 3906 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
3876 goto END; 3907 goto END;
3877 } 3908 }
3878 3909