forked from suyu/suyu
commit
1981aa3d7e
7 changed files with 239 additions and 82 deletions
|
@ -1075,6 +1075,10 @@ typedef struct _swp_inst {
|
||||||
unsigned int Rm;
|
unsigned int Rm;
|
||||||
} swp_inst;
|
} swp_inst;
|
||||||
|
|
||||||
|
typedef struct setend_inst {
|
||||||
|
unsigned int set_bigend;
|
||||||
|
} setend_inst;
|
||||||
|
|
||||||
typedef struct _b_2_thumb {
|
typedef struct _b_2_thumb {
|
||||||
unsigned int imm;
|
unsigned int imm;
|
||||||
}b_2_thumb;
|
}b_2_thumb;
|
||||||
|
@ -2283,7 +2287,20 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index)
|
||||||
return inst_base;
|
return inst_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); }
|
static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)
|
||||||
|
{
|
||||||
|
arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
|
||||||
|
setend_inst* const inst_cream = (setend_inst*)inst_base->component;
|
||||||
|
|
||||||
|
inst_base->cond = AL;
|
||||||
|
inst_base->idx = index;
|
||||||
|
inst_base->br = NON_BRANCH;
|
||||||
|
inst_base->load_r15 = 0;
|
||||||
|
|
||||||
|
inst_cream->set_bigend = BIT(inst, 9);
|
||||||
|
|
||||||
|
return inst_base;
|
||||||
|
}
|
||||||
|
|
||||||
static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index)
|
static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index)
|
||||||
{
|
{
|
||||||
|
@ -4345,30 +4362,30 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
if (BIT(inst, 22) && !BIT(inst, 15)) {
|
if (BIT(inst, 22) && !BIT(inst, 15)) {
|
||||||
for (int i = 0; i < 13; i++) {
|
for (int i = 0; i < 13; i++) {
|
||||||
if(BIT(inst, i)) {
|
if(BIT(inst, i)) {
|
||||||
cpu->Reg[i] = Memory::Read32(addr);
|
cpu->Reg[i] = ReadMemory32(cpu, addr);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (BIT(inst, 13)) {
|
if (BIT(inst, 13)) {
|
||||||
if (cpu->Mode == USER32MODE)
|
if (cpu->Mode == USER32MODE)
|
||||||
cpu->Reg[13] = Memory::Read32(addr);
|
cpu->Reg[13] = ReadMemory32(cpu, addr);
|
||||||
else
|
else
|
||||||
cpu->Reg_usr[0] = Memory::Read32(addr);
|
cpu->Reg_usr[0] = ReadMemory32(cpu, addr);
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
if (BIT(inst, 14)) {
|
if (BIT(inst, 14)) {
|
||||||
if (cpu->Mode == USER32MODE)
|
if (cpu->Mode == USER32MODE)
|
||||||
cpu->Reg[14] = Memory::Read32(addr);
|
cpu->Reg[14] = ReadMemory32(cpu, addr);
|
||||||
else
|
else
|
||||||
cpu->Reg_usr[1] = Memory::Read32(addr);
|
cpu->Reg_usr[1] = ReadMemory32(cpu, addr);
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
} else if (!BIT(inst, 22)) {
|
} else if (!BIT(inst, 22)) {
|
||||||
for(int i = 0; i < 16; i++ ){
|
for(int i = 0; i < 16; i++ ){
|
||||||
if(BIT(inst, i)){
|
if(BIT(inst, i)){
|
||||||
unsigned int ret = Memory::Read32(addr);
|
unsigned int ret = ReadMemory32(cpu, addr);
|
||||||
|
|
||||||
// For armv5t, should enter thumb when bits[0] is non-zero.
|
// For armv5t, should enter thumb when bits[0] is non-zero.
|
||||||
if(i == 15){
|
if(i == 15){
|
||||||
|
@ -4383,7 +4400,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
} else if (BIT(inst, 22) && BIT(inst, 15)) {
|
} else if (BIT(inst, 22) && BIT(inst, 15)) {
|
||||||
for(int i = 0; i < 15; i++ ){
|
for(int i = 0; i < 15; i++ ){
|
||||||
if(BIT(inst, i)){
|
if(BIT(inst, i)){
|
||||||
cpu->Reg[i] = Memory::Read32(addr);
|
cpu->Reg[i] = ReadMemory32(cpu, addr);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4394,7 +4411,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LOAD_NZCVT;
|
LOAD_NZCVT;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->Reg[15] = Memory::Read32(addr);
|
cpu->Reg[15] = ReadMemory32(cpu, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BIT(inst, 15)) {
|
if (BIT(inst, 15)) {
|
||||||
|
@ -4428,10 +4445,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
LDR_INST:
|
LDR_INST:
|
||||||
{
|
{
|
||||||
ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
|
ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
|
||||||
//if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
||||||
|
|
||||||
unsigned int value = Memory::Read32(addr);
|
unsigned int value = ReadMemory32(cpu, addr);
|
||||||
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
|
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
|
||||||
|
|
||||||
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
||||||
|
@ -4441,7 +4457,6 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
goto DISPATCH;
|
goto DISPATCH;
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
|
@ -4454,7 +4469,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
|
ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
||||||
|
|
||||||
unsigned int value = Memory::Read32(addr);
|
unsigned int value = ReadMemory32(cpu, addr);
|
||||||
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
|
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
|
||||||
|
|
||||||
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
||||||
|
@ -4537,8 +4552,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
// Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
|
// Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
||||||
|
|
||||||
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read32(addr);
|
// The 3DS doesn't have LPAE (Large Physical Access Extension), so it
|
||||||
cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = Memory::Read32(addr + 4);
|
// 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);
|
||||||
|
|
||||||
// No dispatch since this operation should not modify R15
|
// No dispatch since this operation should not modify R15
|
||||||
}
|
}
|
||||||
|
@ -4557,7 +4574,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
add_exclusive_addr(cpu, read_addr);
|
add_exclusive_addr(cpu, read_addr);
|
||||||
cpu->exclusive_state = 1;
|
cpu->exclusive_state = 1;
|
||||||
|
|
||||||
RD = Memory::Read32(read_addr);
|
RD = ReadMemory32(cpu, read_addr);
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(generic_arm_inst));
|
INC_PC(sizeof(generic_arm_inst));
|
||||||
goto DISPATCH;
|
goto DISPATCH;
|
||||||
|
@ -4597,7 +4614,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
add_exclusive_addr(cpu, read_addr);
|
add_exclusive_addr(cpu, read_addr);
|
||||||
cpu->exclusive_state = 1;
|
cpu->exclusive_state = 1;
|
||||||
|
|
||||||
RD = Memory::Read16(read_addr);
|
RD = ReadMemory16(cpu, read_addr);
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(generic_arm_inst));
|
INC_PC(sizeof(generic_arm_inst));
|
||||||
goto DISPATCH;
|
goto DISPATCH;
|
||||||
|
@ -4617,8 +4634,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
add_exclusive_addr(cpu, read_addr);
|
add_exclusive_addr(cpu, read_addr);
|
||||||
cpu->exclusive_state = 1;
|
cpu->exclusive_state = 1;
|
||||||
|
|
||||||
RD = Memory::Read32(read_addr);
|
RD = ReadMemory32(cpu, read_addr);
|
||||||
RD2 = Memory::Read32(read_addr + 4);
|
RD2 = ReadMemory32(cpu, read_addr + 4);
|
||||||
|
|
||||||
if (inst_cream->Rd == 15) {
|
if (inst_cream->Rd == 15) {
|
||||||
INC_PC(sizeof(generic_arm_inst));
|
INC_PC(sizeof(generic_arm_inst));
|
||||||
|
@ -4635,7 +4652,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
||||||
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read16(addr);
|
|
||||||
|
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr);
|
||||||
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
goto DISPATCH;
|
goto DISPATCH;
|
||||||
|
@ -4671,7 +4689,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
|
||||||
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
||||||
unsigned int value = Memory::Read16(addr);
|
|
||||||
|
unsigned int value = ReadMemory16(cpu, addr);
|
||||||
if (BIT(value, 15)) {
|
if (BIT(value, 15)) {
|
||||||
value |= 0xffff0000;
|
value |= 0xffff0000;
|
||||||
}
|
}
|
||||||
|
@ -4692,7 +4711,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
|
||||||
|
|
||||||
unsigned int value = Memory::Read32(addr);
|
unsigned int value = ReadMemory32(cpu, addr);
|
||||||
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
|
cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
|
||||||
|
|
||||||
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
if (BITS(inst_cream->inst, 12, 15) == 15) {
|
||||||
|
@ -5521,6 +5540,23 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SETEND_INST:
|
SETEND_INST:
|
||||||
|
{
|
||||||
|
// SETEND is unconditional
|
||||||
|
setend_inst* const inst_cream = (setend_inst*)inst_base->component;
|
||||||
|
const bool big_endian = (inst_cream->set_bigend == 1);
|
||||||
|
|
||||||
|
if (big_endian)
|
||||||
|
cpu->Cpsr |= (1 << 9);
|
||||||
|
else
|
||||||
|
cpu->Cpsr &= ~(1 << 9);
|
||||||
|
|
||||||
|
LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE");
|
||||||
|
|
||||||
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
|
INC_PC(sizeof(setend_inst));
|
||||||
|
FETCH_INST;
|
||||||
|
GOTO_NEXT_INST;
|
||||||
|
}
|
||||||
|
|
||||||
SHADD8_INST:
|
SHADD8_INST:
|
||||||
SHADD16_INST:
|
SHADD16_INST:
|
||||||
|
@ -5976,36 +6012,36 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
if (BIT(inst_cream->inst, 22) == 1) {
|
if (BIT(inst_cream->inst, 22) == 1) {
|
||||||
for (int i = 0; i < 13; i++) {
|
for (int i = 0; i < 13; i++) {
|
||||||
if (BIT(inst_cream->inst, i)) {
|
if (BIT(inst_cream->inst, i)) {
|
||||||
Memory::Write32(addr, cpu->Reg[i]);
|
WriteMemory32(cpu, addr, cpu->Reg[i]);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (BIT(inst_cream->inst, 13)) {
|
if (BIT(inst_cream->inst, 13)) {
|
||||||
if (cpu->Mode == USER32MODE)
|
if (cpu->Mode == USER32MODE)
|
||||||
Memory::Write32(addr, cpu->Reg[13]);
|
WriteMemory32(cpu, addr, cpu->Reg[13]);
|
||||||
else
|
else
|
||||||
Memory::Write32(addr, cpu->Reg_usr[0]);
|
WriteMemory32(cpu, addr, cpu->Reg_usr[0]);
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
if (BIT(inst_cream->inst, 14)) {
|
if (BIT(inst_cream->inst, 14)) {
|
||||||
if (cpu->Mode == USER32MODE)
|
if (cpu->Mode == USER32MODE)
|
||||||
Memory::Write32(addr, cpu->Reg[14]);
|
WriteMemory32(cpu, addr, cpu->Reg[14]);
|
||||||
else
|
else
|
||||||
Memory::Write32(addr, cpu->Reg_usr[1]);
|
WriteMemory32(cpu, addr, cpu->Reg_usr[1]);
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
if (BIT(inst_cream->inst, 15)) {
|
if (BIT(inst_cream->inst, 15)) {
|
||||||
Memory::Write32(addr, cpu->Reg_usr[1] + 8);
|
WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < 15; i++) {
|
for (int i = 0; i < 15; i++) {
|
||||||
if (BIT(inst_cream->inst, i)) {
|
if (BIT(inst_cream->inst, i)) {
|
||||||
if (i == Rn)
|
if (i == Rn)
|
||||||
Memory::Write32(addr, old_RN);
|
WriteMemory32(cpu, addr, old_RN);
|
||||||
else
|
else
|
||||||
Memory::Write32(addr, cpu->Reg[i]);
|
WriteMemory32(cpu, addr, cpu->Reg[i]);
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
|
@ -6013,7 +6049,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
|
|
||||||
// Check PC reg
|
// Check PC reg
|
||||||
if (BIT(inst_cream->inst, 15))
|
if (BIT(inst_cream->inst, 15))
|
||||||
Memory::Write32(addr, cpu->Reg_usr[1] + 8);
|
WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
|
@ -6046,7 +6082,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
||||||
|
|
||||||
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
|
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
|
||||||
Memory::Write32(addr, value);
|
WriteMemory32(cpu, addr, value);
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
|
@ -6109,10 +6145,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
||||||
|
|
||||||
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
|
// The 3DS doesn't have the Large Physical Access Extension (LPAE)
|
||||||
Memory::Write32(addr, value);
|
// so STRD wouldn't store these as a single write.
|
||||||
value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1];
|
WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
|
||||||
Memory::Write32(addr + 4, value);
|
WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
|
@ -6129,7 +6165,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
remove_exclusive(cpu, write_addr);
|
remove_exclusive(cpu, write_addr);
|
||||||
cpu->exclusive_state = 0;
|
cpu->exclusive_state = 0;
|
||||||
|
|
||||||
Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
|
WriteMemory32(cpu, write_addr, RM);
|
||||||
RD = 0;
|
RD = 0;
|
||||||
} else {
|
} else {
|
||||||
// Failed to write due to mutex access
|
// Failed to write due to mutex access
|
||||||
|
@ -6173,8 +6209,16 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
remove_exclusive(cpu, write_addr);
|
remove_exclusive(cpu, write_addr);
|
||||||
cpu->exclusive_state = 0;
|
cpu->exclusive_state = 0;
|
||||||
|
|
||||||
Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
|
const u32 rt = cpu->Reg[inst_cream->Rm + 0];
|
||||||
Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]);
|
const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
|
||||||
|
u64 value;
|
||||||
|
|
||||||
|
if (InBigEndianMode(cpu))
|
||||||
|
value = (((u64)rt << 32) | rt2);
|
||||||
|
else
|
||||||
|
value = (((u64)rt2 << 32) | rt);
|
||||||
|
|
||||||
|
WriteMemory64(cpu, write_addr, value);
|
||||||
RD = 0;
|
RD = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -6197,7 +6241,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
remove_exclusive(cpu, write_addr);
|
remove_exclusive(cpu, write_addr);
|
||||||
cpu->exclusive_state = 0;
|
cpu->exclusive_state = 0;
|
||||||
|
|
||||||
Memory::Write16(write_addr, cpu->Reg[inst_cream->Rm]);
|
WriteMemory16(cpu, write_addr, RM);
|
||||||
RD = 0;
|
RD = 0;
|
||||||
} else {
|
} else {
|
||||||
// Failed to write due to mutex access
|
// Failed to write due to mutex access
|
||||||
|
@ -6216,7 +6260,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
||||||
|
|
||||||
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
|
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
|
||||||
Memory::Write16(addr, value);
|
WriteMemory16(cpu, addr, value);
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
|
@ -6230,7 +6274,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
|
||||||
|
|
||||||
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
|
unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
|
||||||
Memory::Write32(addr, value);
|
WriteMemory32(cpu, addr, value);
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(ldst_inst));
|
INC_PC(sizeof(ldst_inst));
|
||||||
|
@ -6289,8 +6333,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
|
||||||
swp_inst* inst_cream = (swp_inst*)inst_base->component;
|
swp_inst* inst_cream = (swp_inst*)inst_base->component;
|
||||||
|
|
||||||
addr = RN;
|
addr = RN;
|
||||||
unsigned int value = Memory::Read32(addr);
|
unsigned int value = ReadMemory32(cpu, addr);
|
||||||
Memory::Write32(addr, RM);
|
WriteMemory32(cpu, addr, RM);
|
||||||
|
|
||||||
RD = value;
|
RD = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,3 +201,9 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
|
||||||
*saturation_occurred = false;
|
*saturation_occurred = false;
|
||||||
return (u32)value;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/arm/skyeye_common/armmmu.h"
|
|
||||||
#include "core/arm/skyeye_common/arm_regformat.h"
|
#include "core/arm/skyeye_common/arm_regformat.h"
|
||||||
#include "core/arm/skyeye_common/skyeye_defs.h"
|
#include "core/arm/skyeye_common/skyeye_defs.h"
|
||||||
|
|
||||||
|
@ -356,3 +355,5 @@ extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
|
||||||
extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
|
extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
|
||||||
extern u32 ARMul_SignedSatQ(s32, u8, bool*);
|
extern u32 ARMul_SignedSatQ(s32, u8, bool*);
|
||||||
extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
|
extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
|
||||||
|
|
||||||
|
extern bool InBigEndianMode(ARMul_State*);
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/mem_map.h"
|
||||||
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
|
|
||||||
// Register numbers in the MMU
|
// Register numbers in the MMU
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -54,3 +57,55 @@ enum
|
||||||
XSCALE_CP15_AUX_CONTROL = 1,
|
XSCALE_CP15_AUX_CONTROL = 1,
|
||||||
XSCALE_CP15_COPRO_ACCESS = 15,
|
XSCALE_CP15_COPRO_ACCESS = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
|
@ -1388,12 +1388,20 @@ VSTR_INST:
|
||||||
|
|
||||||
if (inst_cream->single)
|
if (inst_cream->single)
|
||||||
{
|
{
|
||||||
Memory::Write32(addr, cpu->ExtReg[inst_cream->d]);
|
WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write32(addr, cpu->ExtReg[inst_cream->d*2]);
|
const u32 word1 = cpu->ExtReg[inst_cream->d*2+0];
|
||||||
Memory::Write32(addr + 4, cpu->ExtReg[inst_cream->d*2+1]);
|
const u32 word2 = cpu->ExtReg[inst_cream->d*2+1];
|
||||||
|
|
||||||
|
if (InBigEndianMode(cpu)) {
|
||||||
|
WriteMemory32(cpu, addr + 0, word2);
|
||||||
|
WriteMemory32(cpu, addr + 4, word1);
|
||||||
|
} else {
|
||||||
|
WriteMemory32(cpu, addr + 0, word1);
|
||||||
|
WriteMemory32(cpu, addr + 4, word2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
|
@ -1447,17 +1455,27 @@ VPUSH_INST:
|
||||||
{
|
{
|
||||||
if (inst_cream->single)
|
if (inst_cream->single)
|
||||||
{
|
{
|
||||||
Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
|
WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]);
|
const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
|
||||||
Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]);
|
const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
|
||||||
|
|
||||||
|
if (InBigEndianMode(cpu)) {
|
||||||
|
WriteMemory32(cpu, addr + 0, word2);
|
||||||
|
WriteMemory32(cpu, addr + 4, word1);
|
||||||
|
} else {
|
||||||
|
WriteMemory32(cpu, addr + 0, word1);
|
||||||
|
WriteMemory32(cpu, addr + 4, word2);
|
||||||
|
}
|
||||||
|
|
||||||
addr += 8;
|
addr += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32;
|
|
||||||
|
cpu->Reg[R13] -= inst_cream->imm32;
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(vpush_inst));
|
INC_PC(sizeof(vpush_inst));
|
||||||
|
@ -1516,13 +1534,22 @@ VSTM_INST: /* encoding 1 */
|
||||||
{
|
{
|
||||||
if (inst_cream->single)
|
if (inst_cream->single)
|
||||||
{
|
{
|
||||||
Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
|
WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]);
|
const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
|
||||||
Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]);
|
const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
|
||||||
|
|
||||||
|
if (InBigEndianMode(cpu)) {
|
||||||
|
WriteMemory32(cpu, addr + 0, word2);
|
||||||
|
WriteMemory32(cpu, addr + 4, word1);
|
||||||
|
} else {
|
||||||
|
WriteMemory32(cpu, addr + 0, word1);
|
||||||
|
WriteMemory32(cpu, addr + 4, word2);
|
||||||
|
}
|
||||||
|
|
||||||
addr += 8;
|
addr += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1575,8 +1602,6 @@ VPOP_INST:
|
||||||
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
|
||||||
CHECK_VFP_ENABLED;
|
CHECK_VFP_ENABLED;
|
||||||
|
|
||||||
unsigned int value1, value2;
|
|
||||||
|
|
||||||
vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
|
vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
|
||||||
|
|
||||||
addr = cpu->Reg[R13];
|
addr = cpu->Reg[R13];
|
||||||
|
@ -1585,20 +1610,26 @@ VPOP_INST:
|
||||||
{
|
{
|
||||||
if (inst_cream->single)
|
if (inst_cream->single)
|
||||||
{
|
{
|
||||||
value1 = Memory::Read32(addr);
|
cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
|
||||||
cpu->ExtReg[inst_cream->d+i] = value1;
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value1 = Memory::Read32(addr);
|
const u32 word1 = ReadMemory32(cpu, addr + 0);
|
||||||
value2 = Memory::Read32(addr + 4);
|
const u32 word2 = ReadMemory32(cpu, addr + 4);
|
||||||
cpu->ExtReg[(inst_cream->d+i)*2] = value1;
|
|
||||||
cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2;
|
if (InBigEndianMode(cpu)) {
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
|
||||||
|
} else {
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
|
||||||
|
}
|
||||||
|
|
||||||
addr += 8;
|
addr += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32;
|
cpu->Reg[R13] += inst_cream->imm32;
|
||||||
}
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(vpop_inst));
|
INC_PC(sizeof(vpop_inst));
|
||||||
|
@ -1653,18 +1684,22 @@ VLDR_INST:
|
||||||
|
|
||||||
if (inst_cream->single)
|
if (inst_cream->single)
|
||||||
{
|
{
|
||||||
cpu->ExtReg[inst_cream->d] = Memory::Read32(addr);
|
cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int word1, word2;
|
const u32 word1 = ReadMemory32(cpu, addr + 0);
|
||||||
word1 = Memory::Read32(addr);
|
const u32 word2 = ReadMemory32(cpu, addr + 4);
|
||||||
word2 = Memory::Read32(addr + 4);
|
|
||||||
|
|
||||||
cpu->ExtReg[inst_cream->d*2] = word1;
|
if (InBigEndianMode(cpu)) {
|
||||||
|
cpu->ExtReg[inst_cream->d*2+0] = word2;
|
||||||
|
cpu->ExtReg[inst_cream->d*2+1] = word1;
|
||||||
|
} else {
|
||||||
|
cpu->ExtReg[inst_cream->d*2+0] = word1;
|
||||||
cpu->ExtReg[inst_cream->d*2+1] = word2;
|
cpu->ExtReg[inst_cream->d*2+1] = word2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
cpu->Reg[15] += GET_INST_SIZE(cpu);
|
||||||
INC_PC(sizeof(vldr_inst));
|
INC_PC(sizeof(vldr_inst));
|
||||||
FETCH_INST;
|
FETCH_INST;
|
||||||
|
@ -1722,13 +1757,22 @@ VLDM_INST:
|
||||||
{
|
{
|
||||||
if (inst_cream->single)
|
if (inst_cream->single)
|
||||||
{
|
{
|
||||||
cpu->ExtReg[inst_cream->d+i] = Memory::Read32(addr);
|
cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cpu->ExtReg[(inst_cream->d+i)*2] = Memory::Read32(addr);
|
const u32 word1 = ReadMemory32(cpu, addr + 0);
|
||||||
cpu->ExtReg[(inst_cream->d+i)*2 + 1] = Memory::Read32(addr + 4);
|
const u32 word2 = ReadMemory32(cpu, addr + 4);
|
||||||
|
|
||||||
|
if (InBigEndianMode(cpu)) {
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
|
||||||
|
} else {
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
|
||||||
|
cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
|
||||||
|
}
|
||||||
|
|
||||||
addr += 8;
|
addr += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,7 @@ inline void Write(VAddr addr, T data);
|
||||||
u8 Read8(VAddr addr);
|
u8 Read8(VAddr addr);
|
||||||
u16 Read16(VAddr addr);
|
u16 Read16(VAddr addr);
|
||||||
u32 Read32(VAddr addr);
|
u32 Read32(VAddr addr);
|
||||||
|
u64 Read64(VAddr addr);
|
||||||
|
|
||||||
u32 Read8_ZX(VAddr addr);
|
u32 Read8_ZX(VAddr addr);
|
||||||
u32 Read16_ZX(VAddr addr);
|
u32 Read16_ZX(VAddr addr);
|
||||||
|
|
|
@ -245,6 +245,12 @@ u32 Read32(const VAddr addr) {
|
||||||
return (u32)data;
|
return (u32)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 Read64(const VAddr addr) {
|
||||||
|
u64_le data = 0;
|
||||||
|
Read<u64_le>(data, addr);
|
||||||
|
return (u64)data;
|
||||||
|
}
|
||||||
|
|
||||||
u32 Read8_ZX(const VAddr addr) {
|
u32 Read8_ZX(const VAddr addr) {
|
||||||
return (u32)Read8(addr);
|
return (u32)Read8(addr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue