From 1a0986ee25e4fc085913b68237e076cb7a98efef Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 20 Nov 2019 11:24:48 -0500 Subject: [PATCH] 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. Backports commit 4b222545dbf30b60c033e1cd6eddda612575fd8c from qemu --- qemu/target/arm/translate.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 8351db58..0ea5aa50 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -10178,7 +10178,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) { TCGContext *tcg_ctx = s->uc->tcg_ctx; int i, j, n, list, mem_idx; @@ -10196,7 +10196,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); @@ -10229,7 +10232,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) @@ -10239,10 +10243,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) { TCGContext *tcg_ctx = s->uc->tcg_ctx; int i, j, n, list, mem_idx; @@ -10272,7 +10277,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); @@ -10340,7 +10348,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) @@ -10350,7 +10359,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); } /*