summaryrefslogtreecommitdiff
path: root/target-arm/op_helper.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-08-19 18:56:26 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-08-19 19:02:03 +0100
commit3a2982038afa0f04fc99b259e8ad8c18be0b04cb (patch)
treed9aa82c4dc7c24d6627b6c3ee8faab582b130728 /target-arm/op_helper.c
parent662cefb7753c1f04d960b443c60e7622c83144d3 (diff)
downloadqemu-3a2982038afa0f04fc99b259e8ad8c18be0b04cb.tar.gz
target-arm: Set PSTATE.SS correctly on exception return from AArch64
Set the PSTATE.SS bit correctly on exception returns from AArch64, as required by the debug single-step functionality. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r--target-arm/op_helper.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 180a4a096b..62cc07d448 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -380,12 +380,26 @@ void HELPER(exception_return)(CPUARMState *env)
env->exclusive_addr = -1;
+ /* We must squash the PSTATE.SS bit to zero unless both of the
+ * following hold:
+ * 1. debug exceptions are currently disabled
+ * 2. singlestep will be active in the EL we return to
+ * We check 1 here and 2 after we've done the pstate/cpsr write() to
+ * transition to the EL we're going to.
+ */
+ if (arm_generate_debug_exceptions(env)) {
+ spsr &= ~PSTATE_SS;
+ }
+
if (spsr & PSTATE_nRW) {
/* TODO: We currently assume EL1/2/3 are running in AArch64. */
env->aarch64 = 0;
new_el = 0;
env->uncached_cpsr = 0x10;
cpsr_write(env, spsr, ~0);
+ if (!arm_singlestep_active(env)) {
+ env->uncached_cpsr &= ~PSTATE_SS;
+ }
for (i = 0; i < 15; i++) {
env->regs[i] = env->xregs[i];
}
@@ -410,6 +424,9 @@ void HELPER(exception_return)(CPUARMState *env)
}
env->aarch64 = 1;
pstate_write(env, spsr);
+ if (!arm_singlestep_active(env)) {
+ env->pstate &= ~PSTATE_SS;
+ }
aarch64_restore_sp(env, new_el);
env->pc = env->elr_el[cur_el];
}
@@ -429,6 +446,9 @@ illegal_return:
spsr &= PSTATE_NZCV | PSTATE_DAIF;
spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
pstate_write(env, spsr);
+ if (!arm_singlestep_active(env)) {
+ env->pstate &= ~PSTATE_SS;
+ }
}
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.