Commit 2ae23e75045095151c3b754e7e4e36b23f053264
1 parent
3b7f5d47
Fix Arm msr spsr bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1761 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
11 additions
and
8 deletions
target-arm/translate.c
... | ... | @@ -1033,7 +1033,7 @@ static inline void gen_mulxy(int x, int y) |
1033 | 1033 | } |
1034 | 1034 | |
1035 | 1035 | /* Return the mask of PSR bits set by a MSR instruction. */ |
1036 | -static uint32_t msr_mask(DisasContext *s, int flags) { | |
1036 | +static uint32_t msr_mask(DisasContext *s, int flags, int spsr) { | |
1037 | 1037 | uint32_t mask; |
1038 | 1038 | |
1039 | 1039 | mask = 0; |
... | ... | @@ -1045,8 +1045,11 @@ static uint32_t msr_mask(DisasContext *s, int flags) { |
1045 | 1045 | mask |= 0xff0000; |
1046 | 1046 | if (flags & (1 << 3)) |
1047 | 1047 | mask |= 0xff000000; |
1048 | - /* Mask out undefined bits and state bits. */ | |
1049 | - mask &= 0xf89f03df; | |
1048 | + /* Mask out undefined bits. */ | |
1049 | + mask &= 0xf90f03ff; | |
1050 | + /* Mask out state bits. */ | |
1051 | + if (!spsr) | |
1052 | + mask &= ~0x01000020; | |
1050 | 1053 | /* Mask out privileged bits. */ |
1051 | 1054 | if (IS_USER(s)) |
1052 | 1055 | mask &= 0xf80f0200; |
... | ... | @@ -1138,8 +1141,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
1138 | 1141 | if (shift) |
1139 | 1142 | val = (val >> shift) | (val << (32 - shift)); |
1140 | 1143 | gen_op_movl_T0_im(val); |
1141 | - if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf), | |
1142 | - (insn & (1 << 22)) != 0)) | |
1144 | + i = ((insn & (1 << 22)) != 0); | |
1145 | + if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) | |
1143 | 1146 | goto illegal_op; |
1144 | 1147 | } else if ((insn & 0x0f900000) == 0x01000000 |
1145 | 1148 | && (insn & 0x00000090) != 0x00000090) { |
... | ... | @@ -1152,11 +1155,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
1152 | 1155 | if (op1 & 1) { |
1153 | 1156 | /* PSR = reg */ |
1154 | 1157 | gen_movl_T0_reg(s, rm); |
1155 | - if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf), | |
1156 | - (op1 & 2) != 0)) | |
1158 | + i = ((op1 & 2) != 0); | |
1159 | + if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) | |
1157 | 1160 | goto illegal_op; |
1158 | 1161 | } else { |
1159 | - /* reg = CPSR */ | |
1162 | + /* reg = PSR */ | |
1160 | 1163 | rd = (insn >> 12) & 0xf; |
1161 | 1164 | if (op1 & 2) { |
1162 | 1165 | if (IS_USER(s)) | ... | ... |