diff options
Diffstat (limited to 'src/core/arm/dyncom/arm_dyncom_interpreter.cpp')
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 308 |
1 files changed, 111 insertions, 197 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 2765cb36e..b79fd1719 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -6,13 +6,12 @@ #include <algorithm> #include <cstdio> -#include <unordered_map> #include "common/logging/log.h" #include "common/profiler.h" -#include "core/mem_map.h" -#include "core/hle/hle.h" +#include "core/memory.h" +#include "core/hle/svc.h" #include "core/arm/disassembler/arm_disasm.h" #include "core/arm/dyncom/arm_dyncom_interpreter.h" #include "core/arm/dyncom/arm_dyncom_thumb.h" @@ -339,7 +338,7 @@ static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int ins unsigned int shift_imm = BITS(inst, 7, 11); unsigned int Rn = BITS(inst, 16, 19); unsigned int Rm = BITS(inst, 0, 3); - unsigned int index; + unsigned int index = 0; unsigned int addr; unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); @@ -390,7 +389,7 @@ static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int in unsigned int shift_imm = BITS(inst, 7, 11); unsigned int Rn = BITS(inst, 16, 19); unsigned int Rm = BITS(inst, 0, 3); - unsigned int index; + unsigned int index = 0; unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); @@ -605,7 +604,7 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u unsigned int shift_imm = BITS(inst, 7, 11); unsigned int Rn = BITS(inst, 16, 19); unsigned int Rm = BITS(inst, 0, 3); - unsigned int index; + unsigned int index = 0; unsigned int addr; unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); @@ -993,6 +992,14 @@ typedef struct _mcr_inst { unsigned int inst; } mcr_inst; +typedef struct mcrr_inst { + unsigned int opcode_1; + unsigned int cp_num; + unsigned int crm; + unsigned int rt; + unsigned int rt2; +} mcrr_inst; + typedef struct _mrs_inst { unsigned int R; unsigned int Rd; @@ -1126,7 +1133,7 @@ int CondPassed(ARMul_State* cpu, unsigned int cond) { #define CFLAG cpu->CFlag #define VFLAG cpu->VFlag - int temp; + int temp = 0; switch (cond) { case 0x0: @@ -1262,11 +1269,6 @@ static get_addr_fp_t get_calc_addr_op(unsigned int inst) { #define CHECK_RM (inst_cream->Rm == 15) #define CHECK_RS (inst_cream->Rs == 15) -#define UNIMPLEMENTED_INSTRUCTION(mnemonic) \ - LOG_ERROR(Core_ARM11, "unimplemented instruction: %s", mnemonic); \ - CITRA_IGNORE_EXIT(-1); \ - return nullptr; - static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) { arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); @@ -1391,7 +1393,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) inst_base->br = NON_BRANCH; inst_base->load_r15 = 0; - inst_cream->imm = BITS(inst, 8, 19) | BITS(inst, 0, 3); + inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); return inst_base; } @@ -1872,7 +1874,26 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) inst_cream->inst = inst; return inst_base; } -static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MCRR"); } + +static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); + mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->crm = BITS(inst, 0, 3); + inst_cream->opcode_1 = BITS(inst, 4, 7); + inst_cream->cp_num = BITS(inst, 8, 11); + inst_cream->rt = BITS(inst, 12, 15); + inst_cream->rt2 = BITS(inst, 16, 19); + + return inst_base; +} + static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) { arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); @@ -1931,7 +1952,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) inst_cream->inst = inst; return inst_base; } -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MRRC"); } + +static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(mcrr)(inst, index); +} + static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) { arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); @@ -3533,31 +3559,12 @@ const transop_fp_t arm_instruction_trans[] = { INTERPRETER_TRANSLATE(blx_1_thumb) }; -typedef std::unordered_map<u32, int> bb_map; -static bb_map CreamCache; - -static void insert_bb(unsigned int addr, int start) { - CreamCache[addr] = start; -} - -static int find_bb(unsigned int addr, int& start) { - int ret = -1; - bb_map::const_iterator it = CreamCache.find(addr); - if (it != CreamCache.end()) { - start = static_cast<int>(it->second); - ret = 0; - } else { - ret = -1; - } - return ret; -} - enum { FETCH_SUCCESS, FETCH_FAILURE }; -static tdstate decode_thumb_instr(ARMul_State* cpu, uint32_t inst, addr_t addr, uint32_t* arm_inst, uint32_t* inst_size, ARM_INST_PTR* ptr_inst_base){ +static tdstate decode_thumb_instr(ARMul_State* cpu, u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { // Check if in Thumb mode tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size); if(ret == t_branch){ @@ -3620,7 +3627,7 @@ typedef struct instruction_set_encoding_item ISEITEM; extern const ISEITEM arm_instruction[]; -static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, addr_t addr) { +static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { Common::Profiling::ScopeTimer timer_decode(profile_decode); // Decode instruction, get index @@ -3638,8 +3645,8 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, addr_t addr) { if (cpu->TFlag) thumb = THUMB; - addr_t phys_addr = addr; - addr_t pc_start = cpu->Reg[15]; + u32 phys_addr = addr; + u32 pc_start = cpu->Reg[15]; while(ret == NON_BRANCH) { inst = Memory::Read32(phys_addr & 0xFFFFFFFC); @@ -3674,7 +3681,9 @@ translated: } ret = inst_base->br; }; - insert_bb(pc_start, bb_start); + + cpu->instruction_cache[pc_start] = bb_start; + return KEEP_GOING; } @@ -3690,20 +3699,16 @@ static int clz(unsigned int x) { return n; } -static bool InAPrivilegedMode(ARMul_State* core) { - return (core->Mode != USER32MODE); -} - -unsigned InterpreterMainLoop(ARMul_State* state) { +unsigned InterpreterMainLoop(ARMul_State* cpu) { Common::Profiling::ScopeTimer timer_execute(profile_execute); #undef RM #undef RS #define CRn inst_cream->crn + #define OPCODE_1 inst_cream->opcode_1 #define OPCODE_2 inst_cream->opcode_2 #define CRm inst_cream->crm - #define CP15_REG(n) cpu->CP15[CP15(n)] #define RD cpu->Reg[inst_cream->Rd] #define RD2 cpu->Reg[inst_cream->Rd + 1] #define RN cpu->Reg[inst_cream->Rn] @@ -3952,8 +3957,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) { #define PC (cpu->Reg[15]) #define CHECK_EXT_INT if (!cpu->NirqSig && !(cpu->Cpsr & 0x80)) goto END; - ARMul_State* cpu = state; - // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback // to a clunky switch statement. #if defined __GNUC__ || defined __clang__ @@ -4005,9 +4008,14 @@ unsigned InterpreterMainLoop(ARMul_State* state) { phys_addr = cpu->Reg[15]; - if (find_bb(cpu->Reg[15], ptr) == -1) + // Find the cached instruction cream, otherwise translate it... + auto itr = cpu->instruction_cache.find(cpu->Reg[15]); + if (itr != cpu->instruction_cache.end()) { + ptr = itr->second; + } else { if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) goto END; + } inst_base = (arm_inst *)&inst_buf[ptr]; GOTO_NEXT_INST; @@ -4764,94 +4772,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { if (inst_cream->Rd == 15) { DEBUG_MSG; } else { - if (inst_cream->cp_num == 15) { - if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { - CP15_REG(CP15_CONTROL) = RD; - } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { - CP15_REG(CP15_AUXILIARY_CONTROL) = RD; - } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { - CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD; - } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { - CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD; - } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { - CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD; - } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { - CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD; - } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { - CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD; - } else if(CRn == MMU_CACHE_OPS){ - //LOG_WARNING(Core_ARM11, "cache operations have not implemented."); - } else if(CRn == MMU_TLB_OPS){ - switch (CRm) { - case 5: // ITLB - switch(OPCODE_2) { - case 0: // Invalidate all - LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate all"); - break; - case 1: // Invalidate by MVA - LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate by mva"); - break; - case 2: // Invalidate by asid - LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate by asid"); - break; - default: - break; - } - - break; - case 6: // DTLB - switch(OPCODE_2){ - case 0: // Invalidate all - LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate all"); - break; - case 1: // Invalidate by MVA - LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate by mva"); - break; - case 2: // Invalidate by asid - LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate by asid"); - break; - default: - break; - } - break; - case 7: // UNIFILED TLB - switch(OPCODE_2){ - case 0: // invalidate all - LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate all"); - break; - case 1: // Invalidate by MVA - LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by mva"); - break; - case 2: // Invalidate by asid - LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by asid"); - break; - default: - break; - } - break; - default: - break; - } - } else if(CRn == MMU_PID) { - if(OPCODE_2 == 0) { - CP15_REG(CP15_PID) = RD; - } else if(OPCODE_2 == 1) { - CP15_REG(CP15_CONTEXT_ID) = RD; - } else if (OPCODE_2 == 2) { - CP15_REG(CP15_THREAD_UPRW) = RD; - } else if(OPCODE_2 == 3) { - if (InAPrivilegedMode(cpu)) - CP15_REG(CP15_THREAD_URO) = RD; - } else if (OPCODE_2 == 4) { - if (InAPrivilegedMode(cpu)) - CP15_REG(CP15_THREAD_PRW) = RD; - } else { - LOG_ERROR(Core_ARM11, "mmu_mcr wrote UNKNOWN - reg %d", CRn); - } - } else { - LOG_ERROR(Core_ARM11, "mcr CRn=%d, CRm=%d OP2=%d is not implemented", CRn, CRm, OPCODE_2); - } - } + if (inst_cream->cp_num == 15) + WriteCP15Register(cpu, RD, CRn, OPCODE_1, CRm, OPCODE_2); } } cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -4859,7 +4781,24 @@ unsigned InterpreterMainLoop(ARMul_State* state) { FETCH_INST; GOTO_NEXT_INST; } + MCRR_INST: + { + // Stubbed, as the MPCore doesn't have any registers that are accessible + // through this instruction. + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; + + LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", + inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); + } + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mcrr_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MLA_INST: { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { @@ -4926,50 +4865,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { CITRA_IGNORE_EXIT(-1); goto END; } else { - if (inst_cream->cp_num == 15) { - if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { - RD = cpu->CP15[CP15(CP15_MAIN_ID)]; - } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) { - RD = cpu->CP15[CP15(CP15_CACHE_TYPE)]; - } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { - RD = cpu->CP15[CP15(CP15_CONTROL)]; - } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { - RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)]; - } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { - RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)]; - } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { - RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)]; - } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { - RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_1)]; - } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { - RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_CONTROL)]; - } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { - RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)]; - } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) { - RD = cpu->CP15[CP15(CP15_FAULT_STATUS)]; - } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) { - RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)]; - } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) { - RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)]; - } else if (CRn == 13) { - if(OPCODE_2 == 0) { - RD = CP15_REG(CP15_PID); - } else if(OPCODE_2 == 1) { - RD = CP15_REG(CP15_CONTEXT_ID); - } else if (OPCODE_2 == 2) { - RD = CP15_REG(CP15_THREAD_UPRW); - } else if(OPCODE_2 == 3) { - RD = Memory::KERNEL_MEMORY_VADDR; - } else if (OPCODE_2 == 4) { - if (InAPrivilegedMode(cpu)) - RD = CP15_REG(CP15_THREAD_PRW); - } else { - LOG_ERROR(Core_ARM11, "mmu_mrr wrote UNKNOWN - reg %d", CRn); - } - } else { - LOG_ERROR(Core_ARM11, "mrc CRn=%d, CRm=%d, OP2=%d is not implemented", CRn, CRm, OPCODE_2); - } - } + if (inst_cream->cp_num == 15) + RD = ReadCP15Register(cpu, CRn, OPCODE_1, CRm, OPCODE_2); } } cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -4977,7 +4874,24 @@ unsigned InterpreterMainLoop(ARMul_State* state) { FETCH_INST; GOTO_NEXT_INST; } + MRRC_INST: + { + // Stubbed, as the MPCore doesn't have any registers that are accessible + // through this instruction. + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; + + LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", + inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); + } + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mcrr_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MRS_INST: { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { @@ -6379,7 +6293,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { SWI_INST: { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { - HLE::CallSVC(Memory::Read32(cpu->Reg[15])); + SVC::CallSVC(Memory::Read32(cpu->Reg[15])); } cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -6637,24 +6551,24 @@ unsigned InterpreterMainLoop(ARMul_State* state) { s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); if (sum1 >= 0x100) - state->Cpsr |= (1 << 16); + cpu->Cpsr |= (1 << 16); else - state->Cpsr &= ~(1 << 16); + cpu->Cpsr &= ~(1 << 16); if (sum2 >= 0x100) - state->Cpsr |= (1 << 17); + cpu->Cpsr |= (1 << 17); else - state->Cpsr &= ~(1 << 17); + cpu->Cpsr &= ~(1 << 17); if (sum3 >= 0x100) - state->Cpsr |= (1 << 18); + cpu->Cpsr |= (1 << 18); else - state->Cpsr &= ~(1 << 18); + cpu->Cpsr &= ~(1 << 18); if (sum4 >= 0x100) - state->Cpsr |= (1 << 19); + cpu->Cpsr |= (1 << 19); else - state->Cpsr &= ~(1 << 19); + cpu->Cpsr &= ~(1 << 19); lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8); hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8); @@ -6667,24 +6581,24 @@ unsigned InterpreterMainLoop(ARMul_State* state) { s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); if (diff1 >= 0) - state->Cpsr |= (1 << 16); + cpu->Cpsr |= (1 << 16); else - state->Cpsr &= ~(1 << 16); + cpu->Cpsr &= ~(1 << 16); if (diff2 >= 0) - state->Cpsr |= (1 << 17); + cpu->Cpsr |= (1 << 17); else - state->Cpsr &= ~(1 << 17); + cpu->Cpsr &= ~(1 << 17); if (diff3 >= 0) - state->Cpsr |= (1 << 18); + cpu->Cpsr |= (1 << 18); else - state->Cpsr &= ~(1 << 18); + cpu->Cpsr &= ~(1 << 18); if (diff4 >= 0) - state->Cpsr |= (1 << 19); + cpu->Cpsr |= (1 << 19); else - state->Cpsr &= ~(1 << 19); + cpu->Cpsr &= ~(1 << 19); lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8); hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8); |