diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-02-11 16:20:39 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-02-11 16:20:39 +0000 |
commit | 2ae23e75045095151c3b754e7e4e36b23f053264 (patch) | |
tree | e187913a21cdbf5210e83756cf018f0570ec9e89 /target-arm | |
parent | 3b7f5d479caf9b51e99da9940619db720637d5b4 (diff) | |
download | hqemu-2ae23e75045095151c3b754e7e4e36b23f053264.zip hqemu-2ae23e75045095151c3b754e7e4e36b23f053264.tar.gz |
Fix Arm msr spsr bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1761 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/translate.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 77c8957..9390579 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -1033,7 +1033,7 @@ static inline void gen_mulxy(int x, int y) } /* Return the mask of PSR bits set by a MSR instruction. */ -static uint32_t msr_mask(DisasContext *s, int flags) { +static uint32_t msr_mask(DisasContext *s, int flags, int spsr) { uint32_t mask; mask = 0; @@ -1045,8 +1045,11 @@ static uint32_t msr_mask(DisasContext *s, int flags) { mask |= 0xff0000; if (flags & (1 << 3)) mask |= 0xff000000; - /* Mask out undefined bits and state bits. */ - mask &= 0xf89f03df; + /* Mask out undefined bits. */ + mask &= 0xf90f03ff; + /* Mask out state bits. */ + if (!spsr) + mask &= ~0x01000020; /* Mask out privileged bits. */ if (IS_USER(s)) mask &= 0xf80f0200; @@ -1138,8 +1141,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (shift) val = (val >> shift) | (val << (32 - shift)); gen_op_movl_T0_im(val); - if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf), - (insn & (1 << 22)) != 0)) + i = ((insn & (1 << 22)) != 0); + if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) goto illegal_op; } else if ((insn & 0x0f900000) == 0x01000000 && (insn & 0x00000090) != 0x00000090) { @@ -1152,11 +1155,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (op1 & 1) { /* PSR = reg */ gen_movl_T0_reg(s, rm); - if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf), - (op1 & 2) != 0)) + i = ((op1 & 2) != 0); + if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) goto illegal_op; } else { - /* reg = CPSR */ + /* reg = PSR */ rd = (insn >> 12) & 0xf; if (op1 & 2) { if (IS_USER(s)) |