On 15.02.2016 20:22, Peter Maydell wrote: > In v8, the illegal mode changes which are UNPREDICTABLE in v7 are > given architected behaviour: > * the mode field is unchanged > * PSTATE.IL is set (so any subsequent instructions will UNDEF) > * any other CPSR fields are written to as normal > > This is pretty much the same behaviour we picked for our > UNPREDICTABLE handling, with the exception that for v8 we > need to set the IL bit. > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Sergey Fedorov <serge.f...@gmail.com> > --- > target-arm/helper.c | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > > diff --git a/target-arm/helper.c b/target-arm/helper.c > index e7b3eb3..69e93a2 100644 > --- a/target-arm/helper.c > +++ b/target-arm/helper.c > @@ -5291,11 +5291,20 @@ void cpsr_write(CPUARMState *env, uint32_t val, > uint32_t mask, > (env->uncached_cpsr & CPSR_M) != CPSR_USER && > ((env->uncached_cpsr ^ val) & mask & CPSR_M)) { > if (bad_mode_switch(env, val & CPSR_M)) { > - /* Attempt to switch to an invalid mode: this is UNPREDICTABLE. > - * We choose to ignore the attempt and leave the CPSR M field > - * untouched. > + /* Attempt to switch to an invalid mode: this is UNPREDICTABLE in > + * v7, and has defined behaviour in v8: > + * + leave CPSR.M untouched > + * + allow changes to the other CPSR fields > + * + set PSTATE.IL > + * For user changes via the GDB stub, we don't set PSTATE.IL, > + * as this would be unnecessarily harsh for a user error. > */ > mask &= ~CPSR_M; > + if (write_type != CPSRWriteByGDBStub && > + arm_feature(env, ARM_FEATURE_V8)) { > + mask |= CPSR_IL; > + val |= CPSR_IL; > + } > } else { > switch_mode(env, val & CPSR_M); > }