aboutsummaryrefslogtreecommitdiff
path: root/target/arm/translate.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-10-08 14:55:04 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-10-08 14:55:04 +0100
commit0bc003bad9752afc61624cb680226c922f34f82c (patch)
tree8c68df2869e87b08089c34e9768758c81542fcd2 /target/arm/translate.c
parent7c0ed88e7d6bee3e55c3d8935c46226cb544191a (diff)
downloadqemu-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.c23
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();