summaryrefslogtreecommitdiffstats
path: root/target-arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-02-23 15:36:43 +0000
committerTimothy Pearson <tpearson@raptorengineering.com>2019-11-29 19:46:49 -0600
commit4dfd98c89467acffa170410eb5acfb1dff861655 (patch)
tree386ef12c8c433b090ae9ffe4fabeefcbd2fe884c /target-arm
parent6b70280a03f69e4ab55c951e3c9ce1bd3d68588c (diff)
downloadhqemu-4dfd98c89467acffa170410eb5acfb1dff861655.zip
hqemu-4dfd98c89467acffa170410eb5acfb1dff861655.tar.gz
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
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/helper.h1
-rw-r--r--target-arm/op_helper.c6
-rw-r--r--target-arm/translate.c6
3 files changed, 10 insertions, 3 deletions
diff --git a/target-arm/helper.h b/target-arm/helper.h
index d009586..37428f8 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -58,6 +58,7 @@ DEF_HELPER_1(check_breakpoints, void, env)
DEF_HELPER_3(cpsr_write_nzcv, 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_3(v7m_msr, void, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 4605b87..291b718 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -425,6 +425,12 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t 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);
+}
+
void HELPER(cpsr_write_nzcv)(CPUARMState *env, uint32_t val, uint32_t mask)
{
if (mask & CPSR_NZCV) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0a8d9a3..164602c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4175,7 +4175,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
TCGv_i32 tmp;
store_reg(s, 15, pc);
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);
s->is_jmp = DISAS_JUMP;
}
@@ -4183,7 +4183,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
/* Generate a v6 exception return. Marks both values as dead. */
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);
store_reg(s, 15, pc);
s->is_jmp = DISAS_JUMP;
@@ -9365,7 +9365,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if (exc_return) {
/* Restore CPSR from 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);
s->is_jmp = DISAS_JUMP;
}
OpenPOWER on IntegriCloud