aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-02-11 16:20:39 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-02-11 16:20:39 +0000
commit2ae23e75045095151c3b754e7e4e36b23f053264 (patch)
treee187913a21cdbf5210e83756cf018f0570ec9e89 /target-arm
parent3b7f5d479caf9b51e99da9940619db720637d5b4 (diff)
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.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 77c8957af8..93905793a0 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))