diff options
author | Richard Henderson | 2019-09-04 21:30:21 +0200 |
---|---|---|
committer | Peter Maydell | 2019-09-05 14:23:03 +0200 |
commit | b0e382b8cf365fed8b8c43482029ac7655961a85 (patch) | |
tree | b8b93d51c5e742beee0fdd1b3385a3a3652c133e | |
parent | target/arm: Diagnose too few registers in list for LDM/STM (diff) | |
download | qemu-b0e382b8cf365fed8b8c43482029ac7655961a85.tar.gz qemu-b0e382b8cf365fed8b8c43482029ac7655961a85.tar.xz qemu-b0e382b8cf365fed8b8c43482029ac7655961a85.zip |
target/arm: Diagnose base == pc for LDM/STM
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.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-32-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | target/arm/translate.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index b623dbcd48..d0fc916ff9 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9863,7 +9863,7 @@ static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n) list = a->list; n = ctpop16(list); - if (n < min_n) { + if (n < min_n || a->rn == 15) { unallocated_encoding(s); return true; } @@ -9943,7 +9943,7 @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n) list = a->list; n = ctpop16(list); - if (n < min_n) { + if (n < min_n || a->rn == 15) { unallocated_encoding(s); return true; } @@ -9983,6 +9983,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); } |