aboutsummaryrefslogtreecommitdiff
path: root/src/core/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.h16
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp25
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h4
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp308
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h41
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp8
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h4
-rw-r--r--src/core/arm/interpreter/armcopro.cpp142
-rw-r--r--src/core/arm/interpreter/arminit.cpp97
-rw-r--r--src/core/arm/interpreter/armsupp.cpp428
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h129
-rw-r--r--src/core/arm/skyeye_common/armdefs.h97
-rw-r--r--src/core/arm/skyeye_common/armemu.h21
-rw-r--r--src/core/arm/skyeye_common/armmmu.h4
-rw-r--r--src/core/arm/skyeye_common/armos.h54
-rw-r--r--src/core/arm/skyeye_common/skyeye_defs.h38
-rw-r--r--src/core/arm/skyeye_common/vfp/asm_vfp.h14
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp632
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h24
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h120
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp35
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp82
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp102
23 files changed, 980 insertions, 1445 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index fe1e584ad..85ed2c698 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -4,8 +4,8 @@
#pragma once
-#include "common/common.h"
#include "common/common_types.h"
+#include "core/arm/skyeye_common/arm_regformat.h"
namespace Core {
struct ThreadContext;
@@ -74,6 +74,20 @@ public:
virtual void SetCPSR(u32 cpsr) = 0;
/**
+ * Gets the value stored in a CP15 register.
+ * @param reg The CP15 register to retrieve the value from.
+ * @return the value stored in the given CP15 register.
+ */
+ virtual u32 GetCP15Register(CP15Register reg) = 0;
+
+ /**
+ * Stores the given value into the indicated CP15 register.
+ * @param reg The CP15 register to store the value into.
+ * @param value The value to store into the CP15 register.
+ */
+ virtual void SetCP15Register(CP15Register reg, u32 value) = 0;
+
+ /**
* Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
* @param ticks Number of ticks to advance the CPU core
*/
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index cb1a410a0..0072ae533 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -2,6 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+
+#include "common/make_unique.h"
+
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
@@ -12,18 +16,13 @@
#include "core/core.h"
#include "core/core_timing.h"
-const static cpu_config_t s_arm11_cpu_info = {
- "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
-};
-
ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
- state = std::unique_ptr<ARMul_State>(new ARMul_State);
+ state = Common::make_unique<ARMul_State>();
ARMul_NewState(state.get());
ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
state->abort_model = ABORT_BASE_RESTORED;
- state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
state->bigendSig = LOW;
state->lateabtSig = LOW;
@@ -31,7 +30,6 @@ ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
// Reset the core to initial state
ARMul_Reset(state.get());
- state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
state->Emulate = RUN;
// Switch to the desired privilege mode.
@@ -68,6 +66,14 @@ void ARM_DynCom::SetCPSR(u32 cpsr) {
state->Cpsr = cpsr;
}
+u32 ARM_DynCom::GetCP15Register(CP15Register reg) {
+ return state->CP15[reg];
+}
+
+void ARM_DynCom::SetCP15Register(CP15Register reg, u32 value) {
+ state->CP15[reg] = value;
+}
+
void ARM_DynCom::AddTicks(u64 ticks) {
down_count -= ticks;
if (down_count < 0)
@@ -91,7 +97,6 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e
context.pc = entry_point;
context.sp = stack_top;
context.cpsr = 0x1F; // Usermode
- context.mode = 8; // Instructs dyncom CPU core to start execution as if it's "resuming" a thread.
}
void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
@@ -105,8 +110,6 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
ctx.fpscr = state->VFP[1];
ctx.fpexc = state->VFP[2];
-
- ctx.mode = state->NextInstr;
}
void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
@@ -120,8 +123,6 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
state->VFP[1] = ctx.fpscr;
state->VFP[2] = ctx.fpexc;
-
- state->NextInstr = ctx.mode;
}
void ARM_DynCom::PrepareReschedule() {
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index a7f95d307..2488c879c 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -22,10 +22,12 @@ public:
void SetReg(int index, u32 value) override;
u32 GetCPSR() const override;
void SetCPSR(u32 cpsr) override;
+ u32 GetCP15Register(CP15Register reg) override;
+ void SetCP15Register(CP15Register reg, u32 value) override;
void AddTicks(u64 ticks) override;
- void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg);
+ void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) override;
void SaveContext(Core::ThreadContext& ctx) override;
void LoadContext(const Core::ThreadContext& ctx) override;
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);
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h
index e17420497..85774c565 100644
--- a/src/core/arm/dyncom/arm_dyncom_run.h
+++ b/src/core/arm/dyncom/arm_dyncom_run.h
@@ -22,31 +22,36 @@
void switch_mode(ARMul_State* core, uint32_t mode);
-/* FIXME, we temporarily think thumb instruction is always 16 bit */
+// Note that for the 3DS, a Thumb instruction will only ever be
+// two bytes in size. Thus we don't need to worry about ThumbEE
+// or Thumb-2 where instructions can be 4 bytes in length.
static inline u32 GET_INST_SIZE(ARMul_State* core) {
return core->TFlag? 2 : 4;
}
/**
-* @brief Read R15 and forced R15 to wold align, used address calculation
-*
-* @param core
-* @param Rn
-*
-* @return
-*/
-static inline addr_t CHECK_READ_REG15_WA(ARMul_State* core, int Rn) {
- return (Rn == 15)? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
+ * Checks if the PC is being read, and if so, word-aligns it.
+ * Used with address calculations.
+ *
+ * @param core The ARM CPU state instance.
+ * @param Rn The register being read.
+ *
+ * @return If the PC is being read, then the word-aligned PC value is returned.
+ * If the PC is not being read, then the value stored in the register is returned.
+ */
+static inline u32 CHECK_READ_REG15_WA(ARMul_State* core, int Rn) {
+ return (Rn == 15) ? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
}
/**
-* @brief Read R15, used to data processing with pc
-*
-* @param core
-* @param Rn
-*
-* @return
-*/
+ * Reads the PC. Used for data processing operations that use the PC.
+ *
+ * @param core The ARM CPU state instance.
+ * @param Rn The register being read.
+ *
+ * @return If the PC is being read, then the incremented PC value is returned.
+ * If the PC is not being read, then the values stored in the register is returned.
+ */
static inline u32 CHECK_READ_REG15(ARMul_State* core, int Rn) {
- return (Rn == 15)? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
+ return (Rn == 15) ? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index e30d515fb..08b5c0b77 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -6,14 +6,12 @@
// ARM instruction, and using the existing ARM simulator.
#include "core/arm/dyncom/arm_dyncom_thumb.h"
-#include "core/arm/skyeye_common/armos.h"
-#include "core/arm/skyeye_common/skyeye_defs.h"
// Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field,
// with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions
// allows easier simulation of the special dual BL instruction.
-tdstate thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size) {
+tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
tdstate valid = t_uninitialized;
ARMword tinstr = instr;
@@ -288,7 +286,7 @@ tdstate thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t*
: 0xE28DDF00) // ADD
|(tinstr & 0x007F); // off7
} else if ((tinstr & 0x0F00) == 0x0e00)
- *ainstr = 0xEF000000 | SWI_Breakpoint;
+ *ainstr = 0xEF000000 | 0x180000; // base | BKPT mask
else {
static const ARMword subset[4] = {
0xE92D0000, // STMDB sp!,{rlist}
@@ -320,7 +318,7 @@ tdstate thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t*
*ainstr |= ((tinstr & 0x00FF) << 16);
// New breakpoint value. See gdb/arm-tdep.c
else if ((tinstr & 0x00FF) == 0xFE)
- *ainstr |= SWI_Breakpoint;
+ *ainstr |= 0x180000; // base |= BKPT mask
else
*ainstr |= (tinstr & 0x00FF);
} else if ((tinstr & 0x0F00) != 0x0E00)
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
index a1785abb8..8394ff156 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -35,9 +35,9 @@ enum tdstate {
t_uninitialized,
};
-tdstate thumb_translate(addr_t addr, u32 instr, u32* ainstr, u32* inst_size);
+tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
-static inline u32 get_thumb_instr(u32 instr, addr_t pc) {
+static inline u32 get_thumb_instr(u32 instr, u32 pc) {
u32 tinstr;
if ((pc & 0x3) != 0)
tinstr = instr >> 16;
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp
deleted file mode 100644
index 4ae0c52e4..000000000
--- a/src/core/arm/interpreter/armcopro.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
- Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "core/arm/skyeye_common/armdefs.h"
-#include "core/arm/skyeye_common/armemu.h"
-#include "core/arm/skyeye_common/vfp/vfp.h"
-
-// Dummy Co-processors.
-
-static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b)
-{
- return ARMul_CANT;
-}
-
-static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c)
-{
- return ARMul_CANT;
-}
-
-static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c)
-{
- return ARMul_CANT;
-}
-
-static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d)
-{
- return ARMul_CANT;
-}
-
-static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d)
-{
- return ARMul_CANT;
-}
-
-// Install co-processor instruction handlers in this routine.
-void ARMul_CoProInit(ARMul_State* state)
-{
- // Initialise tham all first.
- for (unsigned int i = 0; i < 16; i++)
- ARMul_CoProDetach(state, i);
-
- // Install CoPro Instruction handlers here.
- // The format is:
- // ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
- // LDC routine, STC routine, MRC routine, MCR routine,
- // CDP routine, Read Reg routine, Write Reg routine).
- if (state->is_v6) {
- ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
- VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
- ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
- VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
-
- /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
- MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
- }
-
- // No handlers below here.
-
- // Call all the initialisation routines.
- for (unsigned int i = 0; i < 16; i++) {
- if (state->CPInit[i])
- (state->CPInit[i]) (state);
- }
-}
-
-// Install co-processor finalisation routines in this routine.
-void ARMul_CoProExit(ARMul_State * state)
-{
- for (unsigned int i = 0; i < 16; i++)
- if (state->CPExit[i])
- (state->CPExit[i]) (state);
-
- // Detach all handlers.
- for (unsigned int i = 0; i < 16; i++)
- ARMul_CoProDetach(state, i);
-}
-
-// Routines to hook Co-processors into ARMulator.
-
-void
-ARMul_CoProAttach(ARMul_State* state,
-unsigned number,
-ARMul_CPInits* init,
-ARMul_CPExits* exit,
-ARMul_LDCs* ldc,
-ARMul_STCs* stc,
-ARMul_MRCs* mrc,
-ARMul_MCRs* mcr,
-ARMul_MRRCs* mrrc,
-ARMul_MCRRs* mcrr,
-ARMul_CDPs* cdp,
-ARMul_CPReads* read, ARMul_CPWrites* write)
-{
- if (init != NULL)
- state->CPInit[number] = init;
- if (exit != NULL)
- state->CPExit[number] = exit;
- if (ldc != NULL)
- state->LDC[number] = ldc;
- if (stc != NULL)
- state->STC[number] = stc;
- if (mrc != NULL)
- state->MRC[number] = mrc;
- if (mcr != NULL)
- state->MCR[number] = mcr;
- if (mrrc != NULL)
- state->MRRC[number] = mrrc;
- if (mcrr != NULL)
- state->MCRR[number] = mcrr;
- if (cdp != NULL)
- state->CDP[number] = cdp;
- if (read != NULL)
- state->CPRead[number] = read;
- if (write != NULL)
- state->CPWrite[number] = write;
-}
-
-void ARMul_CoProDetach(ARMul_State* state, unsigned number)
-{
- ARMul_CoProAttach(state, number, NULL, NULL,
- NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
- NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
-
- state->CPInit[number] = NULL;
- state->CPExit[number] = NULL;
- state->CPRead[number] = NULL;
- state->CPWrite[number] = NULL;
-}
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 4ac827e0a..680a94a39 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -18,31 +18,16 @@
#include <cstring>
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
+#include "core/arm/skyeye_common/vfp/vfp.h"
/***************************************************************************\
* Returns a new instantiation of the ARMulator's state *
\***************************************************************************/
ARMul_State* ARMul_NewState(ARMul_State* state)
{
- memset(state, 0, sizeof(ARMul_State));
-
state->Emulate = RUN;
- for (unsigned int i = 0; i < 16; i++) {
- state->Reg[i] = 0;
- for (unsigned int j = 0; j < 7; j++)
- state->RegBank[j][i] = 0;
- }
- for (unsigned int i = 0; i < 7; i++)
- state->Spsr[i] = 0;
-
state->Mode = USER32MODE;
- state->VectorCatch = 0;
- state->Aborted = false;
- state->Reseted = false;
- state->Inted = 3;
- state->LastInted = 3;
-
state->lateabtSig = HIGH;
state->bigendSig = LOW;
@@ -55,15 +40,69 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
{
- state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
- state->is_v5 = (properties & ARM_v5_Prop) != 0;
- state->is_v5e = (properties & ARM_v5e_Prop) != 0;
- state->is_v6 = (properties & ARM_v6_Prop) != 0;
- state->is_v7 = (properties & ARM_v7_Prop) != 0;
-
- // Only initialse the coprocessor support once we
- // know what kind of chip we are dealing with.
- ARMul_CoProInit(state);
+ state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
+ state->is_v5 = (properties & ARM_v5_Prop) != 0;
+ state->is_v5e = (properties & ARM_v5e_Prop) != 0;
+ state->is_v6 = (properties & ARM_v6_Prop) != 0;
+ state->is_v7 = (properties & ARM_v7_Prop) != 0;
+}
+
+// Resets certain MPCore CP15 values to their ARM-defined reset values.
+static void ResetMPCoreCP15Registers(ARMul_State* cpu)
+{
+ // c0
+ cpu->CP15[CP15_MAIN_ID] = 0x410FB024;
+ cpu->CP15[CP15_TLB_TYPE] = 0x00000800;
+ cpu->CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111;
+ cpu->CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001;
+ cpu->CP15[CP15_DEBUG_FEATURE_0] = 0x00000002;
+ cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103;
+ cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302;
+ cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000;
+ cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000;
+ cpu->CP15[CP15_ISA_FEATURE_0] = 0x00100011;
+ cpu->CP15[CP15_ISA_FEATURE_1] = 0x12002111;
+ cpu->CP15[CP15_ISA_FEATURE_2] = 0x11221011;
+ cpu->CP15[CP15_ISA_FEATURE_3] = 0x01102131;
+ cpu->CP15[CP15_ISA_FEATURE_4] = 0x00000141;
+
+ // c1
+ cpu->CP15[CP15_CONTROL] = 0x00054078;
+ cpu->CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F;
+ cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000;
+
+ // c2
+ cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000;
+ cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000;
+ cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000;
+
+ // c3
+ cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000;
+
+ // c7
+ cpu->CP15[CP15_PHYS_ADDRESS] = 0x00000000;
+
+ // c9
+ cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0;
+
+ // c10
+ cpu->CP15[CP15_TLB_LOCKDOWN] = 0x00000000;
+ cpu->CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4;
+ cpu->CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0;
+
+ // c13
+ cpu->CP15[CP15_PID] = 0x00000000;
+ cpu->CP15[CP15_CONTEXT_ID] = 0x00000000;
+ cpu->CP15[CP15_THREAD_UPRW] = 0x00000000;
+ cpu->CP15[CP15_THREAD_URO] = 0x00000000;
+ cpu->CP15[CP15_THREAD_PRW] = 0x00000000;
+
+ // c15
+ cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000;
+ cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000;
+ cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000;
+ cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000;
+ cpu->CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
}
/***************************************************************************\
@@ -71,24 +110,20 @@ void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
\***************************************************************************/
void ARMul_Reset(ARMul_State* state)
{
- state->NextInstr = 0;
+ VFPInit(state);
state->Reg[15] = 0;
state->Cpsr = INTBITS | SVC32MODE;
state->Mode = SVC32MODE;
-
state->Bank = SVCBANK;
- FLUSHPIPE;
- state->EndCondition = 0;
- state->ErrorCode = 0;
+ ResetMPCoreCP15Registers(state);
state->NresetSig = HIGH;
state->NfiqSig = HIGH;
state->NirqSig = HIGH;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
state->abortSig = LOW;
- state->AbortAddr = 1;
state->NumInstrs = 0;
}
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index aca2bfbbd..1b078dc71 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -15,7 +15,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include "common/logging/log.h"
+
+#include "core/mem_map.h"
#include "core/arm/skyeye_common/armdefs.h"
+#include "core/arm/skyeye_common/arm_regformat.h"
// Unsigned sum of absolute difference
u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
@@ -207,3 +211,427 @@ bool InBigEndianMode(ARMul_State* cpu)
{
return (cpu->Cpsr & (1 << 9)) != 0;
}
+
+// Whether or not the given CPU is in a mode other than user mode.
+bool InAPrivilegedMode(ARMul_State* cpu)
+{
+ return (cpu->Mode != USER32MODE);
+}
+
+// Reads from the CP15 registers. Used with implementation of the MRC instruction.
+// Note that since the 3DS does not have the hypervisor extensions, these registers
+// are not implemented.
+u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
+{
+ // Unprivileged registers
+ if (crn == 13 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 2)
+ return cpu->CP15[CP15_THREAD_UPRW];
+
+ if (opcode_2 == 3)
+ return cpu->CP15[CP15_THREAD_URO];
+ }
+
+ if (InAPrivilegedMode(cpu))
+ {
+ if (crn == 0 && opcode_1 == 0)
+ {
+ if (crm == 0)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_MAIN_ID];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_CACHE_TYPE];
+
+ if (opcode_2 == 3)
+ return cpu->CP15[CP15_TLB_TYPE];
+
+ if (opcode_2 == 5)
+ return cpu->CP15[CP15_CPU_ID];
+ }
+ else if (crm == 1)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_PROCESSOR_FEATURE_0];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_PROCESSOR_FEATURE_1];
+
+ if (opcode_2 == 2)
+ return cpu->CP15[CP15_DEBUG_FEATURE_0];
+
+ if (opcode_2 == 4)
+ return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0];
+
+ if (opcode_2 == 5)
+ return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1];
+
+ if (opcode_2 == 6)
+ return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2];
+
+ if (opcode_2 == 7)
+ return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3];
+ }
+ else if (crm == 2)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_ISA_FEATURE_0];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_ISA_FEATURE_1];
+
+ if (opcode_2 == 2)
+ return cpu->CP15[CP15_ISA_FEATURE_2];
+
+ if (opcode_2 == 3)
+ return cpu->CP15[CP15_ISA_FEATURE_3];
+
+ if (opcode_2 == 4)
+ return cpu->CP15[CP15_ISA_FEATURE_4];
+ }
+ }
+
+ if (crn == 1 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_CONTROL];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_AUXILIARY_CONTROL];
+
+ if (opcode_2 == 2)
+ return cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
+ }
+
+ if (crn == 2 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1];
+
+ if (opcode_2 == 2)
+ return cpu->CP15[CP15_TRANSLATION_BASE_CONTROL];
+ }
+
+ if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ return cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL];
+
+ if (crn == 5 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_FAULT_STATUS];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_INSTR_FAULT_STATUS];
+ }
+
+ if (crn == 6 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_FAULT_ADDRESS];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_WFAR];
+ }
+
+ if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0)
+ return cpu->CP15[CP15_PHYS_ADDRESS];
+
+ if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ return cpu->CP15[CP15_DATA_CACHE_LOCKDOWN];
+
+ if (crn == 10 && opcode_1 == 0)
+ {
+ if (crm == 0 && opcode_2 == 0)
+ return cpu->CP15[CP15_TLB_LOCKDOWN];
+
+ if (crm == 2)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_PRIMARY_REGION_REMAP];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_NORMAL_REGION_REMAP];
+ }
+ }
+
+ if (crn == 13 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_PID];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_CONTEXT_ID];
+
+ if (opcode_2 == 4)
+ return cpu->CP15[CP15_THREAD_PRW];
+ }
+
+ if (crn == 15)
+ {
+ if (opcode_1 == 0 && crm == 12)
+ {
+ if (opcode_2 == 0)
+ return cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
+
+ if (opcode_2 == 1)
+ return cpu->CP15[CP15_CYCLE_COUNTER];
+
+ if (opcode_2 == 2)
+ return cpu->CP15[CP15_COUNT_0];
+
+ if (opcode_2 == 3)
+ return cpu->CP15[CP15_COUNT_1];
+ }
+
+ if (opcode_1 == 5 && opcode_2 == 2)
+ {
+ if (crm == 5)
+ return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
+
+ if (crm == 6)
+ return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS];
+
+ if (crm == 7)
+ return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE];
+ }
+
+ if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
+ return cpu->CP15[CP15_TLB_DEBUG_CONTROL];
+ }
+ }
+
+ LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2);
+ return 0;
+}
+
+// Write to the CP15 registers. Used with implementation of the MCR instruction.
+// Note that since the 3DS does not have the hypervisor extensions, these registers
+// are not implemented.
+void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
+{
+ if (InAPrivilegedMode(cpu))
+ {
+ if (crn == 1 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_CONTROL] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_AUXILIARY_CONTROL] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
+ }
+ else if (crn == 2 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
+ }
+ else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ {
+ cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
+ }
+ else if (crn == 5 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_FAULT_STATUS] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_INSTR_FAULT_STATUS] = value;
+ }
+ else if (crn == 6 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_FAULT_ADDRESS] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_WFAR] = value;
+ }
+ else if (crn == 7 && opcode_1 == 0)
+ {
+ if (crm == 0 && opcode_2 == 4)
+ {
+ cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value;
+ }
+ else if (crm == 4 && opcode_2 == 0)
+ {
+ // NOTE: Not entirely accurate. This should do permission checks.
+ cpu->CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
+ }
+ else if (crm == 5)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value;
+ else if (opcode_2 == 6)
+ cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
+ else if (opcode_2 == 7)
+ cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
+ }
+ else if (crm == 6)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_INVALIDATE_DATA_CACHE] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
+ }
+ else if (crm == 7 && opcode_2 == 0)
+ {
+ cpu->CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
+ }
+ else if (crm == 10)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_CLEAN_DATA_CACHE] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
+ }
+ else if (crm == 14)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
+ }
+ }
+ else if (crn == 8 && opcode_1 == 0)
+ {
+ LOG_WARNING(Core_ARM11, "TLB operations not fully implemented.");
+
+ if (crm == 5)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_INVALIDATE_ITLB] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
+ else if (opcode_2 == 3)
+ cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
+ }
+ else if (crm == 6)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_INVALIDATE_DTLB] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
+ else if (opcode_2 == 3)
+ cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
+ }
+ else if (crm == 7)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_INVALIDATE_UTLB] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value;
+ else if (opcode_2 == 3)
+ cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
+ }
+ }
+ else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ {
+ cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
+ }
+ else if (crn == 10 && opcode_1 == 0)
+ {
+ if (crm == 0 && opcode_2 == 0)
+ {
+ cpu->CP15[CP15_TLB_LOCKDOWN] = value;
+ }
+ else if (crm == 2)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_PRIMARY_REGION_REMAP] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_NORMAL_REGION_REMAP] = value;
+ }
+ }
+ else if (crn == 13 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_PID] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_CONTEXT_ID] = value;
+ else if (opcode_2 == 3)
+ cpu->CP15[CP15_THREAD_URO] = value;
+ else if (opcode_2 == 4)
+ cpu->CP15[CP15_THREAD_PRW] = value;
+ }
+ else if (crn == 15)
+ {
+ if (opcode_1 == 0 && crm == 12)
+ {
+ if (opcode_2 == 0)
+ cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
+ else if (opcode_2 == 1)
+ cpu->CP15[CP15_CYCLE_COUNTER] = value;
+ else if (opcode_2 == 2)
+ cpu->CP15[CP15_COUNT_0] = value;
+ else if (opcode_2 == 3)
+ cpu->CP15[CP15_COUNT_1] = value;
+ }
+ else if (opcode_1 == 5)
+ {
+ if (crm == 4)
+ {
+ if (opcode_2 == 2)
+ cpu->CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
+ else if (opcode_2 == 4)
+ cpu->CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
+ }
+ else if (crm == 5 && opcode_2 == 2)
+ {
+ cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
+ }
+ else if (crm == 6 && opcode_2 == 2)
+ {
+ cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
+ }
+ else if (crm == 7 && opcode_2 == 2)
+ {
+ cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
+ }
+ }
+ else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
+ {
+ cpu->CP15[CP15_TLB_DEBUG_CONTROL] = value;
+ }
+ }
+ }
+
+ // Unprivileged registers
+ if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4)
+ {
+ cpu->CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
+ }
+ else if (crn == 7 && opcode_1 == 0 && crm == 10)
+ {
+ if (opcode_2 == 4)
+ cpu->CP15[CP15_DATA_SYNC_BARRIER] = value;
+ else if (opcode_2 == 5)
+ cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value;
+
+ }
+ else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
+ {
+ cpu->CP15[CP15_THREAD_UPRW] = value;
+ }
+}
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index 5be3a561f..6c89774eb 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -50,55 +50,134 @@ enum {
EXCLUSIVE_TAG,
EXCLUSIVE_STATE,
EXCLUSIVE_RESULT,
- CP15_BASE,
- CP15_C0 = CP15_BASE,
- CP15_C0_C0 = CP15_C0,
- CP15_MAIN_ID = CP15_C0_C0,
+
+ MAX_REG_NUM,
+};
+
+// VFP system registers
+enum {
+ VFP_FPSID,
+ VFP_FPSCR,
+ VFP_FPEXC,
+
+ // Not an actual register.
+ // All VFP system registers should be defined above this.
+ VFP_SYSTEM_REGISTER_COUNT
+};
+
+enum CP15Register {
+ // c0 - Information registers
+ CP15_MAIN_ID,
CP15_CACHE_TYPE,
CP15_TCM_STATUS,
CP15_TLB_TYPE,
- CP15_C0_C1,
- CP15_PROCESSOR_FEATURE_0 = CP15_C0_C1,
+ CP15_CPU_ID,
+ CP15_PROCESSOR_FEATURE_0,
CP15_PROCESSOR_FEATURE_1,
CP15_DEBUG_FEATURE_0,
CP15_AUXILIARY_FEATURE_0,
- CP15_C1_C0,
- CP15_CONTROL = CP15_C1_C0,
+ CP15_MEMORY_MODEL_FEATURE_0,
+ CP15_MEMORY_MODEL_FEATURE_1,
+ CP15_MEMORY_MODEL_FEATURE_2,
+ CP15_MEMORY_MODEL_FEATURE_3,
+ CP15_ISA_FEATURE_0,
+ CP15_ISA_FEATURE_1,
+ CP15_ISA_FEATURE_2,
+ CP15_ISA_FEATURE_3,
+ CP15_ISA_FEATURE_4,
+
+ // c1 - Control registers
+ CP15_CONTROL,
CP15_AUXILIARY_CONTROL,
CP15_COPROCESSOR_ACCESS_CONTROL,
- CP15_C2,
- CP15_C2_C0 = CP15_C2,
- CP15_TRANSLATION_BASE = CP15_C2_C0,
- CP15_TRANSLATION_BASE_TABLE_0 = CP15_TRANSLATION_BASE,
+
+ // c2 - Translation table registers
+ CP15_TRANSLATION_BASE_TABLE_0,
CP15_TRANSLATION_BASE_TABLE_1,
CP15_TRANSLATION_BASE_CONTROL,
CP15_DOMAIN_ACCESS_CONTROL,
CP15_RESERVED,
- /* Fault status */
+
+ // c5 - Fault status registers
CP15_FAULT_STATUS,
CP15_INSTR_FAULT_STATUS,
CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
CP15_INST_FSR,
- /* Fault Address register */
+
+ // c6 - Fault Address registers
CP15_FAULT_ADDRESS,
CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
CP15_WFAR,
CP15_IFAR,
+
+ // c7 - Cache operation registers
+ CP15_WAIT_FOR_INTERRUPT,
+ CP15_PHYS_ADDRESS,
+ CP15_INVALIDATE_INSTR_CACHE,
+ CP15_INVALIDATE_INSTR_CACHE_USING_MVA,
+ CP15_INVALIDATE_INSTR_CACHE_USING_INDEX,
+ CP15_FLUSH_PREFETCH_BUFFER,
+ CP15_FLUSH_BRANCH_TARGET_CACHE,
+ CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY,
+ CP15_INVALIDATE_DATA_CACHE,
+ CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
+ CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
+ CP15_INVALIDATE_DATA_AND_INSTR_CACHE,
+ CP15_CLEAN_DATA_CACHE,
+ CP15_CLEAN_DATA_CACHE_LINE_USING_MVA,
+ CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX,
+ CP15_DATA_SYNC_BARRIER,
+ CP15_DATA_MEMORY_BARRIER,
+ CP15_CLEAN_AND_INVALIDATE_DATA_CACHE,
+ CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
+ CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
+
+ // c8 - TLB operations
+ CP15_INVALIDATE_ITLB,
+ CP15_INVALIDATE_ITLB_SINGLE_ENTRY,
+ CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH,
+ CP15_INVALIDATE_ITLB_ENTRY_ON_MVA,
+ CP15_INVALIDATE_DTLB,
+ CP15_INVALIDATE_DTLB_SINGLE_ENTRY,
+ CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH,
+ CP15_INVALIDATE_DTLB_ENTRY_ON_MVA,
+ CP15_INVALIDATE_UTLB,
+ CP15_INVALIDATE_UTLB_SINGLE_ENTRY,
+ CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH,
+ CP15_INVALIDATE_UTLB_ENTRY_ON_MVA,
+
+ // c9 - Data cache lockdown register
+ CP15_DATA_CACHE_LOCKDOWN,
+
+ // c10 - TLB/Memory map registers
+ CP15_TLB_LOCKDOWN,
+ CP15_PRIMARY_REGION_REMAP,
+ CP15_NORMAL_REGION_REMAP,
+
+ // c13 - Thread related registers
CP15_PID,
CP15_CONTEXT_ID,
CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W)
CP15_THREAD_PRW, // Thread ID register - Privileged R/W only.
- CP15_TLB_FAULT_ADDR, /* defined by SkyEye */
- CP15_TLB_FAULT_STATUS, /* defined by SkyEye */
- /* VFP registers */
- VFP_BASE,
- VFP_FPSID = VFP_BASE,
- VFP_FPSCR,
- VFP_FPEXC,
- MAX_REG_NUM,
-};
+ // c15 - Performance and TLB lockdown registers
+ CP15_PERFORMANCE_MONITOR_CONTROL,
+ CP15_CYCLE_COUNTER,
+ CP15_COUNT_0,
+ CP15_COUNT_1,
+ CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY,
+ CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY,
+ CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS,
+ CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS,
+ CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE,
+ CP15_TLB_DEBUG_CONTROL,
+
+ // Skyeye defined
+ CP15_TLB_FAULT_ADDR,
+ CP15_TLB_FAULT_STATUS,
-#define CP15(idx) (idx - CP15_BASE)
-#define VFP_OFFSET(x) (x - VFP_BASE)
+ // Not an actual register.
+ // All registers should be defined above this.
+ CP15_REGISTER_COUNT,
+};
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index c1a19fecc..470f9508d 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -17,9 +17,10 @@
#pragma once
+#include <unordered_map>
+
#include "common/common_types.h"
#include "core/arm/skyeye_common/arm_regformat.h"
-#include "core/arm/skyeye_common/skyeye_defs.h"
#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
#define BIT(s, n) ((s >> (n)) & 1)
@@ -53,26 +54,11 @@ typedef u64 ARMdword; // must be 64 bits wide
typedef u32 ARMword; // must be 32 bits wide
typedef u16 ARMhword; // must be 16 bits wide
typedef u8 ARMbyte; // must be 8 bits wide
-typedef struct ARMul_State ARMul_State;
-
-typedef unsigned ARMul_CPInits(ARMul_State* state);
-typedef unsigned ARMul_CPExits(ARMul_State* state);
-typedef unsigned ARMul_LDCs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
-typedef unsigned ARMul_STCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
-typedef unsigned ARMul_MRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
-typedef unsigned ARMul_MCRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
-typedef unsigned ARMul_MRRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
-typedef unsigned ARMul_MCRRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
-typedef unsigned ARMul_CDPs(ARMul_State* state, unsigned type, ARMword instr);
-typedef unsigned ARMul_CPReads(ARMul_State* state, unsigned reg, ARMword* value);
-typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value);
#define VFP_REG_NUM 64
struct ARMul_State
{
ARMword Emulate; // To start and stop emulation
- unsigned EndCondition; // Reason for stopping
- unsigned ErrorCode; // Type of illegal instruction
// Order of the following register should not be modified
ARMword Reg[16]; // The current register file
@@ -91,15 +77,15 @@ struct ARMul_State
ARMword exclusive_tag; // The address for which the local monitor is in exclusive access mode
ARMword exclusive_state;
ARMword exclusive_result;
- ARMword CP15[VFP_BASE - CP15_BASE];
- ARMword VFP[3]; // FPSID, FPSCR, and FPEXC
+ ARMword CP15[CP15_REGISTER_COUNT];
+
+ // FPSID, FPSCR, and FPEXC
+ ARMword VFP[VFP_SYSTEM_REGISTER_COUNT];
// VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
// VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
// and only 32 singleword registers are accessible (S0-S31).
ARMword ExtReg[VFP_REG_NUM];
/* ---- End of the ordered registers ---- */
-
- ARMword RegBank[7][16]; // all the registers
ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
unsigned int shifter_carry_out;
@@ -112,24 +98,7 @@ struct ARMul_State
unsigned long long NumInstrs; // The number of instructions executed
unsigned NumInstrsToExecute;
- unsigned NextInstr;
- unsigned VectorCatch; // Caught exception mask
-
- ARMul_CPInits* CPInit[16]; // Coprocessor initialisers
- ARMul_CPExits* CPExit[16]; // Coprocessor finalisers
- ARMul_LDCs* LDC[16]; // LDC instruction
- ARMul_STCs* STC[16]; // STC instruction
- ARMul_MRCs* MRC[16]; // MRC instruction
- ARMul_MCRs* MCR[16]; // MCR instruction
- ARMul_MRRCs* MRRC[16]; // MRRC instruction
- ARMul_MCRRs* MCRR[16]; // MCRR instruction
- ARMul_CDPs* CDP[16]; // CDP instruction
- ARMul_CPReads* CPRead[16]; // Read CP register
- ARMul_CPWrites* CPWrite[16]; // Write CP register
- unsigned char* CPData[16]; // Coprocessor data
- unsigned char const* CPRegWords[16]; // Map of coprocessor register sizes
-
- unsigned NresetSig; // Reset the processor
+ unsigned NresetSig; // Reset the processor
unsigned NfiqSig;
unsigned NirqSig;
@@ -171,13 +140,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
*/
unsigned lateabtSig;
- bool Aborted; // Sticky flag for aborts
- bool Reseted; // Sticky flag for Reset
- ARMword Inted, LastInted; // Sticky flags for interrupts
- ARMword Base; // Extra hand for base writeback
- ARMword AbortAddr; // To keep track of Prefetch aborts
- ARMword Vector; // Synthesize aborts in cycle modes
-
// For differentiating ARM core emulaiton.
bool is_v4; // Are we emulating a v4 architecture (or higher)?
bool is_v5; // Are we emulating a v5 architecture?
@@ -189,16 +151,9 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
// 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
int abort_model;
- // Added by ksh in 2005-10-1
- cpu_config_t* cpu;
-
- u32 CurrInstr;
- u32 last_pc; // The last PC executed
- u32 last_instr; // The last instruction executed
- u32 WriteAddr[17];
- u32 WriteData[17];
- u32 WritePc[17];
- u32 CurrWrite;
+ // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per
+ // process for our purposes), not per ARMul_State (which tracks CPU core state).
+ std::unordered_map<u32, int> instruction_cache;
};
/***************************************************************************\
@@ -284,34 +239,6 @@ enum {
ARMul_INC = 3
};
-enum {
- ARMul_CP13_R0_FIQ = 0x1,
- ARMul_CP13_R0_IRQ = 0x2,
- ARMul_CP13_R8_PMUS = 0x1,
-
- ARMul_CP14_R0_ENABLE = 0x0001,
- ARMul_CP14_R0_CLKRST = 0x0004,
- ARMul_CP14_R0_CCD = 0x0008,
- ARMul_CP14_R0_INTEN0 = 0x0010,
- ARMul_CP14_R0_INTEN1 = 0x0020,
- ARMul_CP14_R0_INTEN2 = 0x0040,
- ARMul_CP14_R0_FLAG0 = 0x0100,
- ARMul_CP14_R0_FLAG1 = 0x0200,
- ARMul_CP14_R0_FLAG2 = 0x0400,
- ARMul_CP14_R10_MOE_IB = 0x0004,
- ARMul_CP14_R10_MOE_DB = 0x0008,
- ARMul_CP14_R10_MOE_BT = 0x000c,
- ARMul_CP15_R1_ENDIAN = 0x0080,
- ARMul_CP15_R1_ALIGN = 0x0002,
- ARMul_CP15_R5_X = 0x0400,
- ARMul_CP15_R5_ST_ALIGN = 0x0001,
- ARMul_CP15_R5_IMPRE = 0x0406,
- ARMul_CP15_R5_MMU_EXCPT = 0x0400,
- ARMul_CP15_DBCON_M = 0x0100,
- ARMul_CP15_DBCON_E1 = 0x000c,
- ARMul_CP15_DBCON_E0 = 0x0003
-};
-
/***************************************************************************\
* Definitons of things in the host environment *
\***************************************************************************/
@@ -357,3 +284,7 @@ extern u32 ARMul_SignedSatQ(s32, u8, bool*);
extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
extern bool InBigEndianMode(ARMul_State*);
+extern bool InAPrivilegedMode(ARMul_State*);
+
+extern u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
+extern void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 2a1c50779..7e0965052 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -38,16 +38,6 @@ enum : u32 {
INTBITS = 0x1C0,
};
-// Different ways to start the next instruction.
-enum {
- SEQ = 0,
- NONSEQ = 1,
- PCINCEDSEQ = 2,
- PCINCEDNONSEQ = 3,
- PRIMEPIPE = 4,
- RESUME = 8
-};
-
// Values for Emulate.
enum {
STOP = 0, // Stop
@@ -55,14 +45,3 @@ enum {
ONCE = 2, // Execute just one interation
RUN = 3 // Continuous execution
};
-
-#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
-
-// Coprocessor support functions.
-extern void ARMul_CoProInit(ARMul_State*);
-extern void ARMul_CoProExit(ARMul_State*);
-extern void ARMul_CoProAttach(ARMul_State*, unsigned, ARMul_CPInits*,
- ARMul_CPExits*, ARMul_LDCs*, ARMul_STCs*,
- ARMul_MRCs*, ARMul_MCRs*, ARMul_MRRCs*, ARMul_MCRRs*,
- ARMul_CDPs*, ARMul_CPReads*, ARMul_CPWrites*);
-extern void ARMul_CoProDetach(ARMul_State*, unsigned);
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
index 22e564c3d..c67d7209b 100644
--- a/src/core/arm/skyeye_common/armmmu.h
+++ b/src/core/arm/skyeye_common/armmmu.h
@@ -20,7 +20,9 @@
#pragma once
-#include "core/mem_map.h"
+#include "common/swap.h"
+
+#include "core/memory.h"
#include "core/arm/skyeye_common/armdefs.h"
// Register numbers in the MMU
diff --git a/src/core/arm/skyeye_common/armos.h b/src/core/arm/skyeye_common/armos.h
deleted file mode 100644
index 1217a728b..000000000
--- a/src/core/arm/skyeye_common/armos.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* armos.h -- ARMulator OS definitions: ARM6 Instruction Emulator.
- Copyright (C) 1994 Advanced RISC Machines Ltd.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-//
-// SWI Numbers
-//
-
-#define SWI_Syscall 0x0
-#define SWI_Exit 0x1
-#define SWI_Read 0x3
-#define SWI_Write 0x4
-#define SWI_Open 0x5
-#define SWI_Close 0x6
-#define SWI_Seek 0x13
-#define SWI_Rename 0x26
-#define SWI_Break 0x11
-
-#define SWI_Times 0x2b
-#define SWI_Brk 0x2d
-
-#define SWI_Mmap 0x5a
-#define SWI_Munmap 0x5b
-#define SWI_Mmap2 0xc0
-
-#define SWI_GetUID32 0xc7
-#define SWI_GetGID32 0xc8
-#define SWI_GetEUID32 0xc9
-#define SWI_GetEGID32 0xca
-
-#define SWI_ExitGroup 0xf8
-
-#define SWI_Uname 0x7a
-#define SWI_Fcntl 0xdd
-#define SWI_Fstat64 0xc5
-#define SWI_Gettimeofday 0x4e
-#define SWI_Set_tls 0xf0005
-
-#define SWI_Breakpoint 0x180000 /* see gdb's tm-arm.h */
-
diff --git a/src/core/arm/skyeye_common/skyeye_defs.h b/src/core/arm/skyeye_common/skyeye_defs.h
deleted file mode 100644
index edf6097e0..000000000
--- a/src/core/arm/skyeye_common/skyeye_defs.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include "common/common_types.h"
-
-struct cpu_config_t
-{
- const char* cpu_arch_name; // CPU architecture version name.e.g. ARMv4T
- const char* cpu_name; // CPU name. e.g. ARM7TDMI or ARM720T
- u32 cpu_val; // CPU value; also call MMU ID or processor id;see
- // ARM Architecture Reference Manual B2-6
- u32 cpu_mask; // cpu_val's mask.
- u32 cachetype; // CPU cache type
-};
-
-enum {
- // No exception
- No_exp = 0,
- // Memory allocation exception
- Malloc_exp,
- // File open exception
- File_open_exp,
- // DLL open exception
- Dll_open_exp,
- // Invalid argument exception
- Invarg_exp,
- // Invalid module exception
- Invmod_exp,
- // wrong format exception for config file parsing
- Conf_format_exp,
- // some reference excess the predefiend range. Such as the index out of array range
- Excess_range_exp,
- // Can not find the desirable result
- Not_found_exp,
- // Unknown exception
- Unknown_exp
-};
-
-typedef u32 addr_t;
diff --git a/src/core/arm/skyeye_common/vfp/asm_vfp.h b/src/core/arm/skyeye_common/vfp/asm_vfp.h
index ccb7cf4d7..1187924f4 100644
--- a/src/core/arm/skyeye_common/vfp/asm_vfp.h
+++ b/src/core/arm/skyeye_common/vfp/asm_vfp.h
@@ -7,15 +7,15 @@
#pragma once
-// FPSID Information
+// ARM11 MPCore FPSID Information
// Note that these are used as values and not as flags.
enum : u32 {
- VFP_FPSID_IMPLMEN = 0, // Implementation code. Should be the same as cp15 0 c0 0
- VFP_FPSID_SW = 0, // Software emulation bit value
- VFP_FPSID_SUBARCH = 0x2, // Subarchitecture version number
- VFP_FPSID_PARTNUM = 0x1, // Part number
- VFP_FPSID_VARIANT = 0x1, // Variant number
- VFP_FPSID_REVISION = 0x1 // Revision number
+ VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0
+ VFP_FPSID_SW = 0, // Software emulation bit value
+ VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number
+ VFP_FPSID_PARTNUM = 0x20, // Part number
+ VFP_FPSID_VARIANT = 0xB, // Variant number
+ VFP_FPSID_REVISION = 0x4 // Revision number
};
// FPEXC bits
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index 6286e7b62..b88d47750 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -20,7 +20,6 @@
/* Note: this file handles interface with arm core and vfp registers */
-#include "common/common.h"
#include "common/logging/log.h"
#include "core/arm/skyeye_common/armdefs.h"
@@ -29,304 +28,26 @@
unsigned VFPInit(ARMul_State* state)
{
- state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
- VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
- state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0;
- state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0;
+ state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
+ VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
+ state->VFP[VFP_FPEXC] = 0;
+ state->VFP[VFP_FPSCR] = 0;
return 0;
}
-unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
-{
- /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int OPC_1 = BITS(instr, 21, 23);
- int Rt = BITS(instr, 12, 15);
- int CRn = BITS(instr, 16, 19);
- int CRm = BITS(instr, 0, 3);
- int OPC_2 = BITS(instr, 5, 7);
-
- /* TODO check access permission */
-
- /* CRn/opc1 CRm/opc2 */
-
- if (CoProc == 10 || CoProc == 11)
- {
- if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
- {
- /* VMOV r to s */
- /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
- VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value);
- return ARMul_DONE;
- }
-
- if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
- {
- VMRS(state, CRn, Rt, value);
- return ARMul_DONE;
- }
- }
- LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
- instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
-
- return ARMul_CANT;
-}
-
-unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
-{
- /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int OPC_1 = BITS(instr, 21, 23);
- int Rt = BITS(instr, 12, 15);
- int CRn = BITS(instr, 16, 19);
- int CRm = BITS(instr, 0, 3);
- int OPC_2 = BITS(instr, 5, 7);
-
- /* TODO check access permission */
-
- /* CRn/opc1 CRm/opc2 */
- if (CoProc == 10 || CoProc == 11)
- {
- if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
- {
- /* VMOV s to r */
- /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
- VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value);
- return ARMul_DONE;
- }
-
- if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
- {
- VMSR(state, CRn, Rt);
- return ARMul_DONE;
- }
-
- if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
- {
- VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
- return ARMul_DONE;
- }
-
- if (CoProc == 11 && CRm == 0)
- {
- VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
- return ARMul_DONE;
- }
- }
- LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
- instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
-
- return ARMul_CANT;
-}
-
-unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
-{
- /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int OPC_1 = BITS(instr, 4, 7);
- int Rt = BITS(instr, 12, 15);
- int Rt2 = BITS(instr, 16, 19);
- int CRm = BITS(instr, 0, 3);
-
- if (CoProc == 10 || CoProc == 11)
- {
- if (CoProc == 10 && (OPC_1 & 0xD) == 1)
- {
- VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
- return ARMul_DONE;
- }
-
- if (CoProc == 11 && (OPC_1 & 0xD) == 1)
- {
- /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
- VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
- return ARMul_DONE;
- }
- }
- LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
- instr, CoProc, OPC_1, Rt, Rt2, CRm);
-
- return ARMul_CANT;
-}
-
-unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
-{
- /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int OPC_1 = BITS(instr, 4, 7);
- int Rt = BITS(instr, 12, 15);
- int Rt2 = BITS(instr, 16, 19);
- int CRm = BITS(instr, 0, 3);
-
- /* TODO check access permission */
-
- /* CRn/opc1 CRm/opc2 */
-
- if (CoProc == 11 || CoProc == 10)
- {
- if (CoProc == 10 && (OPC_1 & 0xD) == 1)
- {
- VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
- return ARMul_DONE;
- }
-
- if (CoProc == 11 && (OPC_1 & 0xD) == 1)
- {
- /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
- VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
- return ARMul_DONE;
- }
- }
- LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
- instr, CoProc, OPC_1, Rt, Rt2, CRm);
-
- return ARMul_CANT;
-}
-
-unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
-{
- /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int CRd = BITS(instr, 12, 15);
- int Rn = BITS(instr, 16, 19);
- int imm8 = BITS(instr, 0, 7);
- int P = BIT(instr, 24);
- int U = BIT(instr, 23);
- int D = BIT(instr, 22);
- int W = BIT(instr, 21);
-
- /* TODO check access permission */
-
- /* VSTM */
- if ( (P|U|D|W) == 0 ) {
- LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
- exit(-1);
- }
- if (CoProc == 10 || CoProc == 11) {
-#if 1
- if (P == 0 && U == 0 && W == 0) {
- LOG_ERROR(Core_ARM11, "VSTM Related encodings\n");
- exit(-1);
- }
- if (P == U && W == 1) {
- LOG_ERROR(Core_ARM11, "UNDEFINED\n");
- exit(-1);
- }
-#endif
-
- if (P == 1 && W == 0)
- {
- return VSTR(state, type, instr, value);
- }
-
- if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
- {
- return VPUSH(state, type, instr, value);
- }
-
- return VSTM(state, type, instr, value);
- }
- LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
- instr, CoProc, CRd, Rn, imm8, P, U, D, W);
-
- return ARMul_CANT;
-}
-
-unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
+void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
{
- /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int CRd = BITS(instr, 12, 15);
- int Rn = BITS(instr, 16, 19);
- int imm8 = BITS(instr, 0, 7);
- int P = BIT(instr, 24);
- int U = BIT(instr, 23);
- int D = BIT(instr, 22);
- int W = BIT(instr, 21);
-
- /* TODO check access permission */
-
- if ( (P|U|D|W) == 0 ) {
- LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__);
- exit(-1);
- }
- if (CoProc == 10 || CoProc == 11)
+ if (reg == 1)
{
- if (P == 1 && W == 0)
- {
- return VLDR(state, type, instr, value);
- }
-
- if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
- {
- return VPOP(state, type, instr, value);
- }
-
- return VLDM(state, type, instr, value);
+ state->VFP[VFP_FPSCR] = state->Reg[Rt];
}
- LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
- instr, CoProc, CRd, Rn, imm8, P, U, D, W);
-
- return ARMul_CANT;
-}
-
-unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
-{
- /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
- int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
- int OPC_1 = BITS(instr, 20, 23);
- int CRd = BITS(instr, 12, 15);
- int CRn = BITS(instr, 16, 19);
- int CRm = BITS(instr, 0, 3);
- int OPC_2 = BITS(instr, 5, 7);
-
- /* TODO check access permission */
-
- /* CRn/opc1 CRm/opc2 */
-
- if (CoProc == 10 || CoProc == 11)
+ else if (reg == 8)
{
- if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0)
- {
- unsigned int single = BIT(instr, 8) == 0;
- unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
- unsigned int imm;
- instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm
-
- if (single)
- imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19;
- else
- imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16;
-
- VMOVI(state, single, d, imm);
- return ARMul_DONE;
- }
-
- if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
- {
- unsigned int single = BIT(instr, 8) == 0;
- unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
- unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4);
- VMOVR(state, single, d, m);
- return ARMul_DONE;
- }
-
- int exceptions = 0;
- if (CoProc == 10)
- exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
- else
- exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
-
- vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
-
- return ARMul_DONE;
+ state->VFP[VFP_FPEXC] = state->Reg[Rt];
}
- LOG_WARNING(Core_ARM11, "Can't identify %x\n", instr);
- return ARMul_CANT;
}
-/* ----------- MRC ------------ */
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
{
if (to_arm)
@@ -338,43 +59,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword*
state->ExtReg[n] = *value;
}
}
-void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value)
-{
- if (reg == 1)
- {
- if (Rt != 15)
- {
- *value = state->VFP[VFP_OFFSET(VFP_FPSCR)];
- }
- else
- {
- *value = state->VFP[VFP_OFFSET(VFP_FPSCR)] ;
- }
- }
- else
- {
- switch (reg)
- {
- case 0:
- *value = state->VFP[VFP_OFFSET(VFP_FPSID)];
- break;
- case 6:
- /* MVFR1, VFPv3 only ? */
- LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", Rt);
- break;
- case 7:
- /* MVFR0, VFPv3 only? */
- LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", Rt);
- break;
- case 8:
- *value = state->VFP[VFP_OFFSET(VFP_FPEXC)];
- break;
- default:
- LOG_TRACE(Core_ARM11, "\tSUBARCHITECTURE DEFINED\n");
- break;
- }
- }
-}
+
void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2)
{
if (to_arm)
@@ -402,301 +87,6 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor
}
}
-/* ----------- MCR ------------ */
-void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
-{
- if (reg == 1)
- {
- state->VFP[VFP_OFFSET(VFP_FPSCR)] = state->Reg[Rt];
- }
- else if (reg == 8)
- {
- state->VFP[VFP_OFFSET(VFP_FPEXC)] = state->Reg[Rt];
- }
-}
-
-/* Memory operation are not inlined, as old Interpreter and Fast interpreter
- don't have the same memory operation interface.
- Old interpreter framework does one access to coprocessor per data, and
- handles already data write, as well as address computation,
- which is not the case for Fast interpreter. Therefore, implementation
- of vfp instructions in old interpreter and fast interpreter are separate. */
-
-/* ----------- STC ------------ */
-int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
-{
- static int i = 0;
- static int single_reg, add, d, n, imm32, regs;
- if (type == ARMul_FIRST)
- {
- single_reg = BIT(instr, 8) == 0; // Double precision
- add = BIT(instr, 23);
- imm32 = BITS(instr, 0,7)<<2; // may not be used
- d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */
- n = BITS(instr, 16, 19); // destination register
-
- i = 0;
- regs = 1;
-
- return ARMul_DONE;
- }
- else if (type == ARMul_DATA)
- {
- if (single_reg)
- {
- *value = state->ExtReg[d+i];
- i++;
- if (i < regs)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- else
- {
- /* FIXME Careful of endianness, may need to rework this */
- *value = state->ExtReg[d*2+i];
- i++;
- if (i < regs*2)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- }
-
- return -1;
-}
-int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
-{
- static int i = 0;
- static int single_regs, d, imm32, regs;
- if (type == ARMul_FIRST)
- {
- single_regs = BIT(instr, 8) == 0; // Single precision
- d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
- imm32 = BITS(instr, 0,7)<<2; // may not be used
- regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd
-
- state->Reg[R13] = state->Reg[R13] - imm32;
-
- i = 0;
-
- return ARMul_DONE;
- }
- else if (type == ARMul_DATA)
- {
- if (single_regs)
- {
- *value = state->ExtReg[d + i];
- i++;
- if (i < regs)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- else
- {
- /* FIXME Careful of endianness, may need to rework this */
- *value = state->ExtReg[d*2 + i];
- i++;
- if (i < regs*2)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- }
-
- return -1;
-}
-int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
-{
- static int i = 0;
- static int single_regs, add, wback, d, n, imm32, regs;
- if (type == ARMul_FIRST)
- {
- single_regs = BIT(instr, 8) == 0; // Single precision
- add = BIT(instr, 23);
- wback = BIT(instr, 21); // write-back
- d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
- n = BITS(instr, 16, 19); // destination register
- imm32 = BITS(instr, 0,7) * 4; // may not be used
- regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd
-
- if (wback) {
- state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
- }
-
- i = 0;
-
- return ARMul_DONE;
- }
- else if (type == ARMul_DATA)
- {
- if (single_regs)
- {
- *value = state->ExtReg[d + i];
- i++;
- if (i < regs)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- else
- {
- /* FIXME Careful of endianness, may need to rework this */
- *value = state->ExtReg[d*2 + i];
- i++;
- if (i < regs*2)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- }
-
- return -1;
-}
-
-/* ----------- LDC ------------ */
-int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
-{
- static int i = 0;
- static int single_regs, d, imm32, regs;
- if (type == ARMul_FIRST)
- {
- single_regs = BIT(instr, 8) == 0; // Single precision
- d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
- imm32 = BITS(instr, 0, 7)<<2; // may not be used
- regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd
-
- state->Reg[R13] = state->Reg[R13] + imm32;
-
- i = 0;
-
- return ARMul_DONE;
- }
- else if (type == ARMul_TRANSFER)
- {
- return ARMul_DONE;
- }
- else if (type == ARMul_DATA)
- {
- if (single_regs)
- {
- state->ExtReg[d + i] = value;
- i++;
- if (i < regs)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- else
- {
- /* FIXME Careful of endianness, may need to rework this */
- state->ExtReg[d*2 + i] = value;
- i++;
- if (i < regs*2)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- }
-
- return -1;
-}
-int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
-{
- static int i = 0;
- static int single_reg, add, d, n, imm32, regs;
- if (type == ARMul_FIRST)
- {
- single_reg = BIT(instr, 8) == 0; // Double precision
- add = BIT(instr, 23);
- imm32 = BITS(instr, 0, 7)<<2; // may not be used
- d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
- n = BITS(instr, 16, 19); // destination register
-
- i = 0;
- regs = 1;
-
- return ARMul_DONE;
- }
- else if (type == ARMul_TRANSFER)
- {
- return ARMul_DONE;
- }
- else if (type == ARMul_DATA)
- {
- if (single_reg)
- {
- state->ExtReg[d+i] = value;
- i++;
- if (i < regs)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- else
- {
- /* FIXME Careful of endianness, may need to rework this */
- state->ExtReg[d*2+i] = value;
- i++;
- if (i < regs*2)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- }
-
- return -1;
-}
-int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
-{
- static int i = 0;
- static int single_regs, add, wback, d, n, imm32, regs;
- if (type == ARMul_FIRST)
- {
- single_regs = BIT(instr, 8) == 0; // Single precision
- add = BIT(instr, 23);
- wback = BIT(instr, 21); // write-back
- d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
- n = BITS(instr, 16, 19); // destination register
- imm32 = BITS(instr, 0, 7) * 4; // may not be used
- regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd
-
- if (wback) {
- state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
- }
-
- i = 0;
-
- return ARMul_DONE;
- }
- else if (type == ARMul_DATA)
- {
- if (single_regs)
- {
- state->ExtReg[d + i] = value;
- i++;
- if (i < regs)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- else
- {
- /* FIXME Careful of endianness, may need to rework this */
- state->ExtReg[d*2 + i] = value;
- i++;
- if (i < regs*2)
- return ARMul_INC;
- else
- return ARMul_DONE;
- }
- }
-
- return -1;
-}
-
-/* ----------- CDP ------------ */
void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
{
if (single)
@@ -774,5 +164,5 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
fpscr |= exceptions;
- state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr;
+ state->VFP[VFP_FPSCR] = fpscr;
}
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 445a224bc..727350f14 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -25,16 +25,9 @@
#define VFP_DEBUG_UNIMPLEMENTED(x) LOG_ERROR(Core_ARM11, "in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__);
#define CHECK_VFP_ENABLED
-#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);}
+#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
unsigned VFPInit(ARMul_State* state);
-unsigned VFPMRC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
-unsigned VFPMCR(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
-unsigned VFPMRRC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
-unsigned VFPMCRR(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
-unsigned VFPSTC(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
-unsigned VFPLDC(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
-unsigned VFPCDP(ARMul_State* state, unsigned type, ARMword instr);
s32 vfp_get_float(ARMul_State* state, u32 reg);
void vfp_put_float(ARMul_State* state, s32 val, u32 reg);
@@ -44,23 +37,10 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
-// MRC
-void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value);
+void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value);
void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
-// MCR
-void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
-
-// STC
-int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value);
-int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value);
-int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value);
-
-// LDC
-int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value);
-int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value);
-int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value);
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 5d1b4e53f..ccc0212ab 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -35,9 +35,7 @@
#include <cstdio>
#include "common/common_types.h"
#include "core/arm/skyeye_common/armdefs.h"
-
-#define pr_info //printf
-#define pr_debug //printf
+#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#define do_div(n, base) {n/=base;}
@@ -239,33 +237,6 @@ struct vfp_single {
#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
-// Unpack a single-precision float. Note that this returns the magnitude
-// of the single-precision float mantissa with the 1. if necessary,
-// aligned to bit 30.
-static inline void vfp_single_unpack(vfp_single* s, s32 val)
-{
- u32 significand;
-
- s->sign = vfp_single_packed_sign(val) >> 16,
- s->exponent = vfp_single_packed_exponent(val);
-
- significand = (u32) val;
- significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
- if (s->exponent && s->exponent != 255)
- significand |= 0x40000000;
- s->significand = significand;
-}
-
-// Re-pack a single-precision float. This assumes that the float is
-// already normalised such that the MSB is bit 30, _not_ bit 31.
-static inline s32 vfp_single_pack(vfp_single* s)
-{
- u32 val = (s->sign << 16) +
- (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
- (s->significand >> VFP_SINGLE_LOW_BITS);
- return (s32)val;
-}
-
enum : u32 {
VFP_NUMBER = (1 << 0),
VFP_ZERO = (1 << 1),
@@ -297,6 +268,39 @@ static inline int vfp_single_type(vfp_single* s)
return type;
}
+// Unpack a single-precision float. Note that this returns the magnitude
+// of the single-precision float mantissa with the 1. if necessary,
+// aligned to bit 30.
+static inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
+{
+ s->sign = vfp_single_packed_sign(val) >> 16,
+ s->exponent = vfp_single_packed_exponent(val);
+
+ u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
+ if (s->exponent && s->exponent != 255)
+ significand |= 0x40000000;
+ s->significand = significand;
+
+ // If flush-to-zero mode is enabled, turn the denormal into zero.
+ // On a VFPv2 architecture, the sign of the zero is always positive.
+ if ((*fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_single_type(s) & VFP_DENORMAL) != 0) {
+ s->sign = 0;
+ s->exponent = 0;
+ s->significand = 0;
+ *fpscr |= FPSCR_IDC;
+ }
+}
+
+// Re-pack a single-precision float. This assumes that the float is
+// already normalised such that the MSB is bit 30, _not_ bit 31.
+static inline s32 vfp_single_pack(vfp_single* s)
+{
+ u32 val = (s->sign << 16) +
+ (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
+ (s->significand >> VFP_SINGLE_LOW_BITS);
+ return (s32)val;
+}
+
u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, u32 exceptions, const char* func);
@@ -331,24 +335,49 @@ struct vfp_double {
#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
+static inline int vfp_double_type(vfp_double* s)
+{
+ int type = VFP_NUMBER;
+ if (s->exponent == 2047) {
+ if (s->significand == 0)
+ type = VFP_INFINITY;
+ else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
+ type = VFP_QNAN;
+ else
+ type = VFP_SNAN;
+ } else if (s->exponent == 0) {
+ if (s->significand == 0)
+ type |= VFP_ZERO;
+ else
+ type |= VFP_DENORMAL;
+ }
+ return type;
+}
+
// Unpack a double-precision float. Note that this returns the magnitude
// of the double-precision float mantissa with the 1. if necessary,
// aligned to bit 62.
-static inline void vfp_double_unpack(vfp_double* s, s64 val)
+static inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
{
- u64 significand;
-
s->sign = vfp_double_packed_sign(val) >> 48;
s->exponent = vfp_double_packed_exponent(val);
- significand = (u64) val;
- significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
+ u64 significand = ((u64)val << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
if (s->exponent && s->exponent != 2047)
significand |= (1ULL << 62);
s->significand = significand;
+
+ // If flush-to-zero mode is enabled, turn the denormal into zero.
+ // On a VFPv2 architecture, the sign of the zero is always positive.
+ if ((*fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_double_type(s) & VFP_DENORMAL) != 0) {
+ s->sign = 0;
+ s->exponent = 0;
+ s->significand = 0;
+ *fpscr |= FPSCR_IDC;
+ }
}
-// Re-pack a double-precision float. This assumes that the float is
+// Re-pack a double-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
static inline s64 vfp_double_pack(vfp_double* s)
{
@@ -358,25 +387,6 @@ static inline s64 vfp_double_pack(vfp_double* s)
return (s64)val;
}
-static inline int vfp_double_type(vfp_double* s)
-{
- int type = VFP_NUMBER;
- if (s->exponent == 2047) {
- if (s->significand == 0)
- type = VFP_INFINITY;
- else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
- type = VFP_QNAN;
- else
- type = VFP_SNAN;
- } else if (s->exponent == 0) {
- if (s->significand == 0)
- type |= VFP_ZERO;
- else
- type |= VFP_DENORMAL;
- }
- return type;
-}
-
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
// A special flag to tell the normalisation code not to normalise.
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index d76d37fd4..ab9fec39d 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -291,7 +291,8 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32
vfp_double vdm, vdd, *vdp;
int ret, tm;
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
+
tm = vfp_double_type(&vdm);
if (tm & (VFP_NAN|VFP_INFINITY)) {
vdp = &vdd;
@@ -473,7 +474,7 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32
u32 exceptions = 0;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
tm = vfp_double_type(&vdm);
@@ -543,7 +544,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
int tm;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
/*
* Do we have a denormalised number?
@@ -624,7 +625,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
int tm;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
vfp_double_dump("VDM", &vdm);
/*
@@ -896,11 +897,11 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
struct vfp_double vdd, vdp, vdn, vdm;
u32 exceptions;
- vfp_double_unpack(&vdn, vfp_get_double(state, dn));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
if (vdn.exponent == 0 && vdn.significand)
vfp_double_normalise_denormal(&vdn);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
if (vdm.exponent == 0 && vdm.significand)
vfp_double_normalise_denormal(&vdm);
@@ -908,7 +909,7 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
if (negate & NEG_MULTIPLY)
vdp.sign = vfp_sign_negate(vdp.sign);
- vfp_double_unpack(&vdn, vfp_get_double(state, dd));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dd), &fpscr);
if (vdn.exponent == 0 && vdn.significand != 0)
vfp_double_normalise_denormal(&vdn);
@@ -969,11 +970,11 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
u32 exceptions;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdn, vfp_get_double(state, dn));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
if (vdn.exponent == 0 && vdn.significand)
vfp_double_normalise_denormal(&vdn);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
if (vdm.exponent == 0 && vdm.significand)
vfp_double_normalise_denormal(&vdm);
@@ -990,11 +991,11 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
u32 exceptions;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdn, vfp_get_double(state, dn));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
if (vdn.exponent == 0 && vdn.significand)
vfp_double_normalise_denormal(&vdn);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
if (vdm.exponent == 0 && vdm.significand)
vfp_double_normalise_denormal(&vdm);
@@ -1013,11 +1014,11 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
u32 exceptions;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdn, vfp_get_double(state, dn));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
if (vdn.exponent == 0 && vdn.significand)
vfp_double_normalise_denormal(&vdn);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
if (vdm.exponent == 0 && vdm.significand)
vfp_double_normalise_denormal(&vdm);
@@ -1035,11 +1036,11 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
u32 exceptions;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdn, vfp_get_double(state, dn));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
if (vdn.exponent == 0 && vdn.significand)
vfp_double_normalise_denormal(&vdn);
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
if (vdm.exponent == 0 && vdm.significand)
vfp_double_normalise_denormal(&vdm);
@@ -1063,8 +1064,8 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
int tm, tn;
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
- vfp_double_unpack(&vdn, vfp_get_double(state, dn));
- vfp_double_unpack(&vdm, vfp_get_double(state, dm));
+ vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr);
+ vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr);
vdd.sign = vdn.sign ^ vdm.sign;
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 368b5a25d..72afe2164 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -46,9 +46,9 @@ VMLA_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -96,9 +96,9 @@ VMLS_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -146,9 +146,9 @@ VNMLA_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -197,9 +197,9 @@ VNMLS_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -247,9 +247,9 @@ VNMUL_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -297,9 +297,9 @@ VMUL_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -347,9 +347,9 @@ VADD_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -397,9 +397,9 @@ VSUB_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -447,9 +447,9 @@ VDIV_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -591,9 +591,9 @@ VABS_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -642,9 +642,9 @@ VNEG_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -692,9 +692,9 @@ VSQRT_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -742,9 +742,9 @@ VCMP_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -792,9 +792,9 @@ VCMP2_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -842,9 +842,9 @@ VCVTBDS_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -894,9 +894,9 @@ VCVTBFF_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -944,9 +944,9 @@ VCVTBFI_INST:
int ret;
if (inst_cream->dp_operation)
- ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
else
- ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]);
+ ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
CHECK_VFP_CDP_RET;
}
@@ -1146,14 +1146,14 @@ VMRS_INST:
{
if (inst_cream->Rt != 15)
{
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_OFFSET(VFP_FPSCR)];
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSCR];
}
else
{
- cpu->NFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 31) & 1;
- cpu->ZFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 30) & 1;
- cpu->CFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 29) & 1;
- cpu->VFlag = (cpu->VFP[VFP_OFFSET(VFP_FPSCR)] >> 28) & 1;
+ cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1;
+ cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1;
+ cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1;
+ cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1;
}
}
else
@@ -1161,7 +1161,7 @@ VMRS_INST:
switch (inst_cream->reg)
{
case 0:
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_OFFSET(VFP_FPSID)];
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID];
break;
case 6:
/* MVFR1, VFPv3 only ? */
@@ -1172,7 +1172,7 @@ VMRS_INST:
LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", inst_cream->Rt);
break;
case 8:
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_OFFSET(VFP_FPEXC)];
+ cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC];
break;
default:
break;
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 8b2dfa388..4dfe0254d 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -51,6 +51,8 @@
* ===========================================================================
*/
+#include "common/logging/log.h"
+
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
@@ -63,8 +65,8 @@ static struct vfp_single vfp_single_default_qnan = {
static void vfp_single_dump(const char *str, struct vfp_single *s)
{
- pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n",
- str, s->sign != 0, s->exponent, s->significand);
+ LOG_DEBUG(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x",
+ str, s->sign != 0, s->exponent, s->significand);
}
static void vfp_single_normalise_denormal(struct vfp_single *vs)
@@ -154,7 +156,7 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs,
} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0))
incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1;
- pr_debug("VFP: rounding increment = 0x%08x\n", incr);
+ LOG_DEBUG(Core_ARM11, "rounding increment = 0x%08x", incr);
/*
* Is our rounding going to overflow?
@@ -209,10 +211,8 @@ pack:
vfp_single_dump("pack: final", vs);
{
s32 d = vfp_single_pack(vs);
-#if 1
- pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
- sd, d, exceptions);
-#endif
+ LOG_DEBUG(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func,
+ sd, d, exceptions);
vfp_put_float(state, d, sd);
}
@@ -302,7 +302,7 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
u32 z, a;
if ((significand & 0xc0000000) != 0x40000000) {
- pr_debug("VFP: estimate_sqrt: invalid significand\n");
+ LOG_DEBUG(Core_ARM11, "invalid significand");
}
a = significand << 1;
@@ -330,7 +330,7 @@ static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 f
struct vfp_single vsm, vsd, *vsp;
int ret, tm;
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
tm = vfp_single_type(&vsm);
if (tm & (VFP_NAN|VFP_INFINITY)) {
vsp = &vsd;
@@ -392,7 +392,7 @@ sqrt_invalid:
term = (u64)vsd.significand * vsd.significand;
rem = ((u64)vsm.significand << 32) - term;
- pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem);
+ LOG_DEBUG(Core_ARM11, "term=%016lx rem=%016lx", term, rem);
while (rem < 0) {
vsd.significand -= 1;
@@ -498,7 +498,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f
int tm;
u32 exceptions = 0;
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
tm = vfp_single_type(&vsm);
@@ -563,7 +563,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
int rmode = fpscr & FPSCR_RMODE_MASK;
int tm;
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
vfp_single_dump("VSM", &vsm);
/*
@@ -624,7 +624,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
}
}
- pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
+ LOG_DEBUG(Core_ARM11, "ftoui: d(s%d)=%08x exceptions=%08x", sd, d, exceptions);
vfp_put_float(state, d, sd);
@@ -643,7 +643,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
int rmode = fpscr & FPSCR_RMODE_MASK;
int tm;
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
vfp_single_dump("VSM", &vsm);
/*
@@ -703,7 +703,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
}
}
- pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
+ LOG_DEBUG(Core_ARM11, "ftosi: d(s%d)=%08x exceptions=%08x", sd, d, exceptions);
vfp_put_float(state, (s32)d, sd);
@@ -800,7 +800,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
if (vsn->significand & 0x80000000 ||
vsm->significand & 0x80000000) {
- pr_info("VFP: bad FP values in %s\n", __func__);
+ LOG_WARNING(Core_ARM11, "bad FP values");
vfp_single_dump("VSN", vsn);
vfp_single_dump("VSM", vsm);
}
@@ -871,7 +871,7 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s
struct vfp_single *t = vsn;
vsn = vsm;
vsm = t;
- pr_debug("VFP: swapping M <-> N\n");
+ LOG_DEBUG(Core_ARM11, "swapping M <-> N");
}
vsd->sign = vsn->sign ^ vsm->sign;
@@ -924,12 +924,12 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
s32 v;
v = vfp_get_float(state, sn);
- pr_debug("VFP: s%u = %08x\n", sn, v);
- vfp_single_unpack(&vsn, v);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, v);
+ vfp_single_unpack(&vsn, v, &fpscr);
if (vsn.exponent == 0 && vsn.significand)
vfp_single_normalise_denormal(&vsn);
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
if (vsm.exponent == 0 && vsm.significand)
vfp_single_normalise_denormal(&vsm);
@@ -939,8 +939,8 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
vsp.sign = vfp_sign_negate(vsp.sign);
v = vfp_get_float(state, sd);
- pr_debug("VFP: s%u = %08x\n", sd, v);
- vfp_single_unpack(&vsn, v);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sd, v);
+ vfp_single_unpack(&vsn, v, &fpscr);
if (vsn.exponent == 0 && vsn.significand != 0)
vfp_single_normalise_denormal(&vsn);
@@ -961,7 +961,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
*/
static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
- pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
}
@@ -970,7 +970,8 @@ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
*/
static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
- pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sd, sn);
+ // TODO: this one has its arguments inverted, investigate.
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sd, sn);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
}
@@ -979,7 +980,7 @@ static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
*/
static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
- pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
}
@@ -988,7 +989,7 @@ static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
*/
static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
- pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
}
@@ -1001,13 +1002,13 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
u32 exceptions;
s32 n = vfp_get_float(state, sn);
- pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, n);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
- vfp_single_unpack(&vsn, n);
+ vfp_single_unpack(&vsn, n, &fpscr);
if (vsn.exponent == 0 && vsn.significand)
vfp_single_normalise_denormal(&vsn);
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
if (vsm.exponent == 0 && vsm.significand)
vfp_single_normalise_denormal(&vsm);
@@ -1024,13 +1025,13 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
u32 exceptions;
s32 n = vfp_get_float(state, sn);
- pr_debug("VFP: s%u = %08x\n", sn, n);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
- vfp_single_unpack(&vsn, n);
+ vfp_single_unpack(&vsn, n, &fpscr);
if (vsn.exponent == 0 && vsn.significand)
vfp_single_normalise_denormal(&vsn);
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
if (vsm.exponent == 0 && vsm.significand)
vfp_single_normalise_denormal(&vsm);
@@ -1048,16 +1049,16 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
u32 exceptions;
s32 n = vfp_get_float(state, sn);
- pr_debug("VFP: s%u = %08x\n", sn, n);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
/*
* Unpack and normalise denormals.
*/
- vfp_single_unpack(&vsn, n);
+ vfp_single_unpack(&vsn, n, &fpscr);
if (vsn.exponent == 0 && vsn.significand)
vfp_single_normalise_denormal(&vsn);
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsm, m, &fpscr);
if (vsm.exponent == 0 && vsm.significand)
vfp_single_normalise_denormal(&vsm);
@@ -1071,7 +1072,7 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
*/
static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
{
- pr_debug("In %sVFP: s%u = %08x\n", __FUNCTION__, sn, sd);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, sd);
/*
* Subtraction is addition with one sign inverted.
*/
@@ -1091,10 +1092,10 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
s32 n = vfp_get_float(state, sn);
int tm, tn;
- pr_debug("VFP: s%u = %08x\n", sn, n);
+ LOG_DEBUG(Core_ARM11, "s%u = %08x", sn, n);
- vfp_single_unpack(&vsn, n);
- vfp_single_unpack(&vsm, m);
+ vfp_single_unpack(&vsn, n, &fpscr);
+ vfp_single_unpack(&vsm, m, &fpscr);
vsd.sign = vsn.sign ^ vsm.sign;
@@ -1213,7 +1214,6 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
unsigned int sm = vfp_get_sm(inst);
unsigned int vecitr, veclen, vecstride;
struct op *fop;
- pr_debug("In %s\n", __FUNCTION__);
vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
@@ -1239,11 +1239,11 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
else
veclen = fpscr & FPSCR_LENGTH_MASK;
- pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
- (veclen >> FPSCR_LENGTH_BIT) + 1);
+ LOG_DEBUG(Core_ARM11, "vecstride=%u veclen=%u", vecstride,
+ (veclen >> FPSCR_LENGTH_BIT) + 1);
if (!fop->fn) {
- printf("VFP: could not find single op %d, inst=0x%x@0x%x\n", FEXT_TO_IDX(inst), inst, state->Reg[15]);
+ LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), inst, state->Reg[15]);
exit(-1);
goto invalid;
}
@@ -1255,17 +1255,17 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
type = (fop->flags & OP_DD) ? 'd' : 's';
if (op == FOP_EXT)
- pr_debug("VFP: itr%d (%c%u) = op[%u] (s%u=%08x)\n",
- vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
- sm, m);
+ LOG_DEBUG(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)",
+ vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
+ sm, m);
else
- pr_debug("VFP: itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)\n",
- vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
- FOP_TO_IDX(op), sm, m);
+ LOG_DEBUG(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)",
+ vecitr >> FPSCR_LENGTH_BIT, type, dest, sn,
+ FOP_TO_IDX(op), sm, m);
except = fop->fn(state, dest, sn, m, fpscr);
- pr_debug("VFP: itr%d: exceptions=%08x\n",
- vecitr >> FPSCR_LENGTH_BIT, except);
+ LOG_DEBUG(Core_ARM11, "itr%d: exceptions=%08x",
+ vecitr >> FPSCR_LENGTH_BIT, except);
exceptions |= except;