diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2019-09-04 12:30:20 -0700 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-09-05 13:23:03 +0100 |
commit | 4b222545dbf30b60c033e1cd6eddda612575fd8c (patch) | |
tree | 95e55ba08e8a0b1e63f243518aecc4d3232ce040 /target/arm/translate.c | |
parent | 3949f4675d13c587078f8f423845a3a537a22595 (diff) |
target/arm: Diagnose too few registers in list for LDM/STM
This has been a TODO item for quite a while. The minimum bit
count for A32 and T16 is 1, and for T32 is 2.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-31-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index b67e7389d3..b623dbcd48 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9846,7 +9846,7 @@ static void op_addr_block_post(DisasContext *s, arg_ldst_block *a, } } -static bool op_stm(DisasContext *s, arg_ldst_block *a) +static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n) { int i, j, n, list, mem_idx; bool user = a->u; @@ -9863,7 +9863,10 @@ static bool op_stm(DisasContext *s, arg_ldst_block *a) list = a->list; n = ctpop16(list); - /* TODO: test invalid n == 0 case */ + if (n < min_n) { + unallocated_encoding(s); + return true; + } addr = op_addr_block_pre(s, a, n); mem_idx = get_mem_index(s); @@ -9896,7 +9899,8 @@ static bool op_stm(DisasContext *s, arg_ldst_block *a) static bool trans_STM(DisasContext *s, arg_ldst_block *a) { - return op_stm(s, a); + /* BitCount(list) < 1 is UNPREDICTABLE */ + return op_stm(s, a, 1); } static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a) @@ -9906,10 +9910,11 @@ static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a) unallocated_encoding(s); return true; } - return op_stm(s, a); + /* BitCount(list) < 2 is UNPREDICTABLE */ + return op_stm(s, a, 2); } -static bool do_ldm(DisasContext *s, arg_ldst_block *a) +static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n) { int i, j, n, list, mem_idx; bool loaded_base; @@ -9938,7 +9943,10 @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a) list = a->list; n = ctpop16(list); - /* TODO: test invalid n == 0 case */ + if (n < min_n) { + unallocated_encoding(s); + return true; + } addr = op_addr_block_pre(s, a, n); mem_idx = get_mem_index(s); @@ -10006,7 +10014,8 @@ static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a) unallocated_encoding(s); return true; } - return do_ldm(s, a); + /* BitCount(list) < 1 is UNPREDICTABLE */ + return do_ldm(s, a, 1); } static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a) @@ -10016,7 +10025,8 @@ static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a) unallocated_encoding(s); return true; } - return do_ldm(s, a); + /* BitCount(list) < 2 is UNPREDICTABLE */ + return do_ldm(s, a, 2); } /* |