[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 5/7] target-arm: Fix handling of STM (user) with r15
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 5/7] target-arm: Fix handling of STM (user) with r15 in register list |
Date: |
Mon, 16 Mar 2015 12:40:16 +0000 |
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 <address@hidden>
Message-id: address@hidden
---
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
- [Qemu-devel] [PULL 0/7] target-arm queue, Peter Maydell, 2015/03/16
- [Qemu-devel] [PULL 5/7] target-arm: Fix handling of STM (user) with r15 in register list,
Peter Maydell <=
- [Qemu-devel] [PULL 4/7] hw/intc/arm_gic: Initialize the vgic in the realize function, Peter Maydell, 2015/03/16
- [Qemu-devel] [PULL 6/7] target-arm: Ignore low bit of PC in M-profile exception return, Peter Maydell, 2015/03/16
- [Qemu-devel] [PULL 7/7] linux-user: Access correct register for get/set_tls syscalls on ARM TZ CPUs, Peter Maydell, 2015/03/16
- [Qemu-devel] [PULL 2/7] target-arm: fix get_phys_addr_v6/SCTLR_AFE access check, Peter Maydell, 2015/03/16
- [Qemu-devel] [PULL 1/7] target-arm: convert check_ap to ap_to_rw_prot, Peter Maydell, 2015/03/16
- [Qemu-devel] [PULL 3/7] target-arm: get_phys_addr_lpae: more xn control, Peter Maydell, 2015/03/16
- Re: [Qemu-devel] [PULL 0/7] target-arm queue, Peter Maydell, 2015/03/16