diff options
| author | 2015-12-19 18:39:33 -0500 | |
|---|---|---|
| committer | 2015-12-19 19:05:50 -0500 | |
| commit | 5a531d7ec28825f0a00520916a440d6bce2a846b (patch) | |
| tree | e22f4b822d3e752bd02e895fe260e29b6fd3ac30 | |
| parent | Merge pull request #1281 from lioncash/compile (diff) | |
| download | yuzu-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.cpp | 40 |
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)); |