diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 83 |
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 | ||
| 3467 | MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); | 3468 | MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); |
| 3468 | 3469 | ||
| 3469 | static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | 3470 | static 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 | |||
| 3498 | static 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 | ||
| 3511 | translated: | ||
| 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 | ||
| 3532 | static 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 | |||
| 3525 | static int clz(unsigned int x) { | 3553 | static 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 | ||