diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-10-08 14:55:04 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-10-08 14:55:04 +0100 |
commit | 0bc003bad9752afc61624cb680226c922f34f82c (patch) | |
tree | 8c68df2869e87b08089c34e9768758c81542fcd2 /target/arm/translate.c | |
parent | 7c0ed88e7d6bee3e55c3d8935c46226cb544191a (diff) | |
download | qemu-0bc003bad9752afc61624cb680226c922f34f82c.zip qemu-0bc003bad9752afc61624cb680226c922f34f82c.tar.gz qemu-0bc003bad9752afc61624cb680226c922f34f82c.tar.bz2 |
target/arm: Add v8M stack checks for T32 load/store single
Add v8M stack checks for the instructions in the T32
"load/store single" encoding class: these are the
"immediate pre-indexed" and "immediate, post-indexed"
LDR and STR instructions.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20181002163556.10279-11-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index 3fb378a..65df8d6 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -11624,7 +11624,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) imm = -imm; /* Fall through. */ case 0xf: /* Pre-increment. */ - tcg_gen_addi_i32(addr, addr, imm); writeback = 1; break; default: @@ -11636,6 +11635,28 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) issinfo = writeback ? ISSInvalid : rs; + if (s->v8m_stackcheck && rn == 13 && writeback) { + /* + * Stackcheck. Here we know 'addr' is the current SP; + * if imm is +ve we're moving SP up, else down. It is + * UNKNOWN whether the limit check triggers when SP starts + * below the limit and ends up above it; we chose to do so. + */ + if ((int32_t)imm < 0) { + TCGv_i32 newsp = tcg_temp_new_i32(); + + tcg_gen_addi_i32(newsp, addr, imm); + gen_helper_v8m_stackcheck(cpu_env, newsp); + tcg_temp_free_i32(newsp); + } else { + gen_helper_v8m_stackcheck(cpu_env, addr); + } + } + + if (writeback && !postinc) { + tcg_gen_addi_i32(addr, addr, imm); + } + if (insn & (1 << 20)) { /* Load. */ tmp = tcg_temp_new_i32(); |