aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2019-09-04 12:30:21 -0700
committerPeter Maydell <peter.maydell@linaro.org>2019-09-05 13:23:03 +0100
commitb0e382b8cf365fed8b8c43482029ac7655961a85 (patch)
treeb8b93d51c5e742beee0fdd1b3385a3a3652c133e /target
parent4b222545dbf30b60c033e1cd6eddda612575fd8c (diff)
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>
Diffstat (limited to 'target')
-rw-r--r--target/arm/translate.c5
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);
}