summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/arm/arm_interface.h28
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp948
-rw-r--r--src/core/arm/disassembler/arm_disasm.h152
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp35
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h4
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp25
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h16
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp549
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.cpp93
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h21
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp28
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h28
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/arminit.cpp100
-rw-r--r--src/core/arm/skyeye_common/armmmu.h104
-rw-r--r--src/core/arm/skyeye_common/armstate.cpp657
-rw-r--r--src/core/arm/skyeye_common/armstate.h229
-rw-r--r--src/core/arm/skyeye_common/armsupp.cpp430
-rw-r--r--src/core/arm/skyeye_common/armsupp.h8
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp17
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp9
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp164
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp9
-rw-r--r--src/core/hle/applets/applet.cpp9
-rw-r--r--src/core/hle/applets/applet.h3
-rw-r--r--src/core/hle/service/am/am.cpp3
-rw-r--r--src/core/hle/service/am/am_net.cpp3
-rw-r--r--src/core/hle/service/apt/apt.cpp53
-rw-r--r--src/core/hle/service/apt/apt.h30
-rw-r--r--src/core/hle/service/apt/apt_a.cpp1
-rw-r--r--src/core/hle/service/apt/apt_s.cpp4
-rw-r--r--src/core/hle/service/apt/apt_u.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp10
-rw-r--r--src/core/hle/service/hid/hid.h5
-rw-r--r--src/core/hle/service/ldr_ro.cpp6
-rw-r--r--src/core/hle/service/soc_u.cpp10
-rw-r--r--src/core/hw/y2r.cpp1
-rw-r--r--src/core/loader/loader.cpp6
-rw-r--r--src/core/settings.h55
-rw-r--r--src/core/tracer/citrace.h70
41 files changed, 2347 insertions, 1584 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ba9af2a1f..6cc60fd58 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -4,9 +4,8 @@ set(SRCS
arm/dyncom/arm_dyncom.cpp
arm/dyncom/arm_dyncom_dec.cpp
arm/dyncom/arm_dyncom_interpreter.cpp
- arm/dyncom/arm_dyncom_run.cpp
arm/dyncom/arm_dyncom_thumb.cpp
- arm/skyeye_common/arminit.cpp
+ arm/skyeye_common/armstate.cpp
arm/skyeye_common/armsupp.cpp
arm/skyeye_common/vfp/vfp.cpp
arm/skyeye_common/vfp/vfpdouble.cpp
@@ -133,7 +132,6 @@ set(HEADERS
arm/dyncom/arm_dyncom_thumb.h
arm/skyeye_common/arm_regformat.h
arm/skyeye_common/armstate.h
- arm/skyeye_common/armmmu.h
arm/skyeye_common/armsupp.h
arm/skyeye_common/vfp/asm_vfp.h
arm/skyeye_common/vfp/vfp.h
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 85ed2c698..5cffe513c 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -62,6 +62,34 @@ public:
virtual void SetReg(int index, u32 value) = 0;
/**
+ * Gets the value of a VFP register
+ * @param index Register index (0-31)
+ * @return Returns the value in the register
+ */
+ virtual u32 GetVFPReg(int index) const = 0;
+
+ /**
+ * Sets a VFP register to the given value
+ * @param index Register index (0-31)
+ * @param value Value to set register to
+ */
+ virtual void SetVFPReg(int index, u32 value) = 0;
+
+ /**
+ * Gets the current value within a given VFP system register
+ * @param reg The VFP system register
+ * @return The value within the VFP system register
+ */
+ virtual u32 GetVFPSystemReg(VFPSystemRegister reg) const = 0;
+
+ /**
+ * Sets the VFP system register to the given value
+ * @param reg The VFP system register
+ * @param value Value to set the VFP system register to
+ */
+ virtual void SetVFPSystemReg(VFPSystemRegister reg, u32 value) = 0;
+
+ /**
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index f6d44d85a..77af10b54 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -1,9 +1,13 @@
// Copyright 2006 The Android Open Source Project
#include <string>
+#include <unordered_set>
+#include "common/common_types.h"
#include "common/string_util.h"
+
#include "core/arm/disassembler/arm_disasm.h"
+#include "core/arm/skyeye_common/armsupp.h"
static const char *cond_names[] = {
"eq",
@@ -37,6 +41,7 @@ static const char *opcode_names[] = {
"blx",
"bx",
"cdp",
+ "clrex",
"clz",
"cmn",
"cmp",
@@ -46,6 +51,10 @@ static const char *opcode_names[] = {
"ldr",
"ldrb",
"ldrbt",
+ "ldrex",
+ "ldrexb",
+ "ldrexd",
+ "ldrexh",
"ldrh",
"ldrsb",
"ldrsh",
@@ -58,28 +67,105 @@ static const char *opcode_names[] = {
"msr",
"mul",
"mvn",
+ "nop",
"orr",
+ "pkh",
"pld",
+ "qadd16",
+ "qadd8",
+ "qasx",
+ "qsax",
+ "qsub16",
+ "qsub8",
+ "rev",
+ "rev16",
+ "revsh",
"rsb",
"rsc",
+ "sadd16",
+ "sadd8",
+ "sasx",
"sbc",
+ "sel",
+ "sev",
+ "shadd16",
+ "shadd8",
+ "shasx",
+ "shsax",
+ "shsub16",
+ "shsub8",
+ "smlad",
"smlal",
+ "smlald",
+ "smlsd",
+ "smlsld",
+ "smmla",
+ "smmls",
+ "smmul",
+ "smuad",
"smull",
+ "smusd",
+ "ssat",
+ "ssat16",
+ "ssax",
+ "ssub16",
+ "ssub8",
"stc",
"stm",
"str",
"strb",
"strbt",
+ "strex",
+ "strexb",
+ "strexd",
+ "strexh",
"strh",
"strt",
"sub",
"swi",
"swp",
"swpb",
+ "sxtab",
+ "sxtab16",
+ "sxtah",
+ "sxtb",
+ "sxtb16",
+ "sxth",
"teq",
"tst",
+ "uadd16",
+ "uadd8",
+ "uasx",
+ "uhadd16",
+ "uhadd8",
+ "uhasx",
+ "uhsax",
+ "uhsub16",
+ "uhsub8",
"umlal",
"umull",
+ "uqadd16",
+ "uqadd8",
+ "uqasx",
+ "uqsax",
+ "uqsub16",
+ "uqsub8",
+ "usad8",
+ "usada8",
+ "usat",
+ "usat16",
+ "usax",
+ "usub16",
+ "usub8",
+ "uxtab",
+ "uxtab16",
+ "uxtah",
+ "uxtb",
+ "uxtb16",
+ "uxth",
+ "wfe",
+ "wfi",
+ "yield",
"undefined",
"adc",
@@ -131,11 +217,11 @@ static const char *shift_names[] = {
"ROR"
};
-static const char* cond_to_str(uint32_t cond) {
+static const char* cond_to_str(u32 cond) {
return cond_names[cond];
}
-std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
+std::string ARM_Disasm::Disassemble(u32 addr, u32 insn)
{
Opcode opcode = Decode(insn);
switch (opcode) {
@@ -172,6 +258,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
return DisassembleBX(insn);
case OP_CDP:
return "cdp";
+ case OP_CLREX:
+ return "clrex";
case OP_CLZ:
return DisassembleCLZ(insn);
case OP_LDC:
@@ -188,6 +276,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
case OP_STRBT:
case OP_STRT:
return DisassembleMem(insn);
+ case OP_LDREX:
+ case OP_LDREXB:
+ case OP_LDREXD:
+ case OP_LDREXH:
+ case OP_STREX:
+ case OP_STREXB:
+ case OP_STREXD:
+ case OP_STREXH:
+ return DisassembleREX(opcode, insn);
case OP_LDRH:
case OP_LDRSB:
case OP_LDRSH:
@@ -204,8 +301,76 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
return DisassembleMSR(insn);
case OP_MUL:
return DisassembleMUL(opcode, insn);
+ case OP_NOP:
+ case OP_SEV:
+ case OP_WFE:
+ case OP_WFI:
+ case OP_YIELD:
+ return DisassembleNoOperands(opcode, insn);
+ case OP_PKH:
+ return DisassemblePKH(insn);
case OP_PLD:
return DisassemblePLD(insn);
+ case OP_QADD16:
+ case OP_QADD8:
+ case OP_QASX:
+ case OP_QSAX:
+ case OP_QSUB16:
+ case OP_QSUB8:
+ case OP_SADD16:
+ case OP_SADD8:
+ case OP_SASX:
+ case OP_SHADD16:
+ case OP_SHADD8:
+ case OP_SHASX:
+ case OP_SHSAX:
+ case OP_SHSUB16:
+ case OP_SHSUB8:
+ case OP_SSAX:
+ case OP_SSUB16:
+ case OP_SSUB8:
+ case OP_UADD16:
+ case OP_UADD8:
+ case OP_UASX:
+ case OP_UHADD16:
+ case OP_UHADD8:
+ case OP_UHASX:
+ case OP_UHSAX:
+ case OP_UHSUB16:
+ case OP_UHSUB8:
+ case OP_UQADD16:
+ case OP_UQADD8:
+ case OP_UQASX:
+ case OP_UQSAX:
+ case OP_UQSUB16:
+ case OP_UQSUB8:
+ case OP_USAX:
+ case OP_USUB16:
+ case OP_USUB8:
+ return DisassembleParallelAddSub(opcode, insn);
+ case OP_REV:
+ case OP_REV16:
+ case OP_REVSH:
+ return DisassembleREV(opcode, insn);
+ case OP_SEL:
+ return DisassembleSEL(insn);
+ case OP_SMLAD:
+ case OP_SMLALD:
+ case OP_SMLSD:
+ case OP_SMLSLD:
+ case OP_SMMLA:
+ case OP_SMMLS:
+ case OP_SMMUL:
+ case OP_SMUAD:
+ case OP_SMUSD:
+ case OP_USAD8:
+ case OP_USADA8:
+ return DisassembleMediaMulDiv(opcode, insn);
+ case OP_SSAT:
+ case OP_SSAT16:
+ case OP_USAT:
+ case OP_USAT16:
+ return DisassembleSAT(opcode, insn);
case OP_STC:
return "stc";
case OP_SWI:
@@ -213,6 +378,19 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
case OP_SWP:
case OP_SWPB:
return DisassembleSWP(opcode, insn);
+ case OP_SXTAB:
+ case OP_SXTAB16:
+ case OP_SXTAH:
+ case OP_SXTB:
+ case OP_SXTB16:
+ case OP_SXTH:
+ case OP_UXTAB:
+ case OP_UXTAB16:
+ case OP_UXTAH:
+ case OP_UXTB:
+ case OP_UXTB16:
+ case OP_UXTH:
+ return DisassembleXT(opcode, insn);
case OP_UMLAL:
case OP_UMULL:
case OP_SMLAL:
@@ -224,22 +402,22 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
return NULL;
}
-std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
{
- static const uint8_t kNoOperand1 = 1;
- static const uint8_t kNoDest = 2;
- static const uint8_t kNoSbit = 4;
+ static const u8 kNoOperand1 = 1;
+ static const u8 kNoDest = 2;
+ static const u8 kNoSbit = 4;
std::string rn_str;
std::string rd_str;
- uint8_t flags = 0;
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t is_immed = (insn >> 25) & 0x1;
- uint8_t bit_s = (insn >> 20) & 1;
- uint8_t rn = (insn >> 16) & 0xf;
- uint8_t rd = (insn >> 12) & 0xf;
- uint8_t immed = insn & 0xff;
+ u8 flags = 0;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 is_immed = (insn >> 25) & 0x1;
+ u8 bit_s = (insn >> 20) & 1;
+ u8 rn = (insn >> 16) & 0xf;
+ u8 rd = (insn >> 12) & 0xf;
+ u8 immed = insn & 0xff;
const char* opname = opcode_names[opcode];
switch (opcode) {
@@ -279,14 +457,14 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn)
opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed);
}
- uint8_t shift_is_reg = (insn >> 4) & 1;
- uint8_t rotate = (insn >> 8) & 0xf;
- uint8_t rm = insn & 0xf;
- uint8_t shift_type = (insn >> 5) & 0x3;
- uint8_t rs = (insn >> 8) & 0xf;
- uint8_t shift_amount = (insn >> 7) & 0x1f;
- uint32_t rotated_val = immed;
- uint8_t rotate2 = rotate << 1;
+ u8 shift_is_reg = (insn >> 4) & 1;
+ u8 rotate = (insn >> 8) & 0xf;
+ u8 rm = insn & 0xf;
+ u8 shift_type = (insn >> 5) & 0x3;
+ u8 rs = (insn >> 8) & 0xf;
+ u8 shift_amount = (insn >> 7) & 0x1f;
+ u32 rotated_val = immed;
+ u8 rotate2 = rotate << 1;
rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2));
if (!shift_is_reg && shift_type == 0 && shift_amount == 0) {
@@ -312,10 +490,10 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn)
shift_name, shift_amount);
}
-std::string ARM_Disasm::DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint32_t offset = insn & 0xffffff;
+ u8 cond = (insn >> 28) & 0xf;
+ u32 offset = insn & 0xffffff;
// Sign-extend the 24-bit offset
if ((offset >> 23) & 1)
offset |= 0xff000000;
@@ -328,39 +506,71 @@ std::string ARM_Disasm::DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t
return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr);
}
-std::string ARM_Disasm::DisassembleBX(uint32_t insn)
+std::string ARM_Disasm::DisassembleBX(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rn = insn & 0xf;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rn = insn & 0xf;
return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn);
}
-std::string ARM_Disasm::DisassembleBKPT(uint32_t insn)
+std::string ARM_Disasm::DisassembleBKPT(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint32_t immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
+ u8 cond = (insn >> 28) & 0xf;
+ u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed);
}
-std::string ARM_Disasm::DisassembleCLZ(uint32_t insn)
+std::string ARM_Disasm::DisassembleCLZ(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rd = (insn >> 12) & 0xf;
- uint8_t rm = insn & 0xf;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rd = (insn >> 12) & 0xf;
+ u8 rm = insn & 0xf;
return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
}
-std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) {
+ u32 cond = BITS(insn, 28, 31);
+ u32 rd = BITS(insn, 16, 19);
+ u32 ra = BITS(insn, 12, 15);
+ u32 rm = BITS(insn, 8, 11);
+ u32 m = BIT(insn, 5);
+ u32 rn = BITS(insn, 0, 3);
+
+ std::string cross = "";
+ if (m) {
+ if (opcode == OP_SMMLA || opcode == OP_SMMUL || opcode == OP_SMMLS)
+ cross = "r";
+ else
+ cross = "x";
+ }
+
+ std::string ext_reg = "";
+ std::unordered_set<Opcode, std::hash<int>> with_ext_reg = {
+ OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8
+ };
+ if (with_ext_reg.find(opcode) != with_ext_reg.end())
+ ext_reg = Common::StringFromFormat(", r%u", ra);
+
+ std::string rd_low = "";
+ if (opcode == OP_SMLALD || opcode == OP_SMLSLD)
+ rd_low = Common::StringFromFormat("r%u, ", ra);
+
+ return Common::StringFromFormat("%s%s%s\t%sr%u, r%u, r%u%s", opcode_names[opcode],
+ cross.c_str(), cond_to_str(cond), rd_low.c_str(), rd, rn, rm,
+ ext_reg.c_str());
+}
+
+std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
{
std::string tmp_list;
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t write_back = (insn >> 21) & 0x1;
- uint8_t bit_s = (insn >> 22) & 0x1;
- uint8_t is_up = (insn >> 23) & 0x1;
- uint8_t is_pre = (insn >> 24) & 0x1;
- uint8_t rn = (insn >> 16) & 0xf;
- uint16_t reg_list = insn & 0xffff;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 write_back = (insn >> 21) & 0x1;
+ u8 bit_s = (insn >> 22) & 0x1;
+ u8 is_up = (insn >> 23) & 0x1;
+ u8 is_pre = (insn >> 24) & 0x1;
+ u8 rn = (insn >> 16) & 0xf;
+ u16 reg_list = insn & 0xffff;
const char *opname = opcode_names[opcode];
@@ -400,18 +610,18 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn)
opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list.c_str(), carret);
}
-std::string ARM_Disasm::DisassembleMem(uint32_t insn)
+std::string ARM_Disasm::DisassembleMem(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t is_reg = (insn >> 25) & 0x1;
- uint8_t is_load = (insn >> 20) & 0x1;
- uint8_t write_back = (insn >> 21) & 0x1;
- uint8_t is_byte = (insn >> 22) & 0x1;
- uint8_t is_up = (insn >> 23) & 0x1;
- uint8_t is_pre = (insn >> 24) & 0x1;
- uint8_t rn = (insn >> 16) & 0xf;
- uint8_t rd = (insn >> 12) & 0xf;
- uint16_t offset = insn & 0xfff;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 is_reg = (insn >> 25) & 0x1;
+ u8 is_load = (insn >> 20) & 0x1;
+ u8 write_back = (insn >> 21) & 0x1;
+ u8 is_byte = (insn >> 22) & 0x1;
+ u8 is_up = (insn >> 23) & 0x1;
+ u8 is_pre = (insn >> 24) & 0x1;
+ u8 rn = (insn >> 16) & 0xf;
+ u8 rd = (insn >> 12) & 0xf;
+ u16 offset = insn & 0xfff;
const char *opname = "ldr";
if (!is_load)
@@ -448,9 +658,9 @@ std::string ARM_Disasm::DisassembleMem(uint32_t insn)
}
}
- uint8_t rm = insn & 0xf;
- uint8_t shift_type = (insn >> 5) & 0x3;
- uint8_t shift_amount = (insn >> 7) & 0x1f;
+ u8 rm = insn & 0xf;
+ u8 shift_type = (insn >> 5) & 0x3;
+ u8 shift_amount = (insn >> 7) & 0x1f;
const char *shift_name = shift_names[shift_type];
@@ -492,19 +702,19 @@ std::string ARM_Disasm::DisassembleMem(uint32_t insn)
shift_name, shift_amount);
}
-std::string ARM_Disasm::DisassembleMemHalf(uint32_t insn)
+std::string ARM_Disasm::DisassembleMemHalf(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t is_load = (insn >> 20) & 0x1;
- uint8_t write_back = (insn >> 21) & 0x1;
- uint8_t is_immed = (insn >> 22) & 0x1;
- uint8_t is_up = (insn >> 23) & 0x1;
- uint8_t is_pre = (insn >> 24) & 0x1;
- uint8_t rn = (insn >> 16) & 0xf;
- uint8_t rd = (insn >> 12) & 0xf;
- uint8_t bits_65 = (insn >> 5) & 0x3;
- uint8_t rm = insn & 0xf;
- uint8_t offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
+ u8 cond = (insn >> 28) & 0xf;
+ u8 is_load = (insn >> 20) & 0x1;
+ u8 write_back = (insn >> 21) & 0x1;
+ u8 is_immed = (insn >> 22) & 0x1;
+ u8 is_up = (insn >> 23) & 0x1;
+ u8 is_pre = (insn >> 24) & 0x1;
+ u8 rn = (insn >> 16) & 0xf;
+ u8 rd = (insn >> 12) & 0xf;
+ u8 bits_65 = (insn >> 5) & 0x3;
+ u8 rm = insn & 0xf;
+ u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
const char *opname = "ldr";
if (is_load == 0)
@@ -548,78 +758,78 @@ std::string ARM_Disasm::DisassembleMemHalf(uint32_t insn)
}
}
-std::string ARM_Disasm::DisassembleMCR(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t crn = (insn >> 16) & 0xf;
- uint8_t crd = (insn >> 12) & 0xf;
- uint8_t cpnum = (insn >> 8) & 0xf;
- uint8_t opcode2 = (insn >> 5) & 0x7;
- uint8_t crm = insn & 0xf;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 crn = (insn >> 16) & 0xf;
+ u8 crd = (insn >> 12) & 0xf;
+ u8 cpnum = (insn >> 8) & 0xf;
+ u8 opcode2 = (insn >> 5) & 0x7;
+ u8 crm = insn & 0xf;
const char *opname = opcode_names[opcode];
return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}",
opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2);
}
-std::string ARM_Disasm::DisassembleMLA(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rd = (insn >> 16) & 0xf;
- uint8_t rn = (insn >> 12) & 0xf;
- uint8_t rs = (insn >> 8) & 0xf;
- uint8_t rm = insn & 0xf;
- uint8_t bit_s = (insn >> 20) & 1;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rd = (insn >> 16) & 0xf;
+ u8 rn = (insn >> 12) & 0xf;
+ u8 rs = (insn >> 8) & 0xf;
+ u8 rm = insn & 0xf;
+ u8 bit_s = (insn >> 20) & 1;
const char *opname = opcode_names[opcode];
return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d",
opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn);
}
-std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rdhi = (insn >> 16) & 0xf;
- uint8_t rdlo = (insn >> 12) & 0xf;
- uint8_t rs = (insn >> 8) & 0xf;
- uint8_t rm = insn & 0xf;
- uint8_t bit_s = (insn >> 20) & 1;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rdhi = (insn >> 16) & 0xf;
+ u8 rdlo = (insn >> 12) & 0xf;
+ u8 rs = (insn >> 8) & 0xf;
+ u8 rm = insn & 0xf;
+ u8 bit_s = (insn >> 20) & 1;
const char *opname = opcode_names[opcode];
return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d",
opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs);
}
-std::string ARM_Disasm::DisassembleMUL(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rd = (insn >> 16) & 0xf;
- uint8_t rs = (insn >> 8) & 0xf;
- uint8_t rm = insn & 0xf;
- uint8_t bit_s = (insn >> 20) & 1;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rd = (insn >> 16) & 0xf;
+ u8 rs = (insn >> 8) & 0xf;
+ u8 rm = insn & 0xf;
+ u8 bit_s = (insn >> 20) & 1;
const char *opname = opcode_names[opcode];
return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d",
opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs);
}
-std::string ARM_Disasm::DisassembleMRS(uint32_t insn)
+std::string ARM_Disasm::DisassembleMRS(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rd = (insn >> 12) & 0xf;
- uint8_t ps = (insn >> 22) & 1;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rd = (insn >> 12) & 0xf;
+ u8 ps = (insn >> 22) & 1;
return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr");
}
-std::string ARM_Disasm::DisassembleMSR(uint32_t insn)
+std::string ARM_Disasm::DisassembleMSR(u32 insn)
{
char flags[8];
int flag_index = 0;
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t is_immed = (insn >> 25) & 0x1;
- uint8_t pd = (insn >> 22) & 1;
- uint8_t mask = (insn >> 16) & 0xf;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 is_immed = (insn >> 25) & 0x1;
+ u8 pd = (insn >> 22) & 1;
+ u8 mask = (insn >> 16) & 0xf;
if (mask & 1)
flags[flag_index++] = 'c';
@@ -632,36 +842,76 @@ std::string ARM_Disasm::DisassembleMSR(uint32_t insn)
flags[flag_index] = 0;
if (is_immed) {
- uint32_t immed = insn & 0xff;
- uint8_t rotate = (insn >> 8) & 0xf;
- uint8_t rotate2 = rotate << 1;
- uint32_t rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
+ u32 immed = insn & 0xff;
+ u8 rotate = (insn >> 8) & 0xf;
+ u8 rotate2 = rotate << 1;
+ u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
return Common::StringFromFormat("msr%s\t%s_%s, #0x%x",
cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val);
}
- uint8_t rm = insn & 0xf;
+ u8 rm = insn & 0xf;
return Common::StringFromFormat("msr%s\t%s_%s, r%d",
cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm);
}
-std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
+std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn)
+{
+ u32 cond = BITS(insn, 28, 31);
+ return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond));
+}
+
+std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, u32 insn) {
+ u32 cond = BITS(insn, 28, 31);
+ u32 rn = BITS(insn, 16, 19);
+ u32 rd = BITS(insn, 12, 15);
+ u32 rm = BITS(insn, 0, 3);
+
+ return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[opcode], cond_to_str(cond),
+ rd, rn, rm);
+}
+
+std::string ARM_Disasm::DisassemblePKH(u32 insn)
+{
+ u32 cond = BITS(insn, 28, 31);
+ u32 rn = BITS(insn, 16, 19);
+ u32 rd = BITS(insn, 12, 15);
+ u32 imm5 = BITS(insn, 7, 11);
+ u32 tb = BIT(insn, 6);
+ u32 rm = BITS(insn, 0, 3);
+
+ std::string suffix = tb ? "tb" : "bt";
+ std::string shift = "";
+
+ if (tb && imm5 == 0)
+ imm5 = 32;
+
+ if (imm5 > 0) {
+ shift = tb ? ", ASR" : ", LSL";
+ shift += " #" + std::to_string(imm5);
+ }
+
+ return Common::StringFromFormat("pkh%s%s\tr%u, r%u, r%u%s", suffix.c_str(), cond_to_str(cond),
+ rd, rn, rm, shift.c_str());
+}
+
+std::string ARM_Disasm::DisassemblePLD(u32 insn)
{
- uint8_t is_reg = (insn >> 25) & 0x1;
- uint8_t is_up = (insn >> 23) & 0x1;
- uint8_t rn = (insn >> 16) & 0xf;
+ u8 is_reg = (insn >> 25) & 0x1;
+ u8 is_up = (insn >> 23) & 0x1;
+ u8 rn = (insn >> 16) & 0xf;
const char *minus = "";
if (is_up == 0)
minus = "-";
if (is_reg) {
- uint8_t rm = insn & 0xf;
+ u8 rm = insn & 0xf;
return Common::StringFromFormat("pld\t[r%d, %sr%d]", rn, minus, rm);
}
- uint16_t offset = insn & 0xfff;
+ u16 offset = insn & 0xfff;
if (offset == 0) {
return Common::StringFromFormat("pld\t[r%d]", rn);
} else {
@@ -669,27 +919,128 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
}
}
-std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
+std::string ARM_Disasm::DisassembleREV(Opcode opcode, u32 insn) {
+ u32 cond = BITS(insn, 28, 31);
+ u32 rd = BITS(insn, 12, 15);
+ u32 rm = BITS(insn, 0, 3);
+
+ return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond),
+ rd, rm);
+}
+
+std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) {
+ u32 rn = BITS(insn, 16, 19);
+ u32 rd = BITS(insn, 12, 15);
+ u32 rt = BITS(insn, 0, 3);
+ u32 cond = BITS(insn, 28, 31);
+
+ switch (opcode) {
+ case OP_STREX:
+ case OP_STREXB:
+ case OP_STREXH:
+ return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
+ cond_to_str(cond), rd, rt, rn);
+ case OP_STREXD:
+ return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode],
+ cond_to_str(cond), rd, rt, rt + 1, rn);
+
+ // for LDREX instructions, rd corresponds to Rt from reference manual
+ case OP_LDREX:
+ case OP_LDREXB:
+ case OP_LDREXH:
+ return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode],
+ cond_to_str(cond), rd, rn);
+ case OP_LDREXD:
+ return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
+ cond_to_str(cond), rd, rd + 1, rn);
+ default:
+ return opcode_names[OP_UNDEFINED];
+ }
+}
+
+std::string ARM_Disasm::DisassembleSAT(Opcode opcode, u32 insn) {
+ u32 cond = BITS(insn, 28, 31);
+ u32 sat_imm = BITS(insn, 16, 20);
+ u32 rd = BITS(insn, 12, 15);
+ u32 imm5 = BITS(insn, 7, 11);
+ u32 sh = BIT(insn, 6);
+ u32 rn = BITS(insn, 0, 3);
+
+ std::string shift_part = "";
+ bool opcode_has_shift = (opcode == OP_SSAT) || (opcode == OP_USAT);
+ if (opcode_has_shift && !(sh == 0 && imm5 == 0)) {
+ if (sh == 0)
+ shift_part += ", LSL #";
+ else
+ shift_part += ", ASR #";
+
+ if (imm5 == 0)
+ imm5 = 32;
+ shift_part += std::to_string(imm5);
+ }
+
+ if (opcode == OP_SSAT || opcode == OP_SSAT16)
+ sat_imm++;
+
+ return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd,
+ sat_imm, rn, shift_part.c_str());
+}
+
+std::string ARM_Disasm::DisassembleSEL(u32 insn) {
+ u32 cond = BITS(insn, 28, 31);
+ u32 rn = BITS(insn, 16, 19);
+ u32 rd = BITS(insn, 12, 15);
+ u32 rm = BITS(insn, 0, 3);
+
+ return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[OP_SEL], cond_to_str(cond),
+ rd, rn, rm);
+}
+
+std::string ARM_Disasm::DisassembleSWI(u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint32_t sysnum = insn & 0x00ffffff;
+ u8 cond = (insn >> 28) & 0xf;
+ u32 sysnum = insn & 0x00ffffff;
return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum);
}
-std::string ARM_Disasm::DisassembleSWP(Opcode opcode, uint32_t insn)
+std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn)
{
- uint8_t cond = (insn >> 28) & 0xf;
- uint8_t rn = (insn >> 16) & 0xf;
- uint8_t rd = (insn >> 12) & 0xf;
- uint8_t rm = insn & 0xf;
+ u8 cond = (insn >> 28) & 0xf;
+ u8 rn = (insn >> 16) & 0xf;
+ u8 rd = (insn >> 12) & 0xf;
+ u8 rm = insn & 0xf;
const char *opname = opcode_names[opcode];
return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
}
-Opcode ARM_Disasm::Decode(uint32_t insn) {
- uint32_t bits27_26 = (insn >> 26) & 0x3;
+std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn)
+{
+ u32 cond = BITS(insn, 28, 31);
+ u32 rn = BITS(insn, 16, 19);
+ u32 rd = BITS(insn, 12, 15);
+ u32 rotate = BITS(insn, 10, 11);
+ u32 rm = BITS(insn, 0, 3);
+
+ std::string rn_part = "";
+ static std::unordered_set<Opcode, std::hash<int>> extend_with_add = {
+ OP_SXTAB, OP_SXTAB16, OP_SXTAH,
+ OP_UXTAB, OP_UXTAB16, OP_UXTAH
+ };
+ if (extend_with_add.find(opcode) != extend_with_add.end())
+ rn_part = ", r" + std::to_string(rn);
+
+ std::string rotate_part = "";
+ if (rotate != 0)
+ rotate_part = ", ROR #" + std::to_string(rotate << 3);
+
+ return Common::StringFromFormat("%s%s\tr%u%s, r%u%s", opcode_names[opcode], cond_to_str(cond),
+ rd, rn_part.c_str(), rm, rotate_part.c_str());
+}
+
+Opcode ARM_Disasm::Decode(u32 insn) {
+ u32 bits27_26 = (insn >> 26) & 0x3;
switch (bits27_26) {
case 0x0:
return Decode00(insn);
@@ -703,9 +1054,9 @@ Opcode ARM_Disasm::Decode(uint32_t insn) {
return OP_INVALID;
}
-Opcode ARM_Disasm::Decode00(uint32_t insn) {
- uint8_t bit25 = (insn >> 25) & 0x1;
- uint8_t bit4 = (insn >> 4) & 0x1;
+Opcode ARM_Disasm::Decode00(u32 insn) {
+ u8 bit25 = (insn >> 25) & 0x1;
+ u8 bit4 = (insn >> 4) & 0x1;
if (bit25 == 0 && bit4 == 1) {
if ((insn & 0x0ffffff0) == 0x012fff10) {
// Bx instruction
@@ -719,41 +1070,48 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) {
// Bkpt instruction
return OP_BKPT;
}
- uint32_t bits7_4 = (insn >> 4) & 0xf;
+ u32 bits7_4 = (insn >> 4) & 0xf;
if (bits7_4 == 0x9) {
- if ((insn & 0x0ff00ff0) == 0x01000090) {
- // Swp instruction
- uint8_t bit22 = (insn >> 22) & 0x1;
- if (bit22)
- return OP_SWPB;
- return OP_SWP;
+ u32 bit24 = BIT(insn, 24);
+ if (bit24) {
+ return DecodeSyncPrimitive(insn);
}
// One of the multiply instructions
return DecodeMUL(insn);
}
- uint8_t bit7 = (insn >> 7) & 0x1;
+ u8 bit7 = (insn >> 7) & 0x1;
if (bit7 == 1) {
// One of the load/store halfword/byte instructions
return DecodeLDRH(insn);
}
}
+ u32 op1 = BITS(insn, 20, 24);
+ if (bit25 && (op1 == 0x12 || op1 == 0x16)) {
+ // One of the MSR (immediate) and hints instructions
+ return DecodeMSRImmAndHints(insn);
+ }
+
// One of the data processing instructions
return DecodeALU(insn);
}
-Opcode ARM_Disasm::Decode01(uint32_t insn) {
- uint8_t is_reg = (insn >> 25) & 0x1;
- uint8_t bit4 = (insn >> 4) & 0x1;
+Opcode ARM_Disasm::Decode01(u32 insn) {
+ u8 is_reg = (insn >> 25) & 0x1;
+ u8 bit4 = (insn >> 4) & 0x1;
if (is_reg == 1 && bit4 == 1)
- return OP_UNDEFINED;
- uint8_t is_load = (insn >> 20) & 0x1;
- uint8_t is_byte = (insn >> 22) & 0x1;
+ return DecodeMedia(insn);
+ u8 is_load = (insn >> 20) & 0x1;
+ u8 is_byte = (insn >> 22) & 0x1;
if ((insn & 0xfd70f000) == 0xf550f000) {
// Pre-load
return OP_PLD;
}
+ if (insn == 0xf57ff01f) {
+ // Clear-Exclusive
+ return OP_CLREX;
+ }
if (is_load) {
if (is_byte) {
// Load byte
@@ -770,36 +1128,28 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) {
return OP_STR;
}
-Opcode ARM_Disasm::Decode10(uint32_t insn) {
- uint8_t bit25 = (insn >> 25) & 0x1;
+Opcode ARM_Disasm::Decode10(u32 insn) {
+ u8 bit25 = (insn >> 25) & 0x1;
if (bit25 == 0) {
// LDM/STM
- uint8_t is_load = (insn >> 20) & 0x1;
+ u8 is_load = (insn >> 20) & 0x1;
if (is_load)
return OP_LDM;
return OP_STM;
}
- // Branch or Branch with link
- uint8_t is_link = (insn >> 24) & 1;
- uint32_t offset = insn & 0xffffff;
- // Sign-extend the 24-bit offset
- if ((offset >> 23) & 1)
- offset |= 0xff000000;
+ // Branch with link
+ if ((insn >> 24) & 1)
+ return OP_BL;
- // Pre-compute the left-shift and the prefetch offset
- offset <<= 2;
- offset += 8;
- if (is_link == 0)
- return OP_B;
- return OP_BL;
+ return OP_B;
}
-Opcode ARM_Disasm::Decode11(uint32_t insn) {
- uint8_t bit25 = (insn >> 25) & 0x1;
+Opcode ARM_Disasm::Decode11(u32 insn) {
+ u8 bit25 = (insn >> 25) & 0x1;
if (bit25 == 0) {
// LDC, SDC
- uint8_t is_load = (insn >> 20) & 0x1;
+ u8 is_load = (insn >> 20) & 0x1;
if (is_load) {
// LDC
return OP_LDC;
@@ -808,18 +1158,18 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
return OP_STC;
}
- uint8_t bit24 = (insn >> 24) & 0x1;
+ u8 bit24 = (insn >> 24) & 0x1;
if (bit24 == 0x1) {
// SWI
return OP_SWI;
}
- uint8_t bit4 = (insn >> 4) & 0x1;
- uint8_t cpnum = (insn >> 8) & 0xf;
+ u8 bit4 = (insn >> 4) & 0x1;
+ u8 cpnum = (insn >> 8) & 0xf;
if (cpnum == 15) {
// Special case for coprocessor 15
- uint8_t opcode = (insn >> 21) & 0x7;
+ u8 opcode = (insn >> 21) & 0x7;
if (bit4 == 0 || opcode != 0) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
@@ -827,7 +1177,7 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
}
// MRC, MCR
- uint8_t is_mrc = (insn >> 20) & 0x1;
+ u8 is_mrc = (insn >> 20) & 0x1;
if (is_mrc)
return OP_MRC;
return OP_MCR;
@@ -838,22 +1188,165 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
return OP_CDP;
}
// MRC, MCR
- uint8_t is_mrc = (insn >> 20) & 0x1;
+ u8 is_mrc = (insn >> 20) & 0x1;
if (is_mrc)
return OP_MRC;
return OP_MCR;
}
-Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
- uint8_t bit24 = (insn >> 24) & 0x1;
+Opcode ARM_Disasm::DecodeSyncPrimitive(u32 insn) {
+ u32 op = BITS(insn, 20, 23);
+ u32 bit22 = BIT(insn, 22);
+ switch (op) {
+ case 0x0:
+ if (bit22)
+ return OP_SWPB;
+ return OP_SWP;
+ case 0x8:
+ return OP_STREX;
+ case 0x9:
+ return OP_LDREX;
+ case 0xA:
+ return OP_STREXD;
+ case 0xB:
+ return OP_LDREXD;
+ case 0xC:
+ return OP_STREXB;
+ case 0xD:
+ return OP_LDREXB;
+ case 0xE:
+ return OP_STREXH;
+ case 0xF:
+ return OP_LDREXH;
+ default:
+ return OP_UNDEFINED;
+ }
+}
+
+Opcode ARM_Disasm::DecodeParallelAddSub(u32 insn) {
+ u32 op1 = BITS(insn, 20, 21);
+ u32 op2 = BITS(insn, 5, 7);
+ u32 is_unsigned = BIT(insn, 22);
+
+ if (op1 == 0x0 || op2 == 0x5 || op2 == 0x6)
+ return OP_UNDEFINED;
+
+ // change op1 range from [1, 3] to range [0, 2]
+ op1--;
+
+ // change op2 range from [0, 4] U {7} to range [0, 5]
+ if (op2 == 0x7)
+ op2 = 0x5;
+
+ static std::vector<Opcode> opcodes = {
+ // op1 = 0
+ OP_SADD16, OP_UADD16,
+ OP_SASX, OP_UASX,
+ OP_SSAX, OP_USAX,
+ OP_SSUB16, OP_USUB16,
+ OP_SADD8, OP_UADD8,
+ OP_SSUB8, OP_USUB8,
+ // op1 = 1
+ OP_QADD16, OP_UQADD16,
+ OP_QASX, OP_UQASX,
+ OP_QSAX, OP_UQSAX,
+ OP_QSUB16, OP_UQSUB16,
+ OP_QADD8, OP_UQADD8,
+ OP_QSUB8, OP_UQSUB8,
+ // op1 = 2
+ OP_SHADD16, OP_UHADD16,
+ OP_SHASX, OP_UHASX,
+ OP_SHSAX, OP_UHSAX,
+ OP_SHSUB16, OP_UHSUB16,
+ OP_SHADD8, OP_UHADD8,
+ OP_SHSUB8, OP_UHSUB8
+ };
+
+ u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned;
+ return opcodes[opcode_index];
+}
+
+Opcode ARM_Disasm::DecodePackingSaturationReversal(u32 insn) {
+ u32 op1 = BITS(insn, 20, 22);
+ u32 a = BITS(insn, 16, 19);
+ u32 op2 = BITS(insn, 5, 7);
+
+ switch (op1) {
+ case 0x0:
+ if (BIT(op2, 0) == 0)
+ return OP_PKH;
+ if (op2 == 0x3 && a != 0xf)
+ return OP_SXTAB16;
+ if (op2 == 0x3 && a == 0xf)
+ return OP_SXTB16;
+ if (op2 == 0x5)
+ return OP_SEL;
+ break;
+ case 0x2:
+ if (BIT(op2, 0) == 0)
+ return OP_SSAT;
+ if (op2 == 0x1)
+ return OP_SSAT16;
+ if (op2 == 0x3 && a != 0xf)
+ return OP_SXTAB;
+ if (op2 == 0x3 && a == 0xf)
+ return OP_SXTB;
+ break;
+ case 0x3:
+ if (op2 == 0x1)
+ return OP_REV;
+ if (BIT(op2, 0) == 0)
+ return OP_SSAT;
+ if (op2 == 0x3 && a != 0xf)
+ return OP_SXTAH;
+ if (op2 == 0x3 && a == 0xf)
+ return OP_SXTH;
+ if (op2 == 0x5)
+ return OP_REV16;
+ break;
+ case 0x4:
+ if (op2 == 0x3 && a != 0xf)
+ return OP_UXTAB16;
+ if (op2 == 0x3 && a == 0xf)
+ return OP_UXTB16;
+ break;
+ case 0x6:
+ if (BIT(op2, 0) == 0)
+ return OP_USAT;
+ if (op2 == 0x1)
+ return OP_USAT16;
+ if (op2 == 0x3 && a != 0xf)
+ return OP_UXTAB;
+ if (op2 == 0x3 && a == 0xf)
+ return OP_UXTB;
+ break;
+ case 0x7:
+ if (BIT(op2, 0) == 0)
+ return OP_USAT;
+ if (op2 == 0x3 && a != 0xf)
+ return OP_UXTAH;
+ if (op2 == 0x3 && a == 0xf)
+ return OP_UXTH;
+ if (op2 == 0x5)
+ return OP_REVSH;
+ break;
+ default:
+ break;
+ }
+
+ return OP_UNDEFINED;
+}
+
+Opcode ARM_Disasm::DecodeMUL(u32 insn) {
+ u8 bit24 = (insn >> 24) & 0x1;
if (bit24 != 0) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
- uint8_t bit23 = (insn >> 23) & 0x1;
- uint8_t bit22_U = (insn >> 22) & 0x1;
- uint8_t bit21_A = (insn >> 21) & 0x1;
+ u8 bit23 = (insn >> 23) & 0x1;
+ u8 bit22_U = (insn >> 22) & 0x1;
+ u8 bit21_A = (insn >> 21) & 0x1;
if (bit23 == 0) {
// 32-bit multiply
if (bit22_U != 0) {
@@ -878,9 +1371,104 @@ Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
return OP_SMLAL;
}
-Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) {
- uint8_t is_load = (insn >> 20) & 0x1;
- uint8_t bits_65 = (insn >> 5) & 0x3;
+Opcode ARM_Disasm::DecodeMSRImmAndHints(u32 insn) {
+ u32 op = BIT(insn, 22);
+ u32 op1 = BITS(insn, 16, 19);
+ u32 op2 = BITS(insn, 0, 7);
+
+ if (op == 0 && op1 == 0) {
+ switch (op2) {
+ case 0x0:
+ return OP_NOP;
+ case 0x1:
+ return OP_YIELD;
+ case 0x2:
+ return OP_WFE;
+ case 0x3:
+ return OP_WFI;
+ case 0x4:
+ return OP_SEV;
+ default:
+ return OP_UNDEFINED;
+ }
+ }
+
+ return OP_MSR;
+}
+
+Opcode ARM_Disasm::DecodeMediaMulDiv(u32 insn) {
+ u32 op1 = BITS(insn, 20, 22);
+ u32 op2_h = BITS(insn, 6, 7);
+ u32 a = BITS(insn, 12, 15);
+
+ switch (op1) {
+ case 0x0:
+ if (op2_h == 0x0) {
+ if (a != 0xf)
+ return OP_SMLAD;
+ else
+ return OP_SMUAD;
+ } else if (op2_h == 0x1) {
+ if (a != 0xf)
+ return OP_SMLSD;
+ else
+ return OP_SMUSD;
+ }
+ break;
+ case 0x4:
+ if (op2_h == 0x0)
+ return OP_SMLALD;
+ else if (op2_h == 0x1)
+ return OP_SMLSLD;
+ break;
+ case 0x5:
+ if (op2_h == 0x0) {
+ if (a != 0xf)
+ return OP_SMMLA;
+ else
+ return OP_SMMUL;
+ } else if (op2_h == 0x3) {
+ return OP_SMMLS;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return OP_UNDEFINED;
+}
+
+Opcode ARM_Disasm::DecodeMedia(u32 insn) {
+ u32 op1 = BITS(insn, 20, 24);
+ u32 rd = BITS(insn, 12, 15);
+ u32 op2 = BITS(insn, 5, 7);
+
+ switch (BITS(op1, 3, 4)) {
+ case 0x0:
+ // unsigned and signed parallel addition and subtraction
+ return DecodeParallelAddSub(insn);
+ case 0x1:
+ // Packing, unpacking, saturation, and reversal
+ return DecodePackingSaturationReversal(insn);
+ case 0x2:
+ // Signed multiply, signed and unsigned divide
+ return DecodeMediaMulDiv(insn);
+ case 0x3:
+ if (op2 == 0 && rd == 0xf)
+ return OP_USAD8;
+ if (op2 == 0 && rd != 0xf)
+ return OP_USADA8;
+ break;
+ default:
+ break;
+ }
+
+ return OP_UNDEFINED;
+}
+
+Opcode ARM_Disasm::DecodeLDRH(u32 insn) {
+ u8 is_load = (insn >> 20) & 0x1;
+ u8 bits_65 = (insn >> 5) & 0x3;
if (is_load) {
if (bits_65 == 0x1) {
// Load unsigned halfword
@@ -908,12 +1496,12 @@ Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) {
return OP_STRH;
}
-Opcode ARM_Disasm::DecodeALU(uint32_t insn) {
- uint8_t is_immed = (insn >> 25) & 0x1;
- uint8_t opcode = (insn >> 21) & 0xf;
- uint8_t bit_s = (insn >> 20) & 1;
- uint8_t shift_is_reg = (insn >> 4) & 1;
- uint8_t bit7 = (insn >> 7) & 1;
+Opcode ARM_Disasm::DecodeALU(u32 insn) {
+ u8 is_immed = (insn >> 25) & 0x1;
+ u8 opcode = (insn >> 21) & 0xf;
+ u8 bit_s = (insn >> 20) & 1;
+ u8 shift_is_reg = (insn >> 4) & 1;
+ u8 bit7 = (insn >> 7) & 1;
if (!is_immed && shift_is_reg && (bit7 != 0)) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index f94bd4669..53d9c6a74 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -2,9 +2,10 @@
#pragma once
-#include <cstdint>
#include <string>
+#include "common/common_types.h"
+
// Note: this list of opcodes must match the list used to initialize
// the opflags[] array in opcode.cpp.
enum Opcode {
@@ -20,6 +21,7 @@ enum Opcode {
OP_BLX,
OP_BX,
OP_CDP,
+ OP_CLREX,
OP_CLZ,
OP_CMN,
OP_CMP,
@@ -29,6 +31,10 @@ enum Opcode {
OP_LDR,
OP_LDRB,
OP_LDRBT,
+ OP_LDREX,
+ OP_LDREXB,
+ OP_LDREXD,
+ OP_LDREXH,
OP_LDRH,
OP_LDRSB,
OP_LDRSH,
@@ -41,28 +47,105 @@ enum Opcode {
OP_MSR,
OP_MUL,
OP_MVN,
+ OP_NOP,
OP_ORR,
+ OP_PKH,
OP_PLD,
+ OP_QADD16,
+ OP_QADD8,
+ OP_QASX,
+ OP_QSAX,
+ OP_QSUB16,
+ OP_QSUB8,
+ OP_REV,
+ OP_REV16,
+ OP_REVSH,
OP_RSB,
OP_RSC,
+ OP_SADD16,
+ OP_SADD8,
+ OP_SASX,
OP_SBC,
+ OP_SEL,
+ OP_SEV,
+ OP_SHADD16,
+ OP_SHADD8,
+ OP_SHASX,
+ OP_SHSAX,
+ OP_SHSUB16,
+ OP_SHSUB8,
+ OP_SMLAD,
OP_SMLAL,
+ OP_SMLALD,
+ OP_SMLSD,
+ OP_SMLSLD,
+ OP_SMMLA,
+ OP_SMMLS,
+ OP_SMMUL,
+ OP_SMUAD,
OP_SMULL,
+ OP_SMUSD,
+ OP_SSAT,
+ OP_SSAT16,
+ OP_SSAX,
+ OP_SSUB16,
+ OP_SSUB8,
OP_STC,
OP_STM,
OP_STR,
OP_STRB,
OP_STRBT,
+ OP_STREX,
+ OP_STREXB,
+ OP_STREXD,
+ OP_STREXH,
OP_STRH,
OP_STRT,
OP_SUB,
OP_SWI,
OP_SWP,
OP_SWPB,
+ OP_SXTAB,
+ OP_SXTAB16,
+ OP_SXTAH,
+ OP_SXTB,
+ OP_SXTB16,
+ OP_SXTH,
OP_TEQ,
OP_TST,
+ OP_UADD16,
+ OP_UADD8,
+ OP_UASX,
+ OP_UHADD16,
+ OP_UHADD8,
+ OP_UHASX,
+ OP_UHSAX,
+ OP_UHSUB16,
+ OP_UHSUB8,
OP_UMLAL,
OP_UMULL,
+ OP_UQADD16,
+ OP_UQADD8,
+ OP_UQASX,
+ OP_UQSAX,
+ OP_UQSUB16,
+ OP_UQSUB8,
+ OP_USAD8,
+ OP_USADA8,
+ OP_USAT,
+ OP_USAT16,
+ OP_USAX,
+ OP_USUB16,
+ OP_USUB8,
+ OP_UXTAB,
+ OP_UXTAB16,
+ OP_UXTAH,
+ OP_UXTB,
+ OP_UXTB16,
+ OP_UXTH,
+ OP_WFE,
+ OP_WFI,
+ OP_YIELD,
// Define thumb opcodes
OP_THUMB_UNDEFINED,
@@ -109,33 +192,48 @@ enum Opcode {
class ARM_Disasm {
public:
- static std::string Disassemble(uint32_t addr, uint32_t insn);
- static Opcode Decode(uint32_t insn);
+ static std::string Disassemble(u32 addr, u32 insn);
+ static Opcode Decode(u32 insn);
private:
- static Opcode Decode00(uint32_t insn);
- static Opcode Decode01(uint32_t insn);
- static Opcode Decode10(uint32_t insn);
- static Opcode Decode11(uint32_t insn);
- static Opcode DecodeMUL(uint32_t insn);
- static Opcode DecodeLDRH(uint32_t insn);
- static Opcode DecodeALU(uint32_t insn);
+ static Opcode Decode00(u32 insn);
+ static Opcode Decode01(u32 insn);
+ static Opcode Decode10(u32 insn);
+ static Opcode Decode11(u32 insn);
+ static Opcode DecodeSyncPrimitive(u32 insn);
+ static Opcode DecodeParallelAddSub(u32 insn);
+ static Opcode DecodePackingSaturationReversal(u32 insn);
+ static Opcode DecodeMUL(u32 insn);
+ static Opcode DecodeMSRImmAndHints(u32 insn);
+ static Opcode DecodeMediaMulDiv(u32 insn);
+ static Opcode DecodeMedia(u32 insn);
+ static Opcode DecodeLDRH(u32 insn);
+ static Opcode DecodeALU(u32 insn);
- static std::string DisassembleALU(Opcode opcode, uint32_t insn);
- static std::string DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t insn);
- static std::string DisassembleBX(uint32_t insn);
- static std::string DisassembleBKPT(uint32_t insn);
- static std::string DisassembleCLZ(uint32_t insn);
- static std::string DisassembleMemblock(Opcode opcode, uint32_t insn);
- static std::string DisassembleMem(uint32_t insn);
- static std::string DisassembleMemHalf(uint32_t insn);
- static std::string DisassembleMCR(Opcode opcode, uint32_t insn);
- static std::string DisassembleMLA(Opcode opcode, uint32_t insn);
- static std::string DisassembleUMLAL(Opcode opcode, uint32_t insn);
- static std::string DisassembleMUL(Opcode opcode, uint32_t insn);
- static std::string DisassembleMRS(uint32_t insn);
- static std::string DisassembleMSR(uint32_t insn);
- static std::string DisassemblePLD(uint32_t insn);
- static std::string DisassembleSWI(uint32_t insn);
- static std::string DisassembleSWP(Opcode opcode, uint32_t insn);
+ static std::string DisassembleALU(Opcode opcode, u32 insn);
+ static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn);
+ static std::string DisassembleBX(u32 insn);
+ static std::string DisassembleBKPT(u32 insn);
+ static std::string DisassembleCLZ(u32 insn);
+ static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn);
+ static std::string DisassembleMemblock(Opcode opcode, u32 insn);
+ static std::string DisassembleMem(u32 insn);
+ static std::string DisassembleMemHalf(u32 insn);
+ static std::string DisassembleMCR(Opcode opcode, u32 insn);
+ static std::string DisassembleMLA(Opcode opcode, u32 insn);
+ static std::string DisassembleUMLAL(Opcode opcode, u32 insn);
+ static std::string DisassembleMUL(Opcode opcode, u32 insn);
+ static std::string DisassembleMRS(u32 insn);
+ static std::string DisassembleMSR(u32 insn);
+ static std::string DisassembleNoOperands(Opcode opcode, u32 insn);
+ static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn);
+ static std::string DisassemblePKH(u32 insn);
+ static std::string DisassemblePLD(u32 insn);
+ static std::string DisassembleREV(Opcode opcode, u32 insn);
+ static std::string DisassembleREX(Opcode opcode, u32 insn);
+ static std::string DisassembleSAT(Opcode opcode, u32 insn);
+ static std::string DisassembleSEL(u32 insn);
+ static std::string DisassembleSWI(u32 insn);
+ static std::string DisassembleSWP(Opcode opcode, u32 insn);
+ static std::string DisassembleXT(Opcode opcode, u32 insn);
};
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index a51a3acf8..f3be2c857 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -18,16 +18,7 @@
#include "core/core_timing.h"
ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
- state = Common::make_unique<ARMul_State>();
-
- // Reset the core to initial state
- ARMul_Reset(state.get());
-
- // Switch to the desired privilege mode.
- switch_mode(state.get(), initial_mode);
-
- state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
- state->Reg[15] = 0x00000000;
+ state = Common::make_unique<ARMul_State>(initial_mode);
}
ARM_DynCom::~ARM_DynCom() {
@@ -49,6 +40,22 @@ void ARM_DynCom::SetReg(int index, u32 value) {
state->Reg[index] = value;
}
+u32 ARM_DynCom::GetVFPReg(int index) const {
+ return state->ExtReg[index];
+}
+
+void ARM_DynCom::SetVFPReg(int index, u32 value) {
+ state->ExtReg[index] = value;
+}
+
+u32 ARM_DynCom::GetVFPSystemReg(VFPSystemRegister reg) const {
+ return state->VFP[reg];
+}
+
+void ARM_DynCom::SetVFPSystemReg(VFPSystemRegister reg, u32 value) {
+ state->VFP[reg] = value;
+}
+
u32 ARM_DynCom::GetCPSR() const {
return state->Cpsr;
}
@@ -91,8 +98,8 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e
}
void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
- memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
- memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
+ memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers));
+ memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers));
ctx.sp = state->Reg[13];
ctx.lr = state->Reg[14];
@@ -104,8 +111,8 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
}
void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
- memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
- memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
+ memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
+ memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));
state->Reg[13] = ctx.sp;
state->Reg[14] = ctx.lr;
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 87ab6908a..3664fd728 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -25,6 +25,10 @@ public:
u32 GetPC() const override;
u32 GetReg(int index) const override;
void SetReg(int index, u32 value) override;
+ u32 GetVFPReg(int index) const override;
+ void SetVFPReg(int index, u32 value) override;
+ u32 GetVFPSystemReg(VFPSystemRegister reg) const override;
+ void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
u32 GetCPSR() const override;
void SetCPSR(u32 cpsr) override;
u32 GetCP15Register(CP15Register reg) override;
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 3ab9f2c17..ee4288314 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -5,7 +5,7 @@
#include "core/arm/dyncom/arm_dyncom_dec.h"
#include "core/arm/skyeye_common/armsupp.h"
-const ISEITEM arm_instruction[] = {
+const InstructionSetEncodingItem arm_instruction[] = {
{ "vmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 }},
{ "vmls", 7, ARMVFP2, { 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 }},
{ "vnmla", 4, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 }},
@@ -207,7 +207,7 @@ const ISEITEM arm_instruction[] = {
{ "bbl", 1, 0, { 25, 27, 0x00000005 }},
};
-const ISEITEM arm_exclusion_code[] = {
+const InstructionSetEncodingItem arm_exclusion_code[] = {
{ "vmla", 0, ARMVFP2, { 0 }},
{ "vmls", 0, ARMVFP2, { 0 }},
{ "vnmla", 0, ARMVFP2, { 0 }},
@@ -414,14 +414,13 @@ const ISEITEM arm_exclusion_code[] = {
{ "invalid", 0, INVALID, { 0 }}
};
-int decode_arm_instr(u32 instr, s32* idx) {
+ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
int n = 0;
int base = 0;
- int ret = DECODE_FAILURE;
- int i = 0;
- int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM);
+ int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem);
+ ARMDecodeStatus ret = ARMDecodeStatus::FAILURE;
- for (i = 0; i < instr_slots; i++) {
+ for (int i = 0; i < instr_slots; i++) {
n = arm_instruction[i].attribute_value;
base = 0;
@@ -438,11 +437,11 @@ int decode_arm_instr(u32 instr, s32* idx) {
n--;
}
- // All conditions is satisfied.
+ // All conditions are satisfied.
if (n == 0)
- ret = DECODE_SUCCESS;
+ ret = ARMDecodeStatus::SUCCESS;
- if (ret == DECODE_SUCCESS) {
+ if (ret == ARMDecodeStatus::SUCCESS) {
n = arm_exclusion_code[i].attribute_value;
if (n != 0) {
base = 0;
@@ -454,13 +453,13 @@ int decode_arm_instr(u32 instr, s32* idx) {
n--;
}
- // All conditions is satisfied.
+ // All conditions are satisfied.
if (n == 0)
- ret = DECODE_FAILURE;
+ ret = ARMDecodeStatus::FAILURE;
}
}
- if (ret == DECODE_SUCCESS) {
+ if (ret == ARMDecodeStatus::SUCCESS) {
*idx = i;
return ret;
}
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h
index 5f6279627..d7170e0fc 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.h
+++ b/src/core/arm/dyncom/arm_dyncom_dec.h
@@ -6,22 +6,20 @@
#include "common/common_types.h"
-int decode_arm_instr(u32 instr, s32* idx);
-
-enum DECODE_STATUS {
- DECODE_SUCCESS,
- DECODE_FAILURE
+enum class ARMDecodeStatus {
+ SUCCESS,
+ FAILURE
};
-struct instruction_set_encoding_item {
+ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx);
+
+struct InstructionSetEncodingItem {
const char *name;
int attribute_value;
int version;
u32 content[21];
};
-typedef struct instruction_set_encoding_item ISEITEM;
-
// ARM versions
enum {
INVALID = 0,
@@ -38,4 +36,4 @@ enum {
ARMV6K,
};
-extern const ISEITEM arm_instruction[];
+extern const InstructionSetEncodingItem arm_instruction[];
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index fd5e13295..422e80b50 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -7,6 +7,7 @@
#include <algorithm>
#include <cstdio>
+#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/profiler.h"
@@ -17,7 +18,6 @@
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
#include "core/arm/dyncom/arm_dyncom_thumb.h"
#include "core/arm/dyncom/arm_dyncom_run.h"
-#include "core/arm/skyeye_common/armmmu.h"
#include "core/arm/skyeye_common/armstate.h"
#include "core/arm/skyeye_common/armsupp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
@@ -48,27 +48,6 @@ enum {
typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
-// Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
-// This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
-// support LDR/STREXD.
-static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
-
-// Exclusive memory access
-static int exclusive_detect(ARMul_State* state, u32 addr) {
- if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK))
- return 0;
- else
- return -1;
-}
-
-static void add_exclusive_addr(ARMul_State* state, u32 addr){
- state->exclusive_tag = addr & RESERVATION_GRANULE_MASK;
-}
-
-static void remove_exclusive(ARMul_State* state, u32 addr){
- state->exclusive_tag = 0xFFFFFFFF;
-}
-
static int CondPassed(ARMul_State* cpu, unsigned int cond) {
const u32 NFLAG = cpu->NFlag;
const u32 ZFLAG = cpu->ZFlag;
@@ -781,8 +760,8 @@ struct bx_inst {
struct blx_inst {
union {
- int32_t signed_immed_24;
- uint32_t Rm;
+ s32 signed_immed_24;
+ u32 Rm;
} val;
unsigned int inst;
};
@@ -3490,21 +3469,15 @@ enum {
FETCH_FAILURE
};
-static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) {
+static ThumbDecodeStatus DecodeThumbInstruction(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){
- // TODO: FIXME, endian should be judged
- u32 tinstr;
- if((addr & 0x3) != 0)
- tinstr = inst >> 16;
- else
- tinstr = inst & 0xFFFF;
-
+ ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size);
+ if (ret == ThumbDecodeStatus::BRANCH) {
int inst_index;
int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
+ u32 tinstr = GetThumbInstruction(inst, addr);
- switch((tinstr & 0xF800) >> 11){
+ switch ((tinstr & 0xF800) >> 11) {
case 26:
case 27:
if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){
@@ -3537,7 +3510,7 @@ static tdstate decode_thumb_instr(u32 inst, u32 addr, u32* arm_inst, u32* inst_s
*ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
break;
default:
- ret = t_undefined;
+ ret = ThumbDecodeStatus::UNDEFINED;
break;
}
}
@@ -3549,10 +3522,6 @@ enum {
FETCH_EXCEPTION
};
-typedef struct instruction_set_encoding_item ISEITEM;
-
-extern const ISEITEM arm_instruction[];
-
static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
Common::Profiling::ScopeTimer timer_decode(profile_decode);
@@ -3574,20 +3543,19 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
size++;
- // If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction
+ // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
if (cpu->TFlag) {
- uint32_t arm_inst;
- tdstate state = decode_thumb_instr(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
+ u32 arm_inst;
+ ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
- // We have translated the branch instruction of thumb in thumb decoder
- if(state == t_branch){
+ // We have translated the Thumb branch instruction in the Thumb decoder
+ if (state == ThumbDecodeStatus::BRANCH) {
goto translated;
}
inst = arm_inst;
}
- ret = decode_arm_instr(inst, &idx);
- if (ret == DECODE_FAILURE) {
+ if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst);
LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
@@ -3919,7 +3887,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
#endif
arm_inst* inst_base;
unsigned int addr;
- unsigned int phys_addr;
unsigned int num_instrs = 0;
int ptr;
@@ -3938,8 +3905,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
else
cpu->Reg[15] &= 0xfffffffc;
- phys_addr = cpu->Reg[15];
-
// Find the cached instruction cream, otherwise translate it...
auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
if (itr != cpu->instruction_cache.end()) {
@@ -3957,14 +3922,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
adc_inst* const inst_cream = (adc_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+ RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -3978,7 +3947,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(adc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -3990,7 +3959,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rn_val = RN;
if (inst_cream->Rn == 15)
- rn_val += 2 * GET_INST_SIZE(cpu);
+ rn_val += 2 * cpu->GetInstructionSize();
bool carry;
bool overflow;
@@ -3999,7 +3968,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Cpsr & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4013,22 +3982,28 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(add_inst));
FETCH_INST;
GOTO_NEXT_INST;
}
AND_INST:
{
- and_inst *inst_cream = (and_inst *)inst_base->component;
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ and_inst* const inst_cream = (and_inst*)inst_base->component;
+
u32 lop = RN;
u32 rop = SHIFTER_OPERAND;
+
+ if (inst_cream->Rn == 15)
+ lop += 2 * cpu->GetInstructionSize();
+
RD = lop & rop;
+
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Cpsr & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4041,7 +4016,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(and_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4057,7 +4032,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
INC_PC(sizeof(bbl_inst));
goto DISPATCH;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(bbl_inst));
goto DISPATCH;
}
@@ -4067,14 +4042,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
u32 lop = RN;
if (inst_cream->Rn == 15) {
- lop += 2 * GET_INST_SIZE(cpu);
+ lop += 2 * cpu->GetInstructionSize();
}
u32 rop = SHIFTER_OPERAND;
RD = lop & (~rop);
if ((inst_cream->S) && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4087,7 +4062,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(bic_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4098,7 +4073,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(bkpt_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4109,13 +4084,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
unsigned int inst = inst_cream->inst;
if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
- cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu));
+ cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
if(cpu->TFlag)
cpu->Reg[14] |= 0x1;
cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe;
cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1;
} else {
- cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu));
+ cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
cpu->TFlag = 0x1;
int signed_int = inst_cream->val.signed_immed_24;
signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
@@ -4125,7 +4100,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
INC_PC(sizeof(blx_inst));
goto DISPATCH;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(blx_inst));
goto DISPATCH;
}
@@ -4147,7 +4122,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 address = RM;
if (inst_cream->Rm == 15)
- address += 2 * GET_INST_SIZE(cpu);
+ address += 2 * cpu->GetInstructionSize();
cpu->TFlag = address & 1;
cpu->Reg[15] = address & 0xfffffffe;
@@ -4155,7 +4130,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(bx_inst));
goto DISPATCH;
}
@@ -4167,7 +4142,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->NumInstrsToExecute = 0;
return num_instrs;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(cdp_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4175,10 +4150,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
CLREX_INST:
{
- remove_exclusive(cpu, 0);
- cpu->exclusive_state = 0;
-
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->UnsetExclusiveMemoryAddress();
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(clrex_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4189,7 +4162,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
clz_inst* inst_cream = (clz_inst*)inst_base->component;
RD = clz(RM);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(clz_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4199,16 +4172,20 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow);
+ u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
UPDATE_NFLAG(result);
UPDATE_ZFLAG(result);
cpu->CFlag = carry;
cpu->VFlag = overflow;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(cmn_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4220,7 +4197,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rn_val = RN;
if (inst_cream->Rn == 15)
- rn_val += 2 * GET_INST_SIZE(cpu);
+ rn_val += 2 * cpu->GetInstructionSize();
bool carry;
bool overflow;
@@ -4231,7 +4208,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->CFlag = carry;
cpu->VFlag = overflow;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(cmp_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4239,9 +4216,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
CPS_INST:
{
cps_inst *inst_cream = (cps_inst *)inst_base->component;
- uint32_t aif_val = 0;
- uint32_t aif_mask = 0;
- if (InAPrivilegedMode(cpu)) {
+ u32 aif_val = 0;
+ u32 aif_mask = 0;
+ if (cpu->InAPrivilegedMode()) {
if (inst_cream->imod1) {
if (inst_cream->A) {
aif_val |= (inst_cream->imod0 << 8);
@@ -4260,10 +4237,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
if (inst_cream->mmod) {
cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
- switch_mode(cpu, inst_cream->mode);
+ cpu->ChangePrivilegeMode(inst_cream->mode);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(cps_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4279,7 +4256,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mov_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4291,14 +4268,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 lop = RN;
if (inst_cream->Rn == 15) {
- lop += 2 * GET_INST_SIZE(cpu);
+ lop += 2 * cpu->GetInstructionSize();
}
u32 rop = SHIFTER_OPERAND;
RD = lop ^ rop;
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4311,7 +4288,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(eor_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4320,7 +4297,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
// Instruction not implemented
//LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4335,30 +4312,30 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (BIT(inst, 22) && !BIT(inst, 15)) {
for (int i = 0; i < 13; i++) {
if(BIT(inst, i)) {
- cpu->Reg[i] = ReadMemory32(cpu, addr);
+ cpu->Reg[i] = cpu->ReadMemory32(addr);
addr += 4;
}
}
if (BIT(inst, 13)) {
if (cpu->Mode == USER32MODE)
- cpu->Reg[13] = ReadMemory32(cpu, addr);
+ cpu->Reg[13] = cpu->ReadMemory32(addr);
else
- cpu->Reg_usr[0] = ReadMemory32(cpu, addr);
+ cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
addr += 4;
}
if (BIT(inst, 14)) {
if (cpu->Mode == USER32MODE)
- cpu->Reg[14] = ReadMemory32(cpu, addr);
+ cpu->Reg[14] = cpu->ReadMemory32(addr);
else
- cpu->Reg_usr[1] = ReadMemory32(cpu, addr);
+ cpu->Reg_usr[1] = cpu->ReadMemory32(addr);
addr += 4;
}
} else if (!BIT(inst, 22)) {
for(int i = 0; i < 16; i++ ){
if(BIT(inst, i)){
- unsigned int ret = ReadMemory32(cpu, addr);
+ unsigned int ret = cpu->ReadMemory32(addr);
// For armv5t, should enter thumb when bits[0] is non-zero.
if(i == 15){
@@ -4373,18 +4350,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
} else if (BIT(inst, 22) && BIT(inst, 15)) {
for(int i = 0; i < 15; i++ ){
if(BIT(inst, i)){
- cpu->Reg[i] = ReadMemory32(cpu, addr);
+ cpu->Reg[i] = cpu->ReadMemory32(addr);
addr += 4;
}
}
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Cpsr & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
LOAD_NZCVT;
}
- cpu->Reg[15] = ReadMemory32(cpu, addr);
+ cpu->Reg[15] = cpu->ReadMemory32(addr);
}
if (BIT(inst, 15)) {
@@ -4392,7 +4369,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4410,7 +4387,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
RD = operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(sxth_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4420,7 +4397,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = ReadMemory32(cpu, addr);
+ unsigned int value = cpu->ReadMemory32(addr);
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -4431,7 +4408,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4442,7 +4419,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = ReadMemory32(cpu, addr);
+ unsigned int value = cpu->ReadMemory32(addr);
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -4453,7 +4430,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4464,7 +4441,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(uxth_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4477,7 +4454,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = RN + operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(uxtah_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4495,7 +4472,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4513,7 +4490,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4527,8 +4504,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
// The 3DS doesn't have LPAE (Large Physical Access Extension), so it
// wouldn't do this as a single read.
- cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = ReadMemory32(cpu, addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = ReadMemory32(cpu, addr + 4);
+ cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
+ cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4);
// No dispatch since this operation should not modify R15
}
@@ -4544,16 +4521,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int read_addr = RN;
- add_exclusive_addr(cpu, read_addr);
- cpu->exclusive_state = 1;
+ cpu->SetExclusiveMemoryAddress(read_addr);
- RD = ReadMemory32(cpu, read_addr);
+ RD = cpu->ReadMemory32(read_addr);
if (inst_cream->Rd == 15) {
INC_PC(sizeof(generic_arm_inst));
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4564,8 +4540,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int read_addr = RN;
- add_exclusive_addr(cpu, read_addr);
- cpu->exclusive_state = 1;
+ cpu->SetExclusiveMemoryAddress(read_addr);
RD = Memory::Read8(read_addr);
if (inst_cream->Rd == 15) {
@@ -4573,7 +4548,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4584,16 +4559,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int read_addr = RN;
- add_exclusive_addr(cpu, read_addr);
- cpu->exclusive_state = 1;
+ cpu->SetExclusiveMemoryAddress(read_addr);
- RD = ReadMemory16(cpu, read_addr);
+ RD = cpu->ReadMemory16(read_addr);
if (inst_cream->Rd == 15) {
INC_PC(sizeof(generic_arm_inst));
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4604,18 +4578,17 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int read_addr = RN;
- add_exclusive_addr(cpu, read_addr);
- cpu->exclusive_state = 1;
+ cpu->SetExclusiveMemoryAddress(read_addr);
- RD = ReadMemory32(cpu, read_addr);
- RD2 = ReadMemory32(cpu, read_addr + 4);
+ RD = cpu->ReadMemory32(read_addr);
+ RD2 = cpu->ReadMemory32(read_addr + 4);
if (inst_cream->Rd == 15) {
INC_PC(sizeof(generic_arm_inst));
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4626,13 +4599,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr);
+ cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
if (BITS(inst_cream->inst, 12, 15) == 15) {
INC_PC(sizeof(ldst_inst));
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4652,7 +4625,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4663,7 +4636,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = ReadMemory16(cpu, addr);
+ unsigned int value = cpu->ReadMemory16(addr);
if (BIT(value, 15)) {
value |= 0xffff0000;
}
@@ -4673,7 +4646,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4684,7 +4657,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = ReadMemory32(cpu, addr);
+ unsigned int value = cpu->ReadMemory32(addr);
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -4692,7 +4665,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4707,10 +4680,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
DEBUG_MSG;
} else {
if (inst_cream->cp_num == 15)
- WriteCP15Register(cpu, RD, CRn, OPCODE_1, CRm, OPCODE_2);
+ cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mcr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4727,7 +4700,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mcrr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4738,11 +4711,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
mla_inst* inst_cream = (mla_inst*)inst_base->component;
- uint64_t rm = RM;
- uint64_t rs = RS;
- uint64_t rn = RN;
+ u64 rm = RM;
+ u64 rs = RS;
+ u64 rn = RN;
- RD = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff);
+ RD = static_cast<u32>((rm * rs + rn) & 0xffffffff);
if (inst_cream->S) {
UPDATE_NFLAG(RD);
UPDATE_ZFLAG(RD);
@@ -4752,7 +4725,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mla_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4766,7 +4739,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4779,7 +4752,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mov_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4800,10 +4773,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto END;
} else {
if (inst_cream->cp_num == 15)
- RD = ReadCP15Register(cpu, CRn, OPCODE_1, CRm, OPCODE_2);
+ RD = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mrc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4820,7 +4793,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mcrr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4838,7 +4811,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = cpu->Cpsr;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mrs_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4847,7 +4820,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
msr_inst* inst_cream = (msr_inst*)inst_base->component;
- const uint32_t UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
+ const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
unsigned int inst = inst_cream->inst;
unsigned int operand;
@@ -4857,11 +4830,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
} else {
operand = cpu->Reg[BITS(inst, 0, 3)];
}
- uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
+ u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
| (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
- uint32_t mask = 0;
+ u32 mask = 0;
if (!inst_cream->R) {
- if (InAPrivilegedMode(cpu)) {
+ if (cpu->InAPrivilegedMode()) {
if ((operand & StateMask) != 0) {
/// UNPREDICTABLE
DEBUG_MSG;
@@ -4873,7 +4846,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
SAVE_NZCVT;
cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
- switch_mode(cpu, cpu->Cpsr & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
LOAD_NZCVT;
} else {
if (CurrentModeHasSPSR) {
@@ -4882,7 +4855,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(msr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4892,9 +4865,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
mul_inst* inst_cream = (mul_inst*)inst_base->component;
- uint64_t rm = RM;
- uint64_t rs = RS;
- RD = static_cast<uint32_t>((rm * rs) & 0xffffffff);
+ u64 rm = RM;
+ u64 rs = RS;
+ RD = static_cast<u32>((rm * rs) & 0xffffffff);
if (inst_cream->S) {
UPDATE_NFLAG(RD);
UPDATE_ZFLAG(RD);
@@ -4904,7 +4877,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mul_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4919,7 +4892,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4932,7 +4905,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(mvn_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4944,12 +4917,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 lop = RN;
u32 rop = SHIFTER_OPERAND;
+
+ if (inst_cream->Rn == 15)
+ lop += 2 * cpu->GetInstructionSize();
+
RD = lop | rop;
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -4962,7 +4939,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(orr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4970,7 +4947,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
NOP_INST:
{
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC_STUB;
FETCH_INST;
GOTO_NEXT_INST;
@@ -4982,7 +4959,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(pkh_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -4995,7 +4972,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(pkh_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5005,7 +4982,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
// Not implemented. PLD is a hint instruction, so it's optional.
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(pld_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5078,7 +5055,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = result;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5140,7 +5117,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5173,7 +5150,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(rev_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5187,8 +5164,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 address = 0;
inst_cream->get_addr(cpu, inst_cream->inst, address);
- cpu->Cpsr = ReadMemory32(cpu, address);
- cpu->Reg[15] = ReadMemory32(cpu, address + 4);
+ cpu->Cpsr = cpu->ReadMemory32(address);
+ cpu->Reg[15] = cpu->ReadMemory32(address + 4);
INC_PC(sizeof(ldst_inst));
goto DISPATCH;
@@ -5201,7 +5178,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rn_val = RN;
if (inst_cream->Rn == 15)
- rn_val += 2 * GET_INST_SIZE(cpu);
+ rn_val += 2 * cpu->GetInstructionSize();
bool carry;
bool overflow;
@@ -5210,7 +5187,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -5224,7 +5201,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(rsb_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5234,14 +5211,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+ RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -5255,7 +5236,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(rsc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5363,7 +5344,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5374,14 +5355,18 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
+ u32 rn_val = RN;
+ if (inst_cream->Rn == 15)
+ rn_val += 2 * cpu->GetInstructionSize();
+
bool carry;
bool overflow;
- RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
+ RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -5395,7 +5380,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(sbc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5434,7 +5419,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = result;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5453,7 +5438,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE");
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(setend_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5466,7 +5451,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
LOG_TRACE(Core_ARM11, "SEV executed.");
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC_STUB;
FETCH_INST;
GOTO_NEXT_INST;
@@ -5538,7 +5523,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5548,7 +5533,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
smla_inst* inst_cream = (smla_inst*)inst_base->component;
- int32_t operand1, operand2;
+ s32 operand1, operand2;
if (inst_cream->x == 0)
operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
else
@@ -5563,7 +5548,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (AddOverflow(operand1 * operand2, RN, RD))
cpu->Cpsr |= (1 << 27);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smla_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5619,7 +5604,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smlad_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5648,7 +5633,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->ZFlag = (RDHI == 0 && RDLO == 0);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(umlal_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5678,7 +5663,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RDHI = ((dest >> 32) & 0xFFFFFFFF);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smlalxy_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5703,7 +5688,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->Cpsr |= (1 << 27);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smlad_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5741,7 +5726,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RDHI = ((result >> 32) & 0xFFFFFFFF);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smlald_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5777,7 +5762,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = ((result >> 32) & 0xFFFFFFFF);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smlad_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5787,7 +5772,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
smul_inst* inst_cream = (smul_inst*)inst_base->component;
- uint32_t operand1, operand2;
+ u32 operand1, operand2;
if (inst_cream->x == 0)
operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
else
@@ -5799,7 +5784,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
RD = operand1 * operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smul_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5808,15 +5793,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
umull_inst* inst_cream = (umull_inst*)inst_base->component;
- int64_t rm = RM;
- int64_t rs = RS;
+ s64 rm = RM;
+ s64 rs = RS;
if (BIT(rm, 31)) {
rm |= 0xffffffff00000000LL;
}
if (BIT(rs, 31)) {
rs |= 0xffffffff00000000LL;
}
- int64_t rst = rm * rs;
+ s64 rst = rm * rs;
RDHI = BITS(rst, 32, 63);
RDLO = BITS(rst, 0, 31);
@@ -5825,7 +5810,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->ZFlag = (RDHI == 0 && RDLO == 0);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(umull_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5841,7 +5826,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
s64 result = (s64)rm * (s64)(s32)RN;
RD = BITS(result, 16, 47);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(smlad_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5855,10 +5840,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 address = 0;
inst_cream->get_addr(cpu, inst_cream->inst, address);
- WriteMemory32(cpu, address + 0, cpu->Reg[14]);
- WriteMemory32(cpu, address + 4, cpu->Spsr_copy);
+ cpu->WriteMemory32(address + 0, cpu->Reg[14]);
+ cpu->WriteMemory32(address + 4, cpu->Spsr_copy);
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5891,7 +5876,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = rn_val;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ssat_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5913,7 +5898,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->Cpsr |= (1 << 27);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ssat_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5923,7 +5908,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
// Instruction not implemented
//LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(stc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5941,36 +5926,36 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (BIT(inst_cream->inst, 22) == 1) {
for (int i = 0; i < 13; i++) {
if (BIT(inst_cream->inst, i)) {
- WriteMemory32(cpu, addr, cpu->Reg[i]);
+ cpu->WriteMemory32(addr, cpu->Reg[i]);
addr += 4;
}
}
if (BIT(inst_cream->inst, 13)) {
if (cpu->Mode == USER32MODE)
- WriteMemory32(cpu, addr, cpu->Reg[13]);
+ cpu->WriteMemory32(addr, cpu->Reg[13]);
else
- WriteMemory32(cpu, addr, cpu->Reg_usr[0]);
+ cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
addr += 4;
}
if (BIT(inst_cream->inst, 14)) {
if (cpu->Mode == USER32MODE)
- WriteMemory32(cpu, addr, cpu->Reg[14]);
+ cpu->WriteMemory32(addr, cpu->Reg[14]);
else
- WriteMemory32(cpu, addr, cpu->Reg_usr[1]);
+ cpu->WriteMemory32(addr, cpu->Reg_usr[1]);
addr += 4;
}
if (BIT(inst_cream->inst, 15)) {
- WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
+ cpu->WriteMemory32(addr, cpu->Reg_usr[1] + 8);
}
} else {
for (int i = 0; i < 15; i++) {
if (BIT(inst_cream->inst, i)) {
if (i == Rn)
- WriteMemory32(cpu, addr, old_RN);
+ cpu->WriteMemory32(addr, old_RN);
else
- WriteMemory32(cpu, addr, cpu->Reg[i]);
+ cpu->WriteMemory32(addr, cpu->Reg[i]);
addr += 4;
}
@@ -5978,10 +5963,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
// Check PC reg
if (BIT(inst_cream->inst, 15))
- WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
+ cpu->WriteMemory32(addr, cpu->Reg_usr[1] + 8);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -5999,7 +5984,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
RD = operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(sxtb_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6010,10 +5995,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
inst_cream->get_addr(cpu, inst_cream->inst, addr);
- unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
- WriteMemory32(cpu, addr, value);
+ unsigned int reg = BITS(inst_cream->inst, 12, 15);
+ unsigned int value = cpu->Reg[reg];
+
+ if (reg == 15)
+ value += 2 * cpu->GetInstructionSize();
+
+ cpu->WriteMemory32(addr, value);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6024,7 +6014,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(uxtb_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6037,7 +6027,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
RD = RN + operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(uxtab_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6050,7 +6040,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
Memory::Write8(addr, value);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6063,7 +6053,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
Memory::Write8(addr, value);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6076,10 +6066,10 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
// The 3DS doesn't have the Large Physical Access Extension (LPAE)
// so STRD wouldn't store these as a single write.
- WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
- WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
+ cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
+ cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6090,18 +6080,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int write_addr = cpu->Reg[inst_cream->Rn];
- if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
- remove_exclusive(cpu, write_addr);
- cpu->exclusive_state = 0;
-
- WriteMemory32(cpu, write_addr, RM);
+ if (cpu->IsExclusiveMemoryAccess(write_addr)) {
+ cpu->UnsetExclusiveMemoryAddress();
+ cpu->WriteMemory32(write_addr, RM);
RD = 0;
} else {
// Failed to write due to mutex access
RD = 1;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6112,10 +6100,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int write_addr = cpu->Reg[inst_cream->Rn];
- if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
- remove_exclusive(cpu, write_addr);
- cpu->exclusive_state = 0;
-
+ if (cpu->IsExclusiveMemoryAccess(write_addr)) {
+ cpu->UnsetExclusiveMemoryAddress();
Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]);
RD = 0;
} else {
@@ -6123,7 +6109,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = 1;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6134,20 +6120,19 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int write_addr = cpu->Reg[inst_cream->Rn];
- if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
- remove_exclusive(cpu, write_addr);
- cpu->exclusive_state = 0;
+ if (cpu->IsExclusiveMemoryAccess(write_addr)) {
+ cpu->UnsetExclusiveMemoryAddress();
const u32 rt = cpu->Reg[inst_cream->Rm + 0];
const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
u64 value;
- if (InBigEndianMode(cpu))
+ if (cpu->InBigEndianMode())
value = (((u64)rt << 32) | rt2);
else
value = (((u64)rt2 << 32) | rt);
- WriteMemory64(cpu, write_addr, value);
+ cpu->WriteMemory64(write_addr, value);
RD = 0;
}
else {
@@ -6155,7 +6140,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = 1;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6166,18 +6151,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
unsigned int write_addr = cpu->Reg[inst_cream->Rn];
- if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
- remove_exclusive(cpu, write_addr);
- cpu->exclusive_state = 0;
-
- WriteMemory16(cpu, write_addr, RM);
+ if (cpu->IsExclusiveMemoryAccess(write_addr)) {
+ cpu->UnsetExclusiveMemoryAddress();
+ cpu->WriteMemory16(write_addr, RM);
RD = 0;
} else {
// Failed to write due to mutex access
RD = 1;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6189,9 +6172,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
inst_cream->get_addr(cpu, inst_cream->inst, addr);
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
- WriteMemory16(cpu, addr, value);
+ cpu->WriteMemory16(addr, value);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6203,9 +6186,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
inst_cream->get_addr(cpu, inst_cream->inst, addr);
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
- WriteMemory32(cpu, addr, value);
+ cpu->WriteMemory32(addr, value);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ldst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6217,7 +6200,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rn_val = RN;
if (inst_cream->Rn == 15)
- rn_val += 8;
+ rn_val += 2 * cpu->GetInstructionSize();
bool carry;
bool overflow;
@@ -6226,7 +6209,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_cream->S && (inst_cream->Rd == 15)) {
if (CurrentModeHasSPSR) {
cpu->Cpsr = cpu->Spsr_copy;
- switch_mode(cpu, cpu->Spsr_copy & 0x1f);
+ cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
LOAD_NZCVT;
}
} else if (inst_cream->S) {
@@ -6240,7 +6223,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
goto DISPATCH;
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(sub_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6252,7 +6235,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
SVC::CallSVC(inst_cream->num & 0xFFFF);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(swi_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6263,12 +6246,12 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
swp_inst* inst_cream = (swp_inst*)inst_base->component;
addr = RN;
- unsigned int value = ReadMemory32(cpu, addr);
- WriteMemory32(cpu, addr, RM);
+ unsigned int value = cpu->ReadMemory32(addr);
+ cpu->WriteMemory32(addr, RM);
RD = value;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(swp_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6282,7 +6265,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
Memory::Write8(addr, (RM & 0xFF));
RD = value;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(swp_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6298,7 +6281,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2;
RD = RN + operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(uxtab_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6331,7 +6314,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(sxtab_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6347,7 +6330,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
RD = RN + operand2;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(sxtah_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6362,7 +6345,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rop = SHIFTER_OPERAND;
if (inst_cream->Rn == 15)
- lop += GET_INST_SIZE(cpu) * 2;
+ lop += cpu->GetInstructionSize() * 2;
u32 result = lop ^ rop;
@@ -6370,7 +6353,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
UPDATE_ZFLAG(result);
UPDATE_CFLAG_WITH_SC;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(teq_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6384,7 +6367,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
u32 rop = SHIFTER_OPERAND;
if (inst_cream->Rn == 15)
- lop += GET_INST_SIZE(cpu) * 2;
+ lop += cpu->GetInstructionSize() * 2;
u32 result = lop & rop;
@@ -6392,7 +6375,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
UPDATE_ZFLAG(result);
UPDATE_CFLAG_WITH_SC;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(tst_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6563,7 +6546,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6643,7 +6626,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6662,7 +6645,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RDLO = (result & 0xFFFFFFFF);
RDHI = ((result >> 32) & 0xFFFFFFFF);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(umaal_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6685,7 +6668,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->ZFlag = (RDHI == 0 && RDLO == 0);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(umlal_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6705,7 +6688,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->ZFlag = (RDHI == 0 && RDLO == 0);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(umull_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6733,7 +6716,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
{
bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(bl_1_thumb));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6814,7 +6797,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = ((lo_val & 0xFFFF) | hi_val << 16);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6844,7 +6827,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = finalDif;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(generic_arm_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6877,7 +6860,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
RD = rn_val;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ssat_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6899,7 +6882,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
cpu->Cpsr |= (1 << 27);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(ssat_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6930,7 +6913,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(uxtab_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -6943,7 +6926,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
LOG_TRACE(Core_ARM11, "WFE executed.");
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC_STUB;
FETCH_INST;
GOTO_NEXT_INST;
@@ -6956,7 +6939,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
LOG_TRACE(Core_ARM11, "WFI executed.");
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC_STUB;
FETCH_INST;
GOTO_NEXT_INST;
@@ -6969,7 +6952,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
LOG_TRACE(Core_ARM11, "YIELD executed.");
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC_STUB;
FETCH_INST;
GOTO_NEXT_INST;
diff --git a/src/core/arm/dyncom/arm_dyncom_run.cpp b/src/core/arm/dyncom/arm_dyncom_run.cpp
deleted file mode 100644
index 4c6acba98..000000000
--- a/src/core/arm/dyncom/arm_dyncom_run.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/arm/dyncom/arm_dyncom_run.h"
-#include "core/arm/skyeye_common/armstate.h"
-
-void switch_mode(ARMul_State* core, uint32_t mode) {
- if (core->Mode == mode)
- return;
-
- if (mode != USERBANK) {
- switch (core->Mode) {
- case SYSTEM32MODE: // Shares registers with user mode
- case USER32MODE:
- core->Reg_usr[0] = core->Reg[13];
- core->Reg_usr[1] = core->Reg[14];
- break;
- case IRQ32MODE:
- core->Reg_irq[0] = core->Reg[13];
- core->Reg_irq[1] = core->Reg[14];
- core->Spsr[IRQBANK] = core->Spsr_copy;
- break;
- case SVC32MODE:
- core->Reg_svc[0] = core->Reg[13];
- core->Reg_svc[1] = core->Reg[14];
- core->Spsr[SVCBANK] = core->Spsr_copy;
- break;
- case ABORT32MODE:
- core->Reg_abort[0] = core->Reg[13];
- core->Reg_abort[1] = core->Reg[14];
- core->Spsr[ABORTBANK] = core->Spsr_copy;
- break;
- case UNDEF32MODE:
- core->Reg_undef[0] = core->Reg[13];
- core->Reg_undef[1] = core->Reg[14];
- core->Spsr[UNDEFBANK] = core->Spsr_copy;
- break;
- case FIQ32MODE:
- core->Reg_firq[0] = core->Reg[13];
- core->Reg_firq[1] = core->Reg[14];
- core->Spsr[FIQBANK] = core->Spsr_copy;
- break;
- }
-
- switch (mode) {
- case USER32MODE:
- core->Reg[13] = core->Reg_usr[0];
- core->Reg[14] = core->Reg_usr[1];
- core->Bank = USERBANK;
- break;
- case IRQ32MODE:
- core->Reg[13] = core->Reg_irq[0];
- core->Reg[14] = core->Reg_irq[1];
- core->Spsr_copy = core->Spsr[IRQBANK];
- core->Bank = IRQBANK;
- break;
- case SVC32MODE:
- core->Reg[13] = core->Reg_svc[0];
- core->Reg[14] = core->Reg_svc[1];
- core->Spsr_copy = core->Spsr[SVCBANK];
- core->Bank = SVCBANK;
- break;
- case ABORT32MODE:
- core->Reg[13] = core->Reg_abort[0];
- core->Reg[14] = core->Reg_abort[1];
- core->Spsr_copy = core->Spsr[ABORTBANK];
- core->Bank = ABORTBANK;
- break;
- case UNDEF32MODE:
- core->Reg[13] = core->Reg_undef[0];
- core->Reg[14] = core->Reg_undef[1];
- core->Spsr_copy = core->Spsr[UNDEFBANK];
- core->Bank = UNDEFBANK;
- break;
- case FIQ32MODE:
- core->Reg[13] = core->Reg_firq[0];
- core->Reg[14] = core->Reg_firq[1];
- core->Spsr_copy = core->Spsr[FIQBANK];
- core->Bank = FIQBANK;
- break;
- case SYSTEM32MODE: // Shares registers with user mode.
- core->Reg[13] = core->Reg_usr[0];
- core->Reg[14] = core->Reg_usr[1];
- core->Bank = SYSTEMBANK;
- break;
- }
-
- // Set the mode bits in the APSR
- core->Cpsr = (core->Cpsr & ~core->Mode) | mode;
- core->Mode = mode;
- }
-}
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h
index ef18455bc..13bef17fc 100644
--- a/src/core/arm/dyncom/arm_dyncom_run.h
+++ b/src/core/arm/dyncom/arm_dyncom_run.h
@@ -20,38 +20,29 @@
#include "core/arm/skyeye_common/armstate.h"
-void switch_mode(ARMul_State* core, uint32_t mode);
-
-// 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;
-}
-
/**
* 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 cpu 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];
+static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) {
+ return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
}
/**
* Reads the PC. Used for data processing operations that use the PC.
*
- * @param core The ARM CPU state instance.
+ * @param cpu 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];
+static inline u32 CHECK_READ_REG15(ARMul_State* cpu, int Rn) {
+ return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index 2860af376..29272fd5d 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -12,15 +12,9 @@
// 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(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
- tdstate valid = t_uninitialized;
- u32 tinstr = instr;
-
- // The endian should be judge here
- if((addr & 0x3) != 0)
- tinstr = instr >> 16;
- else
- tinstr &= 0xFFFF;
+ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
+ ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED;
+ u32 tinstr = GetThumbInstruction(instr, addr);
*ainstr = 0xDEADC0DE; // Debugging to catch non updates
@@ -357,21 +351,21 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
else
*ainstr |= (tinstr & 0x00FF);
} else if ((tinstr & 0x0F00) != 0x0E00)
- valid = t_branch;
+ valid = ThumbDecodeStatus::BRANCH;
else // UNDEFINED : cc=1110(AL) uses different format
- valid = t_undefined;
+ valid = ThumbDecodeStatus::UNDEFINED;
break;
case 28: // B
- valid = t_branch;
+ valid = ThumbDecodeStatus::BRANCH;
break;
case 29:
- if(tinstr & 0x1)
- valid = t_undefined;
+ if (tinstr & 0x1)
+ valid = ThumbDecodeStatus::UNDEFINED;
else
- valid = t_branch;
+ valid = ThumbDecodeStatus::BRANCH;
break;
case 30: // BL instruction 1
@@ -380,7 +374,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
// simulation simple (from the user perspective) we check if the following instruction is
// the second half of this BL, and if it is we simulate it immediately
- valid = t_branch;
+ valid = ThumbDecodeStatus::BRANCH;
break;
case 31: // BL instruction 2
@@ -389,7 +383,7 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
// ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
// simulation of it on its own, with undefined results if r14 is not suitably initialised.
- valid = t_branch;
+ valid = ThumbDecodeStatus::BRANCH;
break;
}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
index c06f09580..447974363 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -28,20 +28,22 @@
#include "common/common_types.h"
-enum tdstate {
- t_undefined, // Undefined Thumb instruction
- t_decoded, // Instruction decoded to ARM equivalent
- t_branch, // Thumb branch (already processed)
- t_uninitialized,
+enum class ThumbDecodeStatus {
+ UNDEFINED, // Undefined Thumb instruction
+ DECODED, // Instruction decoded to ARM equivalent
+ BRANCH, // Thumb branch (already processed)
+ UNINITIALIZED,
};
-tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
+// Translates a Thumb mode instruction into its ARM equivalent.
+ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
-static inline u32 get_thumb_instr(u32 instr, u32 pc) {
- u32 tinstr;
- if ((pc & 0x3) != 0)
- tinstr = instr >> 16;
- else
- tinstr = instr & 0xFFFF;
- return tinstr;
+static inline u32 GetThumbInstruction(u32 instr, u32 address) {
+ // Normally you would need to handle instruction endianness,
+ // however, it is fixed to little-endian on the MPCore, so
+ // there's no need to check for this beforehand.
+ if ((address & 0x3) != 0)
+ return instr >> 16;
+
+ return instr & 0xFFFF;
}
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index d1c721809..38fa97ab9 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -55,7 +55,7 @@ enum {
};
// VFP system registers
-enum {
+enum VFPSystemRegister {
VFP_FPSID,
VFP_FPSCR,
VFP_FPEXC,
diff --git a/src/core/arm/skyeye_common/arminit.cpp b/src/core/arm/skyeye_common/arminit.cpp
deleted file mode 100644
index b7c508d75..000000000
--- a/src/core/arm/skyeye_common/arminit.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/* arminit.c -- ARMulator initialization: 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. */
-
-#include <cstring>
-#include "core/arm/skyeye_common/armstate.h"
-#include "core/arm/skyeye_common/vfp/vfp.h"
-
-// 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;
-}
-
-// Performs a reset
-void ARMul_Reset(ARMul_State* state)
-{
- VFPInit(state);
-
- state->Reg[15] = 0;
- state->Cpsr = INTBITS | SVC32MODE;
- state->Mode = SVC32MODE;
- state->Bank = SVCBANK;
-
- ResetMPCoreCP15Registers(state);
-
- state->NresetSig = HIGH;
- state->NfiqSig = HIGH;
- state->NirqSig = HIGH;
- state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
- state->abortSig = LOW;
-
- state->NumInstrs = 0;
- state->Emulate = RUN;
-}
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
deleted file mode 100644
index 5423588c0..000000000
--- a/src/core/arm/skyeye_common/armmmu.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- armmmu.c - Memory Management Unit emulation.
- ARMulator extensions for the ARM7100 family.
- Copyright (C) 1999 Ben Williamson
-
- 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
-*/
-
-#pragma once
-
-#include "common/swap.h"
-
-#include "core/memory.h"
-#include "core/arm/skyeye_common/armstate.h"
-#include "core/arm/skyeye_common/armsupp.h"
-
-// Register numbers in the MMU
-enum
-{
- MMU_ID = 0,
- MMU_CONTROL = 1,
- MMU_TRANSLATION_TABLE_BASE = 2,
- MMU_DOMAIN_ACCESS_CONTROL = 3,
- MMU_FAULT_STATUS = 5,
- MMU_FAULT_ADDRESS = 6,
- MMU_CACHE_OPS = 7,
- MMU_TLB_OPS = 8,
- MMU_CACHE_LOCKDOWN = 9,
- MMU_TLB_LOCKDOWN = 10,
- MMU_PID = 13,
-
- // MMU_V4
- MMU_V4_CACHE_OPS = 7,
- MMU_V4_TLB_OPS = 8,
-
- // MMU_V3
- MMU_V3_FLUSH_TLB = 5,
- MMU_V3_FLUSH_TLB_ENTRY = 6,
- MMU_V3_FLUSH_CACHE = 7,
-};
-
-// Reads data in big/little endian format based on the
-// state of the E (endian) bit in the emulated CPU's APSR.
-inline u16 ReadMemory16(ARMul_State* cpu, u32 address) {
- u16 data = Memory::Read16(address);
-
- if (InBigEndianMode(cpu))
- data = Common::swap16(data);
-
- return data;
-}
-
-inline u32 ReadMemory32(ARMul_State* cpu, u32 address) {
- u32 data = Memory::Read32(address);
-
- if (InBigEndianMode(cpu))
- data = Common::swap32(data);
-
- return data;
-}
-
-inline u64 ReadMemory64(ARMul_State* cpu, u32 address) {
- u64 data = Memory::Read64(address);
-
- if (InBigEndianMode(cpu))
- data = Common::swap64(data);
-
- return data;
-}
-
-// Writes data in big/little endian format based on the
-// state of the E (endian) bit in the emulated CPU's APSR.
-inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) {
- if (InBigEndianMode(cpu))
- data = Common::swap16(data);
-
- Memory::Write16(address, data);
-}
-
-inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) {
- if (InBigEndianMode(cpu))
- data = Common::swap32(data);
-
- Memory::Write32(address, data);
-}
-
-inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) {
- if (InBigEndianMode(cpu))
- data = Common::swap64(data);
-
- Memory::Write64(address, data);
-}
diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp
new file mode 100644
index 000000000..ccb2eb0eb
--- /dev/null
+++ b/src/core/arm/skyeye_common/armstate.cpp
@@ -0,0 +1,657 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/swap.h"
+#include "common/logging/log.h"
+#include "core/mem_map.h"
+#include "core/memory.h"
+#include "core/arm/skyeye_common/armstate.h"
+#include "core/arm/skyeye_common/vfp/vfp.h"
+
+ARMul_State::ARMul_State(PrivilegeMode initial_mode)
+{
+ Reset();
+ ChangePrivilegeMode(initial_mode);
+}
+
+void ARMul_State::ChangePrivilegeMode(u32 new_mode)
+{
+ if (Mode == new_mode)
+ return;
+
+ if (new_mode != USERBANK) {
+ switch (Mode) {
+ case SYSTEM32MODE: // Shares registers with user mode
+ case USER32MODE:
+ Reg_usr[0] = Reg[13];
+ Reg_usr[1] = Reg[14];
+ break;
+ case IRQ32MODE:
+ Reg_irq[0] = Reg[13];
+ Reg_irq[1] = Reg[14];
+ Spsr[IRQBANK] = Spsr_copy;
+ break;
+ case SVC32MODE:
+ Reg_svc[0] = Reg[13];
+ Reg_svc[1] = Reg[14];
+ Spsr[SVCBANK] = Spsr_copy;
+ break;
+ case ABORT32MODE:
+ Reg_abort[0] = Reg[13];
+ Reg_abort[1] = Reg[14];
+ Spsr[ABORTBANK] = Spsr_copy;
+ break;
+ case UNDEF32MODE:
+ Reg_undef[0] = Reg[13];
+ Reg_undef[1] = Reg[14];
+ Spsr[UNDEFBANK] = Spsr_copy;
+ break;
+ case FIQ32MODE:
+ Reg_firq[0] = Reg[13];
+ Reg_firq[1] = Reg[14];
+ Spsr[FIQBANK] = Spsr_copy;
+ break;
+ }
+
+ switch (new_mode) {
+ case USER32MODE:
+ Reg[13] = Reg_usr[0];
+ Reg[14] = Reg_usr[1];
+ Bank = USERBANK;
+ break;
+ case IRQ32MODE:
+ Reg[13] = Reg_irq[0];
+ Reg[14] = Reg_irq[1];
+ Spsr_copy = Spsr[IRQBANK];
+ Bank = IRQBANK;
+ break;
+ case SVC32MODE:
+ Reg[13] = Reg_svc[0];
+ Reg[14] = Reg_svc[1];
+ Spsr_copy = Spsr[SVCBANK];
+ Bank = SVCBANK;
+ break;
+ case ABORT32MODE:
+ Reg[13] = Reg_abort[0];
+ Reg[14] = Reg_abort[1];
+ Spsr_copy = Spsr[ABORTBANK];
+ Bank = ABORTBANK;
+ break;
+ case UNDEF32MODE:
+ Reg[13] = Reg_undef[0];
+ Reg[14] = Reg_undef[1];
+ Spsr_copy = Spsr[UNDEFBANK];
+ Bank = UNDEFBANK;
+ break;
+ case FIQ32MODE:
+ Reg[13] = Reg_firq[0];
+ Reg[14] = Reg_firq[1];
+ Spsr_copy = Spsr[FIQBANK];
+ Bank = FIQBANK;
+ break;
+ case SYSTEM32MODE: // Shares registers with user mode.
+ Reg[13] = Reg_usr[0];
+ Reg[14] = Reg_usr[1];
+ Bank = SYSTEMBANK;
+ break;
+ }
+
+ // Set the mode bits in the APSR
+ Cpsr = (Cpsr & ~Mode) | new_mode;
+ Mode = new_mode;
+ }
+}
+
+// Performs a reset
+void ARMul_State::Reset()
+{
+ VFPInit(this);
+
+ // Set stack pointer to the top of the stack
+ Reg[13] = 0x10000000;
+ Reg[15] = 0;
+
+ Cpsr = INTBITS | SVC32MODE;
+ Mode = SVC32MODE;
+ Bank = SVCBANK;
+
+ ResetMPCoreCP15Registers();
+
+ NresetSig = HIGH;
+ NfiqSig = HIGH;
+ NirqSig = HIGH;
+ NtransSig = (Mode & 3) ? HIGH : LOW;
+ abortSig = LOW;
+
+ NumInstrs = 0;
+ Emulate = RUN;
+}
+
+// Resets certain MPCore CP15 values to their ARM-defined reset values.
+void ARMul_State::ResetMPCoreCP15Registers()
+{
+ // c0
+ CP15[CP15_MAIN_ID] = 0x410FB024;
+ CP15[CP15_TLB_TYPE] = 0x00000800;
+ CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111;
+ CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001;
+ CP15[CP15_DEBUG_FEATURE_0] = 0x00000002;
+ CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103;
+ CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302;
+ CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000;
+ CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000;
+ CP15[CP15_ISA_FEATURE_0] = 0x00100011;
+ CP15[CP15_ISA_FEATURE_1] = 0x12002111;
+ CP15[CP15_ISA_FEATURE_2] = 0x11221011;
+ CP15[CP15_ISA_FEATURE_3] = 0x01102131;
+ CP15[CP15_ISA_FEATURE_4] = 0x00000141;
+
+ // c1
+ CP15[CP15_CONTROL] = 0x00054078;
+ CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F;
+ CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000;
+
+ // c2
+ CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000;
+ CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000;
+ CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000;
+
+ // c3
+ CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000;
+
+ // c7
+ CP15[CP15_PHYS_ADDRESS] = 0x00000000;
+
+ // c9
+ CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0;
+
+ // c10
+ CP15[CP15_TLB_LOCKDOWN] = 0x00000000;
+ CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4;
+ CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0;
+
+ // c13
+ CP15[CP15_PID] = 0x00000000;
+ CP15[CP15_CONTEXT_ID] = 0x00000000;
+ CP15[CP15_THREAD_UPRW] = 0x00000000;
+ CP15[CP15_THREAD_URO] = 0x00000000;
+ CP15[CP15_THREAD_PRW] = 0x00000000;
+
+ // c15
+ CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000;
+ CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000;
+ CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000;
+ CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000;
+ CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
+}
+
+u16 ARMul_State::ReadMemory16(u32 address) const
+{
+ u16 data = Memory::Read16(address);
+
+ if (InBigEndianMode())
+ data = Common::swap16(data);
+
+ return data;
+}
+
+u32 ARMul_State::ReadMemory32(u32 address) const
+{
+ u32 data = Memory::Read32(address);
+
+ if (InBigEndianMode())
+ data = Common::swap32(data);
+
+ return data;
+}
+
+u64 ARMul_State::ReadMemory64(u32 address) const
+{
+ u64 data = Memory::Read64(address);
+
+ if (InBigEndianMode())
+ data = Common::swap64(data);
+
+ return data;
+}
+
+void ARMul_State::WriteMemory16(u32 address, u16 data)
+{
+ if (InBigEndianMode())
+ data = Common::swap16(data);
+
+ Memory::Write16(address, data);
+}
+
+void ARMul_State::WriteMemory32(u32 address, u32 data)
+{
+ if (InBigEndianMode())
+ data = Common::swap32(data);
+
+ Memory::Write32(address, data);
+}
+
+void ARMul_State::WriteMemory64(u32 address, u64 data)
+{
+ if (InBigEndianMode())
+ data = Common::swap64(data);
+
+ Memory::Write64(address, data);
+}
+
+
+// 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 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const
+{
+ // Unprivileged registers
+ if (crn == 13 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 2)
+ return CP15[CP15_THREAD_UPRW];
+
+ if (opcode_2 == 3)
+ return CP15[CP15_THREAD_URO];
+ }
+
+ if (InAPrivilegedMode())
+ {
+ if (crn == 0 && opcode_1 == 0)
+ {
+ if (crm == 0)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_MAIN_ID];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_CACHE_TYPE];
+
+ if (opcode_2 == 3)
+ return CP15[CP15_TLB_TYPE];
+
+ if (opcode_2 == 5)
+ return CP15[CP15_CPU_ID];
+ }
+ else if (crm == 1)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_PROCESSOR_FEATURE_0];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_PROCESSOR_FEATURE_1];
+
+ if (opcode_2 == 2)
+ return CP15[CP15_DEBUG_FEATURE_0];
+
+ if (opcode_2 == 4)
+ return CP15[CP15_MEMORY_MODEL_FEATURE_0];
+
+ if (opcode_2 == 5)
+ return CP15[CP15_MEMORY_MODEL_FEATURE_1];
+
+ if (opcode_2 == 6)
+ return CP15[CP15_MEMORY_MODEL_FEATURE_2];
+
+ if (opcode_2 == 7)
+ return CP15[CP15_MEMORY_MODEL_FEATURE_3];
+ }
+ else if (crm == 2)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_ISA_FEATURE_0];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_ISA_FEATURE_1];
+
+ if (opcode_2 == 2)
+ return CP15[CP15_ISA_FEATURE_2];
+
+ if (opcode_2 == 3)
+ return CP15[CP15_ISA_FEATURE_3];
+
+ if (opcode_2 == 4)
+ return CP15[CP15_ISA_FEATURE_4];
+ }
+ }
+
+ if (crn == 1 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_CONTROL];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_AUXILIARY_CONTROL];
+
+ if (opcode_2 == 2)
+ return CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
+ }
+
+ if (crn == 2 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_TRANSLATION_BASE_TABLE_0];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_TRANSLATION_BASE_TABLE_1];
+
+ if (opcode_2 == 2)
+ return CP15[CP15_TRANSLATION_BASE_CONTROL];
+ }
+
+ if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ return CP15[CP15_DOMAIN_ACCESS_CONTROL];
+
+ if (crn == 5 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_FAULT_STATUS];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_INSTR_FAULT_STATUS];
+ }
+
+ if (crn == 6 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_FAULT_ADDRESS];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_WFAR];
+ }
+
+ if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0)
+ return CP15[CP15_PHYS_ADDRESS];
+
+ if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ return CP15[CP15_DATA_CACHE_LOCKDOWN];
+
+ if (crn == 10 && opcode_1 == 0)
+ {
+ if (crm == 0 && opcode_2 == 0)
+ return CP15[CP15_TLB_LOCKDOWN];
+
+ if (crm == 2)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_PRIMARY_REGION_REMAP];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_NORMAL_REGION_REMAP];
+ }
+ }
+
+ if (crn == 13 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_PID];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_CONTEXT_ID];
+
+ if (opcode_2 == 4)
+ return CP15[CP15_THREAD_PRW];
+ }
+
+ if (crn == 15)
+ {
+ if (opcode_1 == 0 && crm == 12)
+ {
+ if (opcode_2 == 0)
+ return CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
+
+ if (opcode_2 == 1)
+ return CP15[CP15_CYCLE_COUNTER];
+
+ if (opcode_2 == 2)
+ return CP15[CP15_COUNT_0];
+
+ if (opcode_2 == 3)
+ return CP15[CP15_COUNT_1];
+ }
+
+ if (opcode_1 == 5 && opcode_2 == 2)
+ {
+ if (crm == 5)
+ return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
+
+ if (crm == 6)
+ return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS];
+
+ if (crm == 7)
+ return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE];
+ }
+
+ if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
+ return 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 ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
+{
+ if (InAPrivilegedMode())
+ {
+ if (crn == 1 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_CONTROL] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_AUXILIARY_CONTROL] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
+ }
+ else if (crn == 2 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
+ }
+ else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ {
+ CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
+ }
+ else if (crn == 5 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_FAULT_STATUS] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_INSTR_FAULT_STATUS] = value;
+ }
+ else if (crn == 6 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_FAULT_ADDRESS] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_WFAR] = value;
+ }
+ else if (crn == 7 && opcode_1 == 0)
+ {
+ if (crm == 0 && opcode_2 == 4)
+ {
+ CP15[CP15_WAIT_FOR_INTERRUPT] = value;
+ }
+ else if (crm == 4 && opcode_2 == 0)
+ {
+ // NOTE: Not entirely accurate. This should do permission checks.
+ CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
+ }
+ else if (crm == 5)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value;
+ else if (opcode_2 == 6)
+ CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
+ else if (opcode_2 == 7)
+ CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
+ }
+ else if (crm == 6)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_INVALIDATE_DATA_CACHE] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
+ }
+ else if (crm == 7 && opcode_2 == 0)
+ {
+ CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
+ }
+ else if (crm == 10)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_CLEAN_DATA_CACHE] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
+ }
+ else if (crm == 14)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
+ }
+ }
+ else if (crn == 8 && opcode_1 == 0)
+ {
+ if (crm == 5)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_INVALIDATE_ITLB] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
+ else if (opcode_2 == 3)
+ CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
+ }
+ else if (crm == 6)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_INVALIDATE_DTLB] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
+ else if (opcode_2 == 3)
+ CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
+ }
+ else if (crm == 7)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_INVALIDATE_UTLB] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value;
+ else if (opcode_2 == 3)
+ CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
+ }
+ }
+ else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
+ {
+ CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
+ }
+ else if (crn == 10 && opcode_1 == 0)
+ {
+ if (crm == 0 && opcode_2 == 0)
+ {
+ CP15[CP15_TLB_LOCKDOWN] = value;
+ }
+ else if (crm == 2)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_PRIMARY_REGION_REMAP] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_NORMAL_REGION_REMAP] = value;
+ }
+ }
+ else if (crn == 13 && opcode_1 == 0 && crm == 0)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_PID] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_CONTEXT_ID] = value;
+ else if (opcode_2 == 3)
+ CP15[CP15_THREAD_URO] = value;
+ else if (opcode_2 == 4)
+ CP15[CP15_THREAD_PRW] = value;
+ }
+ else if (crn == 15)
+ {
+ if (opcode_1 == 0 && crm == 12)
+ {
+ if (opcode_2 == 0)
+ CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
+ else if (opcode_2 == 1)
+ CP15[CP15_CYCLE_COUNTER] = value;
+ else if (opcode_2 == 2)
+ CP15[CP15_COUNT_0] = value;
+ else if (opcode_2 == 3)
+ CP15[CP15_COUNT_1] = value;
+ }
+ else if (opcode_1 == 5)
+ {
+ if (crm == 4)
+ {
+ if (opcode_2 == 2)
+ CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
+ else if (opcode_2 == 4)
+ CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
+ }
+ else if (crm == 5 && opcode_2 == 2)
+ {
+ CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
+ }
+ else if (crm == 6 && opcode_2 == 2)
+ {
+ CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
+ }
+ else if (crm == 7 && opcode_2 == 2)
+ {
+ CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
+ }
+ }
+ else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
+ {
+ CP15[CP15_TLB_DEBUG_CONTROL] = value;
+ }
+ }
+ }
+
+ // Unprivileged registers
+ if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4)
+ {
+ CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
+ }
+ else if (crn == 7 && opcode_1 == 0 && crm == 10)
+ {
+ if (opcode_2 == 4)
+ CP15[CP15_DATA_SYNC_BARRIER] = value;
+ else if (opcode_2 == 5)
+ CP15[CP15_DATA_MEMORY_BARRIER] = value;
+ }
+ else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
+ {
+ CP15[CP15_THREAD_UPRW] = value;
+ }
+}
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h
index 3ba0ba5cd..b364e2621 100644
--- a/src/core/arm/skyeye_common/armstate.h
+++ b/src/core/arm/skyeye_common/armstate.h
@@ -17,6 +17,7 @@
#pragma once
+#include <array>
#include <unordered_map>
#include "common/common_types.h"
@@ -37,67 +38,30 @@ enum {
INSTCACHE = 2,
};
-#define VFP_REG_NUM 64
-struct ARMul_State
-{
- u32 Emulate; // To start and stop emulation
-
- // Order of the following register should not be modified
- u32 Reg[16]; // The current register file
- u32 Cpsr; // The current PSR
- u32 Spsr_copy;
- u32 phys_pc;
- u32 Reg_usr[2];
- u32 Reg_svc[2]; // R13_SVC R14_SVC
- u32 Reg_abort[2]; // R13_ABORT R14_ABORT
- u32 Reg_undef[2]; // R13 UNDEF R14 UNDEF
- u32 Reg_irq[2]; // R13_IRQ R14_IRQ
- u32 Reg_firq[7]; // R8---R14 FIRQ
- u32 Spsr[7]; // The exception psr's
- u32 Mode; // The current mode
- u32 Bank; // The current register bank
- u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
- u32 exclusive_state;
- u32 exclusive_result;
- u32 CP15[CP15_REGISTER_COUNT];
-
- // FPSID, FPSCR, and FPEXC
- u32 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).
- u32 ExtReg[VFP_REG_NUM];
- /* ---- End of the ordered registers ---- */
-
- u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
- unsigned int shifter_carry_out;
-
- // Add armv6 flags dyf:2010-08-09
- u32 GEFlag, EFlag, AFlag, QFlag;
-
- u32 TFlag; // Thumb state
-
- unsigned long long NumInstrs; // The number of instructions executed
- unsigned NumInstrsToExecute;
-
- unsigned NresetSig; // Reset the processor
- unsigned NfiqSig;
- unsigned NirqSig;
-
- unsigned abortSig;
- unsigned NtransSig;
- unsigned bigendSig;
- unsigned syscallSig;
-
- // 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;
+// ARM privilege modes
+enum PrivilegeMode {
+ USER32MODE = 16,
+ FIQ32MODE = 17,
+ IRQ32MODE = 18,
+ SVC32MODE = 19,
+ ABORT32MODE = 23,
+ UNDEF32MODE = 27,
+ SYSTEM32MODE = 31
};
-/***************************************************************************\
-* The hardware vector addresses *
-\***************************************************************************/
+// ARM privilege mode register banks
+enum {
+ USERBANK = 0,
+ FIQBANK = 1,
+ IRQBANK = 2,
+ SVCBANK = 3,
+ ABORTBANK = 4,
+ UNDEFBANK = 5,
+ DUMMYBANK = 6,
+ SYSTEMBANK = 7
+};
+// Hardware vector addresses
enum {
ARMResetV = 0,
ARMUndefinedInstrV = 4,
@@ -119,40 +83,7 @@ enum {
ARMul_FIQV = ARMFIQV
};
-/***************************************************************************\
-* Mode and Bank Constants *
-\***************************************************************************/
-
-enum PrivilegeMode {
- USER32MODE = 16,
- FIQ32MODE = 17,
- IRQ32MODE = 18,
- SVC32MODE = 19,
- ABORT32MODE = 23,
- UNDEF32MODE = 27,
- SYSTEM32MODE = 31
-};
-
-enum {
- USERBANK = 0,
- FIQBANK = 1,
- IRQBANK = 2,
- SVCBANK = 3,
- ABORTBANK = 4,
- UNDEFBANK = 5,
- DUMMYBANK = 6,
- SYSTEMBANK = 7
-};
-
-/***************************************************************************\
-* Definitions of things in the emulator *
-\***************************************************************************/
-void ARMul_Reset(ARMul_State* state);
-
-/***************************************************************************\
-* Definitions of things in the co-processor interface *
-\***************************************************************************/
-
+// Coprocessor status values
enum {
ARMul_FIRST = 0,
ARMul_TRANSFER = 1,
@@ -164,10 +95,7 @@ enum {
ARMul_INC = 3
};
-/***************************************************************************\
-* Definitions of things in the host environment *
-\***************************************************************************/
-
+// Instruction condition codes
enum ConditionCode {
EQ = 0,
NE = 1,
@@ -213,3 +141,112 @@ enum {
ONCE = 2, // Execute just one iteration
RUN = 3 // Continuous execution
};
+
+
+struct ARMul_State final
+{
+public:
+ explicit ARMul_State(PrivilegeMode initial_mode);
+
+ void ChangePrivilegeMode(u32 new_mode);
+ void Reset();
+
+ // Reads/writes data in big/little endian format based on the
+ // state of the E (endian) bit in the APSR.
+ u16 ReadMemory16(u32 address) const;
+ u32 ReadMemory32(u32 address) const;
+ u64 ReadMemory64(u32 address) const;
+ void WriteMemory16(u32 address, u16 data);
+ void WriteMemory32(u32 address, u32 data);
+ void WriteMemory64(u32 address, u64 data);
+
+ u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const;
+ void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
+
+ // Exclusive memory access functions
+ bool IsExclusiveMemoryAccess(u32 address) const {
+ return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK);
+ }
+ void SetExclusiveMemoryAddress(u32 address) {
+ exclusive_tag = address & RESERVATION_GRANULE_MASK;
+ exclusive_state = true;
+ }
+ void UnsetExclusiveMemoryAddress() {
+ exclusive_tag = 0xFFFFFFFF;
+ exclusive_state = false;
+ }
+
+ // Whether or not the given CPU is in big endian mode (E bit is set)
+ bool InBigEndianMode() const {
+ return (Cpsr & (1 << 9)) != 0;
+ }
+ // Whether or not the given CPU is in a mode other than user mode.
+ bool InAPrivilegedMode() const {
+ return (Mode != USER32MODE);
+ }
+ // 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.
+ u32 GetInstructionSize() const {
+ return TFlag ? 2 : 4;
+ }
+
+ std::array<u32, 16> Reg; // The current register file
+ std::array<u32, 2> Reg_usr;
+ std::array<u32, 2> Reg_svc; // R13_SVC R14_SVC
+ std::array<u32, 2> Reg_abort; // R13_ABORT R14_ABORT
+ std::array<u32, 2> Reg_undef; // R13 UNDEF R14 UNDEF
+ std::array<u32, 2> Reg_irq; // R13_IRQ R14_IRQ
+ std::array<u32, 7> Reg_firq; // R8---R14 FIRQ
+ std::array<u32, 7> Spsr; // The exception psr's
+ std::array<u32, CP15_REGISTER_COUNT> CP15;
+
+ // FPSID, FPSCR, and FPEXC
+ std::array<u32, VFP_SYSTEM_REGISTER_COUNT> VFP;
+
+ // 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).
+ std::array<u32, 64> ExtReg;
+
+ u32 Emulate; // To start and stop emulation
+ u32 Cpsr; // The current PSR
+ u32 Spsr_copy;
+ u32 phys_pc;
+
+ u32 Mode; // The current mode
+ u32 Bank; // The current register bank
+
+ u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
+ unsigned int shifter_carry_out;
+
+ u32 TFlag; // Thumb state
+
+ unsigned long long NumInstrs; // The number of instructions executed
+ unsigned NumInstrsToExecute;
+
+ unsigned NresetSig; // Reset the processor
+ unsigned NfiqSig;
+ unsigned NirqSig;
+
+ unsigned abortSig;
+ unsigned NtransSig;
+ unsigned bigendSig;
+ unsigned syscallSig;
+
+ // 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;
+
+private:
+ void ResetMPCoreCP15Registers();
+
+ // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
+ // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
+ // support LDR/STREXD.
+ static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
+
+ u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
+ u32 exclusive_result;
+ bool exclusive_state;
+};
diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp
index affbf193a..d31fb9449 100644
--- a/src/core/arm/skyeye_common/armsupp.cpp
+++ b/src/core/arm/skyeye_common/armsupp.cpp
@@ -206,433 +206,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
*saturation_occurred = false;
return (u32)value;
}
-
-// Whether or not the given CPU is in big endian mode (E bit is set)
-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/armsupp.h b/src/core/arm/skyeye_common/armsupp.h
index 5cf1cd1d3..391309fa8 100644
--- a/src/core/arm/skyeye_common/armsupp.h
+++ b/src/core/arm/skyeye_common/armsupp.h
@@ -6,8 +6,6 @@
#include "common/common_types.h"
-struct ARMul_State;
-
#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
#define BIT(s, n) ((s >> (n)) & 1)
@@ -32,9 +30,3 @@ u16 ARMul_UnsignedSaturatedSub16(u16, u16);
u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
u32 ARMul_SignedSatQ(s32, u8, bool*);
u32 ARMul_UnsignedSatQ(s32, u8, bool*);
-
-bool InBigEndianMode(ARMul_State*);
-bool InAPrivilegedMode(ARMul_State*);
-
-u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
-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/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index 26f303de4..0537135e2 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -21,6 +21,7 @@
/* Note: this file handles interface with arm core and vfp registers */
#include "common/common_funcs.h"
+#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/arm/skyeye_common/armstate.h"
@@ -110,30 +111,30 @@ void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m)
}
/* Miscellaneous functions */
-int32_t vfp_get_float(ARMul_State* state, unsigned int reg)
+s32 vfp_get_float(ARMul_State* state, unsigned int reg)
{
LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]);
return state->ExtReg[reg];
}
-void vfp_put_float(ARMul_State* state, int32_t val, unsigned int reg)
+void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg)
{
LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]\n", reg, val);
state->ExtReg[reg] = val;
}
-uint64_t vfp_get_double(ARMul_State* state, unsigned int reg)
+u64 vfp_get_double(ARMul_State* state, unsigned int reg)
{
- uint64_t result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
+ u64 result = ((u64) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result);
return result;
}
-void vfp_put_double(ARMul_State* state, uint64_t val, unsigned int reg)
+void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg)
{
- LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg * 2 + 1, reg * 2, (uint32_t)(val >> 32), (uint32_t)(val & 0xffffffff));
- state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff);
- state->ExtReg[reg*2+1] = (uint32_t) (val>>32);
+ LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg * 2 + 1, reg * 2, (u32)(val >> 32), (u32)(val & 0xffffffff));
+ state->ExtReg[reg*2] = (u32) (val & 0xffffffff);
+ state->ExtReg[reg*2+1] = (u32) (val>>32);
}
/*
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index 1d844a66e..47a9fe804 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -51,6 +51,7 @@
* ===========================================================================
*/
+#include <algorithm>
#include "common/logging/log.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
@@ -785,9 +786,7 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou
* This ensures that NaN propagation works correctly.
*/
if (vdn->exponent < vdm->exponent) {
- struct vfp_double *t = vdn;
- vdn = vdm;
- vdm = t;
+ std::swap(vdm, vdn);
}
/*
@@ -843,9 +842,7 @@ vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
* This ensures that NaN propagation works correctly.
*/
if (vdn->exponent < vdm->exponent) {
- struct vfp_double *t = vdn;
- vdn = vdm;
- vdm = t;
+ std::swap(vdm, vdn);
LOG_TRACE(Core_ARM11, "VFP: swapping M <-> N\n");
}
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 8efcbab1c..49298d7ba 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -51,7 +51,7 @@ VMLA_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmla_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -100,7 +100,7 @@ VMLS_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmls_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -149,7 +149,7 @@ VNMLA_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vnmla_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -199,7 +199,7 @@ VNMLS_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vnmls_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -248,7 +248,7 @@ VNMUL_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vnmul_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -297,7 +297,7 @@ VMUL_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmul_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -346,7 +346,7 @@ VADD_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vadd_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -395,7 +395,7 @@ VSUB_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vsub_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -444,7 +444,7 @@ VDIV_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vdiv_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -492,7 +492,7 @@ VMOVI_INST:
VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovi_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -536,7 +536,7 @@ VMOVR_INST:
VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -585,7 +585,7 @@ VABS_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vabs_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -635,7 +635,7 @@ VNEG_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vneg_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -684,7 +684,7 @@ VSQRT_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vsqrt_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -733,7 +733,7 @@ VCMP_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vcmp_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -782,7 +782,7 @@ VCMP2_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vcmp2_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -831,7 +831,7 @@ VCVTBDS_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vcvtbds_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -882,7 +882,7 @@ VCVTBFF_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vcvtbff_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -931,7 +931,7 @@ VCVTBFI_INST:
CHECK_VFP_CDP_RET;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vcvtbfi_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -981,7 +981,7 @@ VMOVBRS_INST:
VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t]));
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovbrs_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1032,7 +1032,7 @@ VMSR_INST:
{
cpu->VFP[VFP_FPSCR] = cpu->Reg[rt];
}
- else if (InAPrivilegedMode(cpu))
+ else if (cpu->InAPrivilegedMode())
{
if (reg == 8)
cpu->VFP[VFP_FPEXC] = cpu->Reg[rt];
@@ -1042,7 +1042,7 @@ VMSR_INST:
cpu->VFP[VFP_FPINST2] = cpu->Reg[rt];
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmsr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1090,7 +1090,7 @@ VMOVBRC_INST:
cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t];
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovbrc_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1163,7 +1163,7 @@ VMRS_INST:
{
cpu->Reg[rt] = cpu->VFP[VFP_MVFR0];
}
- else if (InAPrivilegedMode(cpu))
+ else if (cpu->InAPrivilegedMode())
{
if (reg == 8)
cpu->Reg[rt] = cpu->VFP[VFP_FPEXC];
@@ -1173,7 +1173,7 @@ VMRS_INST:
cpu->Reg[rt] = cpu->VFP[VFP_FPINST2];
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmrs_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1221,7 +1221,7 @@ VMOVBCR_INST:
cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index];
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovbcr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1274,7 +1274,7 @@ VMOVBRRSS_INST:
VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
&cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]);
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovbrrss_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1322,7 +1322,7 @@ VMOVBRRD_INST:
VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
&(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2]));
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vmovbrrd_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1378,23 +1378,23 @@ VSTR_INST:
if (inst_cream->single)
{
- WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]);
+ cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]);
}
else
{
const u32 word1 = cpu->ExtReg[inst_cream->d*2+0];
const u32 word2 = cpu->ExtReg[inst_cream->d*2+1];
- if (InBigEndianMode(cpu)) {
- WriteMemory32(cpu, addr + 0, word2);
- WriteMemory32(cpu, addr + 4, word1);
+ if (cpu->InBigEndianMode()) {
+ cpu->WriteMemory32(addr + 0, word2);
+ cpu->WriteMemory32(addr + 4, word1);
} else {
- WriteMemory32(cpu, addr + 0, word1);
- WriteMemory32(cpu, addr + 4, word2);
+ cpu->WriteMemory32(addr + 0, word1);
+ cpu->WriteMemory32(addr + 4, word2);
}
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vstr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1444,7 +1444,7 @@ VPUSH_INST:
{
if (inst_cream->single)
{
- WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
+ cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]);
addr += 4;
}
else
@@ -1452,12 +1452,12 @@ VPUSH_INST:
const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
- if (InBigEndianMode(cpu)) {
- WriteMemory32(cpu, addr + 0, word2);
- WriteMemory32(cpu, addr + 4, word1);
+ if (cpu->InBigEndianMode()) {
+ cpu->WriteMemory32(addr + 0, word2);
+ cpu->WriteMemory32(addr + 4, word1);
} else {
- WriteMemory32(cpu, addr + 0, word1);
- WriteMemory32(cpu, addr + 4, word2);
+ cpu->WriteMemory32(addr + 0, word1);
+ cpu->WriteMemory32(addr + 4, word2);
}
addr += 8;
@@ -1466,7 +1466,7 @@ VPUSH_INST:
cpu->Reg[R13] -= inst_cream->imm32;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vpush_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1511,37 +1511,44 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VSTM_INST: /* encoding 1 */
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
- vstm_inst *inst_cream = (vstm_inst *)inst_base->component;
+ vstm_inst* inst_cream = (vstm_inst*)inst_base->component;
+
+ u32 address = cpu->Reg[inst_cream->n];
- addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
+ // Only possible in ARM mode, where PC accesses have an 8 byte offset.
+ if (inst_cream->n == 15)
+ address += 8;
+
+ if (inst_cream->add == 0)
+ address -= inst_cream->imm32;
for (unsigned int i = 0; i < inst_cream->regs; i++)
{
if (inst_cream->single)
{
- WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
- addr += 4;
+ cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d+i]);
+ address += 4;
}
else
{
const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
- if (InBigEndianMode(cpu)) {
- WriteMemory32(cpu, addr + 0, word2);
- WriteMemory32(cpu, addr + 4, word1);
+ if (cpu->InBigEndianMode()) {
+ cpu->WriteMemory32(address + 0, word2);
+ cpu->WriteMemory32(address + 4, word1);
} else {
- WriteMemory32(cpu, addr + 0, word1);
- WriteMemory32(cpu, addr + 4, word2);
+ cpu->WriteMemory32(address + 0, word1);
+ cpu->WriteMemory32(address + 4, word2);
}
- addr += 8;
+ address += 8;
}
}
- if (inst_cream->wback){
+ if (inst_cream->wback) {
cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 :
cpu->Reg[inst_cream->n] - inst_cream->imm32);
}
@@ -1597,15 +1604,15 @@ VPOP_INST:
{
if (inst_cream->single)
{
- cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
+ cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr);
addr += 4;
}
else
{
- const u32 word1 = ReadMemory32(cpu, addr + 0);
- const u32 word2 = ReadMemory32(cpu, addr + 4);
+ const u32 word1 = cpu->ReadMemory32(addr + 0);
+ const u32 word2 = cpu->ReadMemory32(addr + 4);
- if (InBigEndianMode(cpu)) {
+ if (cpu->InBigEndianMode()) {
cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
} else {
@@ -1618,7 +1625,7 @@ VPOP_INST:
}
cpu->Reg[R13] += inst_cream->imm32;
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vpop_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1670,14 +1677,14 @@ VLDR_INST:
if (inst_cream->single)
{
- cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr);
+ cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr);
}
else
{
- const u32 word1 = ReadMemory32(cpu, addr + 0);
- const u32 word2 = ReadMemory32(cpu, addr + 4);
+ const u32 word1 = cpu->ReadMemory32(addr + 0);
+ const u32 word2 = cpu->ReadMemory32(addr + 4);
- if (InBigEndianMode(cpu)) {
+ if (cpu->InBigEndianMode()) {
cpu->ExtReg[inst_cream->d*2+0] = word2;
cpu->ExtReg[inst_cream->d*2+1] = word1;
} else {
@@ -1686,7 +1693,7 @@ VLDR_INST:
}
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vldr_inst));
FETCH_INST;
GOTO_NEXT_INST;
@@ -1731,26 +1738,33 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VLDM_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
CHECK_VFP_ENABLED;
- vldm_inst *inst_cream = (vldm_inst *)inst_base->component;
+ vldm_inst* inst_cream = (vldm_inst*)inst_base->component;
+
+ u32 address = cpu->Reg[inst_cream->n];
- addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
+ // Only possible in ARM mode, where PC accesses have an 8 byte offset.
+ if (inst_cream->n == 15)
+ address += 8;
+
+ if (inst_cream->add == 0)
+ address -= inst_cream->imm32;
for (unsigned int i = 0; i < inst_cream->regs; i++)
{
if (inst_cream->single)
{
- cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
- addr += 4;
+ cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(address);
+ address += 4;
}
else
{
- const u32 word1 = ReadMemory32(cpu, addr + 0);
- const u32 word2 = ReadMemory32(cpu, addr + 4);
+ const u32 word1 = cpu->ReadMemory32(address + 0);
+ const u32 word2 = cpu->ReadMemory32(address + 4);
- if (InBigEndianMode(cpu)) {
+ if (cpu->InBigEndianMode()) {
cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
} else {
@@ -1758,15 +1772,15 @@ VLDM_INST:
cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
}
- addr += 8;
+ address += 8;
}
}
- if (inst_cream->wback){
+ if (inst_cream->wback) {
cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 :
cpu->Reg[inst_cream->n] - inst_cream->imm32);
}
}
- cpu->Reg[15] += GET_INST_SIZE(cpu);
+ cpu->Reg[15] += cpu->GetInstructionSize();
INC_PC(sizeof(vldm_inst));
FETCH_INST;
GOTO_NEXT_INST;
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index e5d339252..0fb3c3bf1 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -51,6 +51,7 @@
* ===========================================================================
*/
+#include <algorithm>
#include <cinttypes>
#include "common/common_funcs.h"
@@ -815,9 +816,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
* This ensures that NaN propagation works correctly.
*/
if (vsn->exponent < vsm->exponent) {
- struct vfp_single *t = vsn;
- vsn = vsm;
- vsm = t;
+ std::swap(vsm, vsn);
}
/*
@@ -872,9 +871,7 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s
* This ensures that NaN propagation works correctly.
*/
if (vsn->exponent < vsm->exponent) {
- struct vfp_single *t = vsn;
- vsn = vsm;
- vsm = t;
+ std::swap(vsm, vsn);
LOG_TRACE(Core_ARM11, "swapping M <-> N");
}
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
index 826f6cbb6..bc2a1829e 100644
--- a/src/core/hle/applets/applet.cpp
+++ b/src/core/hle/applets/applet.cpp
@@ -89,12 +89,21 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter)
return result;
}
+bool IsLibraryAppletRunning() {
+ // Check the applets map for instances of any applet
+ for (auto itr = applets.begin(); itr != applets.end(); ++itr)
+ if (itr->second != nullptr)
+ return true;
+ return false;
+}
+
void Init() {
// Register the applet update callback
applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent);
}
void Shutdown() {
+ CoreTiming::RemoveEvent(applet_update_event);
}
}
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
index b235d0b8a..af442f81d 100644
--- a/src/core/hle/applets/applet.h
+++ b/src/core/hle/applets/applet.h
@@ -67,6 +67,9 @@ protected:
Service::APT::AppletId id; ///< Id of this Applet
};
+/// Returns whether a library applet is currently running
+bool IsLibraryAppletRunning();
+
/// Initializes the HLE applets
void Init();
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 7332478fb..7ae4859a7 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -5,6 +5,7 @@
#include "common/logging/log.h"
#include "core/hle/service/service.h"
+#include "core/hle/service/am/am.h"
#include "core/hle/service/am/am_app.h"
#include "core/hle/service/am/am_net.h"
#include "core/hle/service/am/am_sys.h"
@@ -35,7 +36,7 @@ void GetTitleIDList(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = 0;
- LOG_WARNING(Service_AM, "(STUBBED) Requested %u titles from media type %u", num_titles, media_type);
+ LOG_WARNING(Service_AM, "(STUBBED) Requested %u titles from media type %u. Address=0x%08X", num_titles, media_type, addr);
}
void GetNumContentInfos(Service::Interface* self) {
diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp
index b1af0e9d8..aa391f3b2 100644
--- a/src/core/hle/service/am/am_net.cpp
+++ b/src/core/hle/service/am/am_net.cpp
@@ -28,7 +28,8 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x08130000, nullptr, "GetTotalContents"},
{0x08140042, nullptr, "GetContentIndexes"},
{0x08150044, nullptr, "GetContentsInfo"},
- {0x08190108, nullptr, "Unknown"},
+ {0x08180042, nullptr, "GetCTCert"},
+ {0x08190108, nullptr, "SetCertificates"},
{0x081B00C2, nullptr, "InstallTitlesFinish"},
};
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 7b6ab4ce0..35402341b 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -101,18 +101,19 @@ void NotifyToWait(Service::Interface* self) {
void GetLockHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
+ // Bits [0:2] are the applet type (System, Library, etc)
+ // Bit 5 tells the application that there's a pending APT parameter,
+ // this will cause the app to wait until parameter_event is signaled.
+ u32 applet_attributes = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- // Not sure what these parameters are used for, but retail apps check that they are 0 after
- // GetLockHandle has been called.
- cmd_buff[2] = 0; // Applet Attributes, this value is passed to Enable.
- cmd_buff[3] = 0;
- cmd_buff[4] = 0;
-
+ cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable.
+ cmd_buff[3] = 0; // Least significant bit = power button state
+ cmd_buff[4] = IPC::CopyHandleDesc();
cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
- LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]);
+
+ LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes);
}
void Enable(Service::Interface* self) {
@@ -139,13 +140,16 @@ void IsRegistered(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 app_id = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- /// TODO(Subv): It is currently unknown what this value (0x400) means,
- /// but i believe it is used as a global "LibraryApplet" id, to verify if there's
- /// any LibApplet currently running. This is not verified.
- if (app_id != 0x400)
+
+ // TODO(Subv): An application is considered "registered" if it has already called APT::Enable
+ // handle this properly once we implement multiprocess support.
+ cmd_buff[2] = 0; // Set to not registered by default
+
+ if (app_id == static_cast<u32>(AppletId::AnyLibraryApplet)) {
+ cmd_buff[2] = HLE::Applets::IsLibraryAppletRunning() ? 1 : 0;
+ } else if (auto applet = HLE::Applets::Applet::Get(static_cast<AppletId>(app_id))) {
cmd_buff[2] = 1; // Set to registered
- else
- cmd_buff[2] = 0; // Set to not registered
+ }
LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
}
@@ -330,7 +334,26 @@ void GetAppCpuTimeLimit(Service::Interface* self) {
void PrepareToStartLibraryApplet(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
AppletId applet_id = static_cast<AppletId>(cmd_buff[1]);
- cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw;
+ auto applet = HLE::Applets::Applet::Get(applet_id);
+ if (applet) {
+ LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ } else {
+ cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw;
+ }
+ LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id);
+}
+
+void PreloadLibraryApplet(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ AppletId applet_id = static_cast<AppletId>(cmd_buff[1]);
+ auto applet = HLE::Applets::Applet::Get(applet_id);
+ if (applet) {
+ LOG_WARNING(Service_APT, "applet has already been started id=%08X", applet_id);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ } else {
+ cmd_buff[1] = HLE::Applets::Applet::Create(applet_id).raw;
+ }
LOG_DEBUG(Service_APT, "called applet_id=%08X", applet_id);
}
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index 72972d05b..4a72b6b5c 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -62,6 +62,7 @@ enum class AppletId : u32 {
Extrapad = 0x208,
Memolib = 0x209,
Application = 0x300,
+ AnyLibraryApplet = 0x400,
SoftwareKeyboard2 = 0x401,
};
@@ -96,8 +97,26 @@ void GetSharedFont(Service::Interface* self);
*/
void NotifyToWait(Service::Interface* self);
+/**
+ * APT::GetLockHandle service function
+ * Inputs:
+ * 1 : Applet attributes
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Applet attributes
+ * 3 : Power button state
+ * 4 : IPC handle descriptor
+ * 5 : APT mutex handle
+ */
void GetLockHandle(Service::Interface* self);
+/**
+ * APT::Enable service function
+ * Inputs:
+ * 1 : Applet attributes
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
void Enable(Service::Interface* self);
/**
@@ -284,6 +303,17 @@ void GetAppCpuTimeLimit(Service::Interface* self);
void PrepareToStartLibraryApplet(Service::Interface* self);
/**
+ * APT::PreloadLibraryApplet service function
+ * Inputs:
+ * 0 : Command header [0x00160040]
+ * 1 : Id of the applet to start
+ * Outputs:
+ * 0 : Return header
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void PreloadLibraryApplet(Service::Interface* self);
+
+/**
* APT::StartLibraryApplet service function
* Inputs:
* 0 : Command header [0x001E0084]
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 88de339f9..22800c56f 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -21,6 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x000D0080, ReceiveParameter, "ReceiveParameter"},
{0x000E0080, GlanceParameter, "GlanceParameter"},
{0x000F0100, CancelParameter, "CancelParameter"},
+ {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
{0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
{0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
{0x003B0040, nullptr, "CancelLibraryApplet?"},
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index 396d1f04a..3ac6ff94f 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -32,9 +32,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00130000, nullptr, "GetPreparationState"},
{0x00140040, nullptr, "SetPreparationState"},
{0x00150140, nullptr, "PrepareToStartApplication"},
- {0x00160040, nullptr, "PreloadLibraryApplet"},
+ {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
{0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
- {0x00180040, nullptr, "PrepareToStartLibraryApplet"},
+ {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"},
{0x00190040, nullptr, "PrepareToStartSystemApplet"},
{0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
{0x001B00C4, nullptr, "StartApplication"},
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index b724cd72b..146bfd595 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -33,7 +33,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00130000, nullptr, "GetPreparationState"},
{0x00140040, nullptr, "SetPreparationState"},
{0x00150140, nullptr, "PrepareToStartApplication"},
- {0x00160040, nullptr, "PreloadLibraryApplet"},
+ {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
{0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
{0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
{0x00190040, nullptr, "PrepareToStartSystemApplet"},
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 70caa7d80..c35b13b25 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -35,6 +35,16 @@ static Kernel::SharedPtr<Kernel::Event> event_debug_pad;
static u32 next_pad_index;
static u32 next_touch_index;
+const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = {
+ Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y,
+ Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR,
+ Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE,
+ Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT,
+ Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT,
+ Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT
+};
+
+
// TODO(peachum):
// Add a method for setting analog input from joystick device for the circle Pad.
//
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index d50d479f8..517f4f2ae 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -9,7 +9,7 @@
#ifndef _MSC_VER
#include <cstddef>
#endif
-
+#include "core/settings.h"
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
@@ -157,6 +157,9 @@ const PadState PAD_CIRCLE_LEFT = {{1u << 29}};
const PadState PAD_CIRCLE_UP = {{1u << 30}};
const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
+
+extern const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping;
+
/**
* HID::GetIPCHandles service function
* Inputs:
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
index 155b97f69..f84ce4d72 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -40,7 +40,8 @@ static void Initialize(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_LDR, "(STUBBED) called");
+ LOG_WARNING(Service_LDR, "(STUBBED) called. crs_buffer_ptr=0x%08X, crs_size=0x%08X, address=0x%08X, value=0x%08X, process=0x%08X",
+ crs_buffer_ptr, crs_size, address, value, process);
}
/**
@@ -69,7 +70,8 @@ static void LoadCRR(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_LDR, "(STUBBED) called");
+ LOG_WARNING(Service_LDR, "(STUBBED) called. crs_buffer_ptr=0x%08X, crs_size=0x%08X, value=0x%08X, process=0x%08X",
+ crs_buffer_ptr, crs_size, value, process);
}
const Interface::FunctionInfo FunctionTable[] = {
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index d0e166fdf..d768a3fc7 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -481,11 +481,17 @@ static void GetHostId(Service::Interface* self) {
char name[128];
gethostname(name, sizeof(name));
- hostent* host = gethostbyname(name);
- in_addr* addr = reinterpret_cast<in_addr*>(host->h_addr);
+ addrinfo hints = {};
+ addrinfo* res;
+
+ hints.ai_family = AF_INET;
+ getaddrinfo(name, NULL, &hints, &res);
+ sockaddr_in* sock_addr = reinterpret_cast<sockaddr_in*>(res->ai_addr);
+ in_addr* addr = &sock_addr->sin_addr;
cmd_buffer[2] = addr->s_addr;
cmd_buffer[1] = 0;
+ freeaddrinfo(res);
}
static void Close(Service::Interface* self) {
diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp
index f80e26ecd..082a4db82 100644
--- a/src/core/hw/y2r.cpp
+++ b/src/core/hw/y2r.cpp
@@ -14,6 +14,7 @@
#include "common/vector_math.h"
#include "core/hle/service/y2r_u.h"
+#include "core/hw/y2r.h"
#include "core/memory.h"
namespace HW {
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index f5b349a77..062291006 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -77,6 +77,8 @@ static const char* GetFileTypeString(FileType type) {
return "NCSD";
case FileType::CXI:
return "NCCH";
+ case FileType::CIA:
+ return "CIA";
case FileType::ELF:
return "ELF";
case FileType::THREEDSX:
@@ -134,6 +136,10 @@ ResultStatus LoadFile(const std::string& filename) {
break;
}
+ // CIA file format...
+ case FileType::CIA:
+ return ResultStatus::ErrorNotImplemented;
+
// Error occurred durring IdentifyFile...
case FileType::Error:
diff --git a/src/core/settings.h b/src/core/settings.h
index 5a70d157a..6ca0e1afc 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -5,34 +5,42 @@
#pragma once
#include <string>
+#include <array>
namespace Settings {
+namespace NativeInput {
+enum Values {
+ A, B, X, Y,
+ L, R, ZL, ZR,
+ START, SELECT, HOME,
+ DUP, DDOWN, DLEFT, DRIGHT,
+ SUP, SDOWN, SLEFT, SRIGHT,
+ CUP, CDOWN, CLEFT, CRIGHT,
+ NUM_INPUTS
+};
+static const std::array<const char*, NUM_INPUTS> Mapping = {
+ "pad_a", "pad_b", "pad_x", "pad_y",
+ "pad_l", "pad_r", "pad_zl", "pad_zr",
+ "pad_start", "pad_select", "pad_home",
+ "pad_dup", "pad_ddown", "pad_dleft", "pad_dright",
+ "pad_sup", "pad_sdown", "pad_sleft", "pad_sright",
+ "pad_cup", "pad_cdown", "pad_cleft", "pad_cright"
+};
+static const std::array<Values, NUM_INPUTS> All = {
+ A, B, X, Y,
+ L, R, ZL, ZR,
+ START, SELECT, HOME,
+ DUP, DDOWN, DLEFT, DRIGHT,
+ SUP, SDOWN, SLEFT, SRIGHT,
+ CUP, CDOWN, CLEFT, CRIGHT
+};
+}
+
+
struct Values {
// Controls
- int pad_a_key;
- int pad_b_key;
- int pad_x_key;
- int pad_y_key;
- int pad_l_key;
- int pad_r_key;
- int pad_zl_key;
- int pad_zr_key;
- int pad_start_key;
- int pad_select_key;
- int pad_home_key;
- int pad_dup_key;
- int pad_ddown_key;
- int pad_dleft_key;
- int pad_dright_key;
- int pad_sup_key;
- int pad_sdown_key;
- int pad_sleft_key;
- int pad_sright_key;
- int pad_cup_key;
- int pad_cdown_key;
- int pad_cleft_key;
- int pad_cright_key;
+ std::array<int, NativeInput::NUM_INPUTS> input_mappings;
// Core
int frame_skip;
@@ -45,6 +53,7 @@ struct Values {
// Renderer
bool use_hw_renderer;
+ bool use_shader_jit;
float bg_red;
float bg_green;
diff --git a/src/core/tracer/citrace.h b/src/core/tracer/citrace.h
index 5deb6ce9e..709abdfb3 100644
--- a/src/core/tracer/citrace.h
+++ b/src/core/tracer/citrace.h
@@ -4,7 +4,7 @@
#pragma once
-#include <cstdint>
+#include "common/common_types.h"
namespace CiTrace {
@@ -17,38 +17,38 @@ struct CTHeader {
return "CiTr";
}
- static uint32_t ExpectedVersion() {
+ static u32 ExpectedVersion() {
return 1;
}
char magic[4];
- uint32_t version;
- uint32_t header_size;
+ u32 version;
+ u32 header_size;
struct {
// NOTE: Register range sizes are technically hardware-constants, but the actual limits
// aren't known. Hence we store the presumed limits along the offsets.
- // Sizes are given in uint32_t units.
- uint32_t gpu_registers;
- uint32_t gpu_registers_size;
- uint32_t lcd_registers;
- uint32_t lcd_registers_size;
- uint32_t pica_registers;
- uint32_t pica_registers_size;
- uint32_t default_attributes;
- uint32_t default_attributes_size;
- uint32_t vs_program_binary;
- uint32_t vs_program_binary_size;
- uint32_t vs_swizzle_data;
- uint32_t vs_swizzle_data_size;
- uint32_t vs_float_uniforms;
- uint32_t vs_float_uniforms_size;
- uint32_t gs_program_binary;
- uint32_t gs_program_binary_size;
- uint32_t gs_swizzle_data;
- uint32_t gs_swizzle_data_size;
- uint32_t gs_float_uniforms;
- uint32_t gs_float_uniforms_size;
+ // Sizes are given in u32 units.
+ u32 gpu_registers;
+ u32 gpu_registers_size;
+ u32 lcd_registers;
+ u32 lcd_registers_size;
+ u32 pica_registers;
+ u32 pica_registers_size;
+ u32 default_attributes;
+ u32 default_attributes_size;
+ u32 vs_program_binary;
+ u32 vs_program_binary_size;
+ u32 vs_swizzle_data;
+ u32 vs_swizzle_data_size;
+ u32 vs_float_uniforms;
+ u32 vs_float_uniforms_size;
+ u32 gs_program_binary;
+ u32 gs_program_binary_size;
+ u32 gs_swizzle_data;
+ u32 gs_swizzle_data_size;
+ u32 gs_float_uniforms;
+ u32 gs_float_uniforms_size;
// Other things we might want to store here:
// - Initial framebuffer data, maybe even a full copy of FCRAM/VRAM
@@ -56,27 +56,27 @@ struct CTHeader {
// - Lookup tables for procedural textures
} initial_state_offsets;
- uint32_t stream_offset;
- uint32_t stream_size;
+ u32 stream_offset;
+ u32 stream_size;
};
-enum CTStreamElementType : uint32_t {
+enum CTStreamElementType : u32 {
FrameMarker = 0xE1,
MemoryLoad = 0xE2,
RegisterWrite = 0xE3,
};
struct CTMemoryLoad {
- uint32_t file_offset;
- uint32_t size;
- uint32_t physical_address;
- uint32_t pad;
+ u32 file_offset;
+ u32 size;
+ u32 physical_address;
+ u32 pad;
};
struct CTRegisterWrite {
- uint32_t physical_address;
+ u32 physical_address;
- enum : uint32_t {
+ enum : u32 {
SIZE_8 = 0xD1,
SIZE_16 = 0xD2,
SIZE_32 = 0xD3,
@@ -84,7 +84,7 @@ struct CTRegisterWrite {
} size;
// TODO: Make it clearer which bits of this member are used for sizes other than 32 bits
- uint64_t value;
+ u64 value;
};
struct CTStreamElement {