target-arm: Give CPSR setting on 32-bit exception return its own helper

The rules for setting the CPSR on a 32-bit exception return are
subtly different from those for setting the CPSR via an instruction
like MSR or CPS. (In particular, in Hyp mode changing the mode bits
is not valid via MSR or CPS.) Split the exception-return case into
its own helper for setting CPSR, so we can eventually handle them
differently in the helper function.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Sergey Fedorov <serge.fdrv@gmail.com>
Message-id: 1455556977-3644-2-git-send-email-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2016-02-23 15:36:43 +00:00
parent 4d1e324b22
commit 235ea1f5c8
3 changed files with 10 additions and 3 deletions

View File

@ -57,6 +57,7 @@ DEF_HELPER_2(pre_smc, void, env, i32)
DEF_HELPER_1(check_breakpoints, void, env) DEF_HELPER_1(check_breakpoints, void, env)
DEF_HELPER_3(cpsr_write, void, env, i32, i32) DEF_HELPER_3(cpsr_write, void, env, i32, i32)
DEF_HELPER_2(cpsr_write_eret, void, env, i32)
DEF_HELPER_1(cpsr_read, i32, env) DEF_HELPER_1(cpsr_read, i32, env)
DEF_HELPER_3(v7m_msr, void, env, i32, i32) DEF_HELPER_3(v7m_msr, void, env, i32, i32)

View File

@ -425,6 +425,12 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
cpsr_write(env, val, mask); cpsr_write(env, val, mask);
} }
/* Write the CPSR for a 32-bit exception return */
void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
{
cpsr_write(env, val, CPSR_ERET_MASK);
}
/* Access to user mode registers from privileged modes. */ /* Access to user mode registers from privileged modes. */
uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno)
{ {

View File

@ -4094,7 +4094,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
TCGv_i32 tmp; TCGv_i32 tmp;
store_reg(s, 15, pc); store_reg(s, 15, pc);
tmp = load_cpu_field(spsr); tmp = load_cpu_field(spsr);
gen_set_cpsr(tmp, CPSR_ERET_MASK); gen_helper_cpsr_write_eret(cpu_env, tmp);
tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp);
s->is_jmp = DISAS_JUMP; s->is_jmp = DISAS_JUMP;
} }
@ -4102,7 +4102,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
/* Generate a v6 exception return. Marks both values as dead. */ /* Generate a v6 exception return. Marks both values as dead. */
static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr) static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
{ {
gen_set_cpsr(cpsr, CPSR_ERET_MASK); gen_helper_cpsr_write_eret(cpu_env, cpsr);
tcg_temp_free_i32(cpsr); tcg_temp_free_i32(cpsr);
store_reg(s, 15, pc); store_reg(s, 15, pc);
s->is_jmp = DISAS_JUMP; s->is_jmp = DISAS_JUMP;
@ -9094,7 +9094,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if (exc_return) { if (exc_return) {
/* Restore CPSR from SPSR. */ /* Restore CPSR from SPSR. */
tmp = load_cpu_field(spsr); tmp = load_cpu_field(spsr);
gen_set_cpsr(tmp, CPSR_ERET_MASK); gen_helper_cpsr_write_eret(cpu_env, tmp);
tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp);
s->is_jmp = DISAS_JUMP; s->is_jmp = DISAS_JUMP;
} }