From 5a531d7ec28825f0a00520916a440d6bce2a846b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 19 Dec 2015 18:39:33 -0500 Subject: [PATCH 1/2] 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 --- .../arm/dyncom/arm_dyncom_interpreter.cpp | 40 +++++++++++++++---- 1 file 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) { 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)] = cpu->ReadMemory8(addr); + const u32 dest_index = BITS(inst_cream->inst, 12, 15); + const u32 previous_mode = cpu->Mode; - if (BITS(inst_cream->inst, 12, 15) == 15) { + cpu->ChangePrivilegeMode(USER32MODE); + const u8 value = cpu->ReadMemory8(addr); + cpu->ChangePrivilegeMode(previous_mode); + + cpu->Reg[dest_index] = value; + + if (dest_index == 15) { INC_PC(sizeof(ldst_inst)); goto DISPATCH; } @@ -4668,10 +4675,16 @@ 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->ReadMemory32(addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + const u32 dest_index = BITS(inst_cream->inst, 12, 15); + const u32 previous_mode = cpu->Mode; - if (BITS(inst_cream->inst, 12, 15) == 15) { + cpu->ChangePrivilegeMode(USER32MODE); + const u32 value = cpu->ReadMemory32(addr); + cpu->ChangePrivilegeMode(previous_mode); + + cpu->Reg[dest_index] = value; + + if (dest_index == 15) { INC_PC(sizeof(ldst_inst)); goto DISPATCH; } @@ -6061,8 +6074,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 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)] & 0xff; + + const u32 previous_mode = cpu->Mode; + const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; + + cpu->ChangePrivilegeMode(USER32MODE); cpu->WriteMemory8(addr, value); + cpu->ChangePrivilegeMode(previous_mode); } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -6196,8 +6214,16 @@ 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)]; + const u32 previous_mode = cpu->Mode; + const u32 rt_index = BITS(inst_cream->inst, 12, 15); + + u32 value = cpu->Reg[rt_index]; + if (rt_index == 15) + value += 2 * cpu->GetInstructionSize(); + + cpu->ChangePrivilegeMode(USER32MODE); cpu->WriteMemory32(addr, value); + cpu->ChangePrivilegeMode(previous_mode); } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); From d09b7a3c127fdd97d73d0c10820c88c906bb59d1 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 19 Dec 2015 18:51:02 -0500 Subject: [PATCH 2/2] dyncom: Remove PC dispatch from several instructions These instructions aren't capable of using the PC as a destination --- .../arm/dyncom/arm_dyncom_interpreter.cpp | 94 ------------------- 1 file changed, 94 deletions(-) diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 187aee702..459877eae 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -1623,9 +1623,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) @@ -1646,9 +1643,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) DEBUG_MSG; } - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) @@ -1703,9 +1697,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) @@ -1720,9 +1711,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) @@ -1737,9 +1725,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) @@ -2597,9 +2582,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) @@ -2645,9 +2627,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) @@ -2669,9 +2648,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) DEBUG_MSG; } - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ @@ -2685,9 +2661,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) @@ -2729,9 +2702,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) inst_cream->inst = inst; inst_cream->get_addr = get_calc_addr_op(inst); - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) @@ -2757,9 +2727,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) DEBUG_MSG; } - if (BITS(inst, 12, 15) == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) @@ -2808,9 +2775,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) inst_cream->Rd = BITS(inst, 12, 15); inst_cream->Rm = BITS(inst, 0, 3); - if (inst_cream->Rd == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ @@ -2825,9 +2789,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ inst_cream->Rd = BITS(inst, 12, 15); inst_cream->Rm = BITS(inst, 0, 3); - if (inst_cream->Rd == 15) { - inst_base->br = INDIRECT_BRANCH; - } return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ @@ -2915,9 +2876,6 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) inst_cream->shifter_operand = BITS(inst, 0, 11); inst_cream->shtop_func = get_shtop(inst); - if (inst_cream->Rd == 15) - inst_base->br = INDIRECT_BRANCH; - return inst_base; } @@ -4477,11 +4435,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->get_addr(cpu, inst_cream->inst, addr); cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); - - if (BITS(inst_cream->inst, 12, 15) == 15) { - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -4502,11 +4455,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->ChangePrivilegeMode(previous_mode); cpu->Reg[dest_index] = value; - - if (dest_index == 15) { - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -4542,10 +4490,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->SetExclusiveMemoryAddress(read_addr); RD = cpu->ReadMemory32(read_addr); - if (inst_cream->Rd == 15) { - INC_PC(sizeof(generic_arm_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); @@ -4561,10 +4505,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->SetExclusiveMemoryAddress(read_addr); RD = cpu->ReadMemory8(read_addr); - if (inst_cream->Rd == 15) { - INC_PC(sizeof(generic_arm_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); @@ -4580,10 +4520,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->SetExclusiveMemoryAddress(read_addr); RD = cpu->ReadMemory16(read_addr); - if (inst_cream->Rd == 15) { - INC_PC(sizeof(generic_arm_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); @@ -4600,11 +4536,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { 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] += cpu->GetInstructionSize(); INC_PC(sizeof(generic_arm_inst)); @@ -4618,10 +4549,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { inst_cream->get_addr(cpu, inst_cream->inst, 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] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -4638,10 +4565,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { value |= 0xffffff00; } cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; - if (BITS(inst_cream->inst, 12, 15) == 15) { - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -4659,10 +4582,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { value |= 0xffff0000; } cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; - if (BITS(inst_cream->inst, 12, 15) == 15) { - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -4683,11 +4602,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { cpu->ChangePrivilegeMode(previous_mode); cpu->Reg[dest_index] = value; - - if (dest_index == 15) { - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(ldst_inst)); @@ -4744,10 +4658,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { UPDATE_NFLAG(RD); UPDATE_ZFLAG(RD); } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(mla_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mla_inst)); @@ -4896,10 +4806,6 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { UPDATE_NFLAG(RD); UPDATE_ZFLAG(RD); } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(mul_inst)); - goto DISPATCH; - } } cpu->Reg[15] += cpu->GetInstructionSize(); INC_PC(sizeof(mul_inst));