summaryrefslogtreecommitdiffstats
path: root/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/dyncom/arm_dyncom_interpreter.cpp')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp308
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);