summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Lioncash2015-12-19 18:39:33 -0500
committerGravatar Lioncash2015-12-19 19:05:50 -0500
commit5a531d7ec28825f0a00520916a440d6bce2a846b (patch)
treee22f4b822d3e752bd02e895fe260e29b6fd3ac30 /src/core
parentMerge pull request #1281 from lioncash/compile (diff)
downloadyuzu-5a531d7ec28825f0a00520916a440d6bce2a846b.tar.gz
yuzu-5a531d7ec28825f0a00520916a440d6bce2a846b.tar.xz
yuzu-5a531d7ec28825f0a00520916a440d6bce2a846b.zip
dyncom: Handle unprivileged load/store variants correctly
LDRT/LDRBT/STRBT/STRT should simulate the load or store as if the host CPU is in user mode. STRT is also allowed to use the PC as an operand
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 2cff2a26a..187aee702 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -4494,9 +4494,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4494 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4494 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4495 inst_cream->get_addr(cpu, inst_cream->inst, addr); 4495 inst_cream->get_addr(cpu, inst_cream->inst, addr);
4496 4496
4497 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); 4497 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
4498 const u32 previous_mode = cpu->Mode;
4498 4499
4499 if (BITS(inst_cream->inst, 12, 15) == 15) { 4500 cpu->ChangePrivilegeMode(USER32MODE);
4501 const u8 value = cpu->ReadMemory8(addr);
4502 cpu->ChangePrivilegeMode(previous_mode);
4503
4504 cpu->Reg[dest_index] = value;
4505
4506 if (dest_index == 15) {
4500 INC_PC(sizeof(ldst_inst)); 4507 INC_PC(sizeof(ldst_inst));
4501 goto DISPATCH; 4508 goto DISPATCH;
4502 } 4509 }
@@ -4668,10 +4675,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4668 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4675 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4669 inst_cream->get_addr(cpu, inst_cream->inst, addr); 4676 inst_cream->get_addr(cpu, inst_cream->inst, addr);
4670 4677
4671 unsigned int value = cpu->ReadMemory32(addr); 4678 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
4672 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4679 const u32 previous_mode = cpu->Mode;
4673 4680
4674 if (BITS(inst_cream->inst, 12, 15) == 15) { 4681 cpu->ChangePrivilegeMode(USER32MODE);
4682 const u32 value = cpu->ReadMemory32(addr);
4683 cpu->ChangePrivilegeMode(previous_mode);
4684
4685 cpu->Reg[dest_index] = value;
4686
4687 if (dest_index == 15) {
4675 INC_PC(sizeof(ldst_inst)); 4688 INC_PC(sizeof(ldst_inst));
4676 goto DISPATCH; 4689 goto DISPATCH;
4677 } 4690 }
@@ -6061,8 +6074,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6061 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 6074 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
6062 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 6075 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
6063 inst_cream->get_addr(cpu, inst_cream->inst, addr); 6076 inst_cream->get_addr(cpu, inst_cream->inst, addr);
6064 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; 6077
6078 const u32 previous_mode = cpu->Mode;
6079 const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
6080
6081 cpu->ChangePrivilegeMode(USER32MODE);
6065 cpu->WriteMemory8(addr, value); 6082 cpu->WriteMemory8(addr, value);
6083 cpu->ChangePrivilegeMode(previous_mode);
6066 } 6084 }
6067 cpu->Reg[15] += cpu->GetInstructionSize(); 6085 cpu->Reg[15] += cpu->GetInstructionSize();
6068 INC_PC(sizeof(ldst_inst)); 6086 INC_PC(sizeof(ldst_inst));
@@ -6196,8 +6214,16 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6196 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 6214 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
6197 inst_cream->get_addr(cpu, inst_cream->inst, addr); 6215 inst_cream->get_addr(cpu, inst_cream->inst, addr);
6198 6216
6199 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6217 const u32 previous_mode = cpu->Mode;
6218 const u32 rt_index = BITS(inst_cream->inst, 12, 15);
6219
6220 u32 value = cpu->Reg[rt_index];
6221 if (rt_index == 15)
6222 value += 2 * cpu->GetInstructionSize();
6223
6224 cpu->ChangePrivilegeMode(USER32MODE);
6200 cpu->WriteMemory32(addr, value); 6225 cpu->WriteMemory32(addr, value);
6226 cpu->ChangePrivilegeMode(previous_mode);
6201 } 6227 }
6202 cpu->Reg[15] += cpu->GetInstructionSize(); 6228 cpu->Reg[15] += cpu->GetInstructionSize();
6203 INC_PC(sizeof(ldst_inst)); 6229 INC_PC(sizeof(ldst_inst));