summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2015-12-19 18:39:33 -0500
committerGravatar Lioncash2015-12-19 19:05:50 -0500
commit5a531d7ec28825f0a00520916a440d6bce2a846b (patch)
treee22f4b822d3e752bd02e895fe260e29b6fd3ac30
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
-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));