diff mbox series

[v2,30/68] target/arm: Diagnose base == pc for LDM/STM

Message ID 20190819213755.26175-31-richard.henderson@linaro.org
State New
Headers show
Series target/arm: Convert aa32 base isa to decodetree | expand

Commit Message

Richard Henderson Aug. 19, 2019, 9:37 p.m. UTC
We have been using store_reg and not store_reg_for_load when writing
back a loaded value into the base register.  At first glance this is
incorrect when base == pc, however that case is UNPREDICTABLE.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 target/arm/translate.c | 9 +++++++++
 1 file changed, 9 insertions(+)

-- 
2.17.1

Comments

Peter Maydell Aug. 23, 2019, 5:31 p.m. UTC | #1
On Mon, 19 Aug 2019 at 22:38, Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> We have been using store_reg and not store_reg_for_load when writing

> back a loaded value into the base register.  At first glance this is

> incorrect when base == pc, however that case is UNPREDICTABLE.

>

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> ---


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>


thanks
-- PMM
diff mbox series

Patch

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 1792bb7abd..09636aab4e 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9752,6 +9752,10 @@  static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
     if (n < min_n) {
         return false;
     }
+    /* Using PC as the base register is UNPREDICTABLE.  */
+    if (a->rn == 15) {
+        return false;
+    }
 
     addr = op_addr_block_pre(s, a, n);
     mem_idx = get_mem_index(s);
@@ -9828,6 +9832,10 @@  static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
     if (n < min_n) {
         return false;
     }
+    /* Using PC as the base register is UNPREDICTABLE.  */
+    if (a->rn == 15) {
+        return false;
+    }
 
     addr = op_addr_block_pre(s, a, n);
     mem_idx = get_mem_index(s);
@@ -9864,6 +9872,7 @@  static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
     op_addr_block_post(s, a, addr, n);
 
     if (loaded_base) {
+        /* Note that we reject base == pc above.  */
         store_reg(s, a->rn, loaded_var);
     }