From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42257) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YXUJo-0001LC-Q1 for qemu-devel@nongnu.org; Mon, 16 Mar 2015 08:40:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YXUJn-0005bI-5S for qemu-devel@nongnu.org; Mon, 16 Mar 2015 08:40:28 -0400 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:55251) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YXUJm-0005PR-Uz for qemu-devel@nongnu.org; Mon, 16 Mar 2015 08:40:27 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1YXUJf-00078z-3y for qemu-devel@nongnu.org; Mon, 16 Mar 2015 12:40:19 +0000 From: Peter Maydell Date: Mon, 16 Mar 2015 12:40:16 +0000 Message-Id: <1426509618-27416-6-git-send-email-peter.maydell@linaro.org> In-Reply-To: <1426509618-27416-1-git-send-email-peter.maydell@linaro.org> References: <1426509618-27416-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PULL 5/7] target-arm: Fix handling of STM (user) with r15 in register list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org The A32 encoding of LDM distinguishes LDM (user) from LDM (exception return) based on whether r15 is in the register list. However for STM (user) there is no equivalent distinction. We were incorrectly treating "r15 in list" as indicating exception return for both LDM and STM, with the result that an STM (user) involving r15 went into an infinite loop. Fix this; note that the value stored for r15 in this case is the current PC regardless of our current mode. Signed-off-by: Peter Maydell Message-id: 1426015125-5521-1-git-send-email-peter.maydell@linaro.org --- target-arm/translate.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index 381d896..9116529 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8859,17 +8859,23 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) case 0x08: case 0x09: { - int j, n, user, loaded_base; + int j, n, loaded_base; + bool exc_return = false; + bool is_load = extract32(insn, 20, 1); + bool user = false; TCGv_i32 loaded_var; /* load/store multiple words */ /* XXX: store correct base if write back */ - user = 0; if (insn & (1 << 22)) { + /* LDM (user), LDM (exception return) and STM (user) */ if (IS_USER(s)) goto illegal_op; /* only usable in supervisor mode */ - if ((insn & (1 << 15)) == 0) - user = 1; + if (is_load && extract32(insn, 15, 1)) { + exc_return = true; + } else { + user = true; + } } rn = (insn >> 16) & 0xf; addr = load_reg(s, rn); @@ -8903,7 +8909,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) j = 0; for(i=0;i<16;i++) { if (insn & (1 << i)) { - if (insn & (1 << 20)) { + if (is_load) { /* load */ tmp = tcg_temp_new_i32(); gen_aa32_ld32u(tmp, addr, get_mem_index(s)); @@ -8968,7 +8974,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) if (loaded_base) { store_reg(s, rn, loaded_var); } - if ((insn & (1 << 22)) && !user) { + if (exc_return) { /* Restore CPSR from SPSR. */ tmp = load_cpu_field(spsr); gen_set_cpsr(tmp, CPSR_ERET_MASK); -- 1.9.1