target-arm: UNDEF in the UNPREDICTABLE SRS-from-System case

Make get_r13_banked() raise an exception at runtime for the
corner case of SRS from System mode, so that we can UNDEF it;
this brings us in to line with the ARM ARM's set of permitted
CONSTRAINED UNPREDICTABLE choices.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Sergey Fedorov <serge.fdrv@gmail.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
This commit is contained in:
Peter Maydell 2016-02-18 14:16:17 +00:00
parent d86d57d4fe
commit f01377f591
2 changed files with 13 additions and 4 deletions

View file

@ -468,6 +468,14 @@ void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val)
uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
{
if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_SYS) {
/* SRS instruction is UNPREDICTABLE from System mode; we UNDEF.
* Other UNPREDICTABLE and UNDEF cases were caught at translate time.
*/
raise_exception(env, EXCP_UDEF, syn_uncategorized(),
exception_target_el(env));
}
if ((env->uncached_cpsr & CPSR_M) == mode) {
return env->regs[13];
} else {

View file

@ -7590,10 +7590,7 @@ static void gen_srs(DisasContext *s,
* -- not a valid mode number
* -- a mode that's at a higher exception level
* -- Monitor, if we are Non-secure
* For the UNPREDICTABLE cases we choose to UNDEF, except that for
* "current mode is System" we will write a garbage SPSR.
* (This is because we don't have access to our current mode here
* and would have to do a runtime check to UNDEF for System.)
* For the UNPREDICTABLE cases we choose to UNDEF.
*/
if (s->current_el == 1 && !s->ns) {
gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
@ -7639,6 +7636,9 @@ static void gen_srs(DisasContext *s,
addr = tcg_temp_new_i32();
tmp = tcg_const_i32(mode);
/* get_r13_banked() will raise an exception if called from System mode */
gen_set_condexec(s);
gen_set_pc_im(s, s->pc - 4);
gen_helper_get_r13_banked(addr, cpu_env, tmp);
tcg_temp_free_i32(tmp);
switch (amode) {
@ -7688,6 +7688,7 @@ static void gen_srs(DisasContext *s,
tcg_temp_free_i32(tmp);
}
tcg_temp_free_i32(addr);
s->is_jmp = DISAS_UPDATE;
}
static void disas_arm_insn(DisasContext *s, unsigned int insn)