From c52cfb9aa62920136aa0725f28f526a029f47b91 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 20 Nov 2019 12:12:41 -0500 Subject: [PATCH] target/arm: Convert T16 load/store multiple Backports commit 6e8514ba408f3cc758cd47e2da5475d8684507ec from qemu --- qemu/target/arm/t16.decode | 8 +++++++ qemu/target/arm/translate.c | 48 +++++++------------------------------ 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/qemu/target/arm/t16.decode b/qemu/target/arm/t16.decode index 71b3e8f0..a7a437f9 100644 --- a/qemu/target/arm/t16.decode +++ b/qemu/target/arm/t16.decode @@ -26,6 +26,7 @@ &ri !extern rd imm &ldst_rr !extern p w u rn rt rm shimm shtype &ldst_ri !extern p w u rn rt imm +&ldst_block !extern rn i b u w list # Set S if the instruction is outside of an IT block. %s !function=t16_setflags @@ -109,3 +110,10 @@ LDR_ri 10011 ... ........ @ldst_spec_i rn=13 ADR 10100 rd:3 ........ imm=%imm8_0x4 ADD_rri 10101 rd:3 ........ \ &s_rri_rot rn=13 s=0 rot=0 imm=%imm8_0x4 # SP + +# Load/store multiple + +@ldstm ..... rn:3 list:8 &ldst_block i=1 b=0 u=0 w=1 + +STM 11000 ... ........ @ldstm +LDM_t16 11001 ... ........ @ldstm diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 23b51c52..dacf6479 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -10426,6 +10426,14 @@ static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a) return do_ldm(s, a, 2); } +static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a) +{ + /* Writeback is conditional on the base register not being loaded. */ + a->w = !(a->list & (1 << a->rn)); + /* BitCount(list) < 1 is UNPREDICTABLE */ + return do_ldm(s, a, 1); +} + /* * Branch, branch with link */ @@ -11221,6 +11229,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn) case 8: /* load/store halfword immediate offset, in decodetree */ case 9: /* load/store from stack, in decodetree */ case 10: /* add PC/SP (immediate), in decodetree */ + case 12: /* load/store multiple, in decodetree */ goto illegal_op; case 11: @@ -11444,45 +11453,6 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn) } break; - case 12: - { - /* load/store multiple */ - TCGv_i32 loaded_var = NULL; - rn = (insn >> 8) & 0x7; - addr = load_reg(s, rn); - for (i = 0; i < 8; i++) { - if (insn & (1 << i)) { - if (insn & (1 << 11)) { - /* load */ - tmp = tcg_temp_new_i32(tcg_ctx); - gen_aa32_ld32u(s, tmp, addr, get_mem_index(s)); - if (i == rn) { - loaded_var = tmp; - } else { - store_reg(s, i, tmp); - } - } else { - /* store */ - tmp = load_reg(s, i); - gen_aa32_st32(s, tmp, addr, get_mem_index(s)); - tcg_temp_free_i32(tcg_ctx, tmp); - } - /* advance to the next address */ - tcg_gen_addi_i32(tcg_ctx, addr, addr, 4); - } - } - if ((insn & (1 << rn)) == 0) { - /* base reg not in list: base register writeback */ - store_reg(s, rn, addr); - } else { - /* base reg in list: if load, complete it now */ - if (insn & (1 << 11)) { - store_reg(s, rn, loaded_var); - } - tcg_temp_free_i32(tcg_ctx, addr); - } - break; - } case 13: /* conditional branch or swi */ cond = (insn >> 8) & 0xf;