Commit 86753403b282cd1de867e19449c76a3b1c6e47ff
1 parent
f5a5cca3
Fix ARMv6t2 strex instructions.
Signed-off-by: Paul Brook <paul@codesourcery.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5517 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
45 additions
and
3 deletions
target-arm/translate.c
| ... | ... | @@ -40,7 +40,7 @@ |
| 40 | 40 | #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2) |
| 41 | 41 | #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7) |
| 42 | 42 | |
| 43 | -#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op; | |
| 43 | +#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) | |
| 44 | 44 | |
| 45 | 45 | /* internal defines */ |
| 46 | 46 | typedef struct DisasContext { |
| ... | ... | @@ -6225,11 +6225,35 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6225 | 6225 | rd = (insn >> 12) & 0xf; |
| 6226 | 6226 | if (insn & (1 << 23)) { |
| 6227 | 6227 | /* load/store exclusive */ |
| 6228 | + op1 = (insn >> 21) & 0x3; | |
| 6229 | + if (op1) | |
| 6230 | + ARCH(6T2); | |
| 6231 | + else | |
| 6232 | + ARCH(6); | |
| 6228 | 6233 | gen_movl_T1_reg(s, rn); |
| 6229 | 6234 | addr = cpu_T[1]; |
| 6230 | 6235 | if (insn & (1 << 20)) { |
| 6231 | 6236 | gen_helper_mark_exclusive(cpu_env, cpu_T[1]); |
| 6232 | - tmp = gen_ld32(addr, IS_USER(s)); | |
| 6237 | + switch (op1) { | |
| 6238 | + case 0: /* ldrex */ | |
| 6239 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6240 | + break; | |
| 6241 | + case 1: /* ldrexd */ | |
| 6242 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6243 | + store_reg(s, rd, tmp); | |
| 6244 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6245 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6246 | + rd++; | |
| 6247 | + break; | |
| 6248 | + case 2: /* ldrexb */ | |
| 6249 | + tmp = gen_ld8u(addr, IS_USER(s)); | |
| 6250 | + break; | |
| 6251 | + case 3: /* ldrexh */ | |
| 6252 | + tmp = gen_ld16u(addr, IS_USER(s)); | |
| 6253 | + break; | |
| 6254 | + default: | |
| 6255 | + abort(); | |
| 6256 | + } | |
| 6233 | 6257 | store_reg(s, rd, tmp); |
| 6234 | 6258 | } else { |
| 6235 | 6259 | int label = gen_new_label(); |
| ... | ... | @@ -6238,7 +6262,25 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6238 | 6262 | tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], |
| 6239 | 6263 | 0, label); |
| 6240 | 6264 | tmp = load_reg(s,rm); |
| 6241 | - gen_st32(tmp, cpu_T[1], IS_USER(s)); | |
| 6265 | + switch (op1) { | |
| 6266 | + case 0: /* strex */ | |
| 6267 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6268 | + break; | |
| 6269 | + case 1: /* strexd */ | |
| 6270 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6271 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6272 | + tmp = load_reg(s, rm + 1); | |
| 6273 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6274 | + break; | |
| 6275 | + case 2: /* strexb */ | |
| 6276 | + gen_st8(tmp, addr, IS_USER(s)); | |
| 6277 | + break; | |
| 6278 | + case 3: /* strexh */ | |
| 6279 | + gen_st16(tmp, addr, IS_USER(s)); | |
| 6280 | + break; | |
| 6281 | + default: | |
| 6282 | + abort(); | |
| 6283 | + } | |
| 6242 | 6284 | gen_set_label(label); |
| 6243 | 6285 | gen_movl_reg_T0(s, rd); |
| 6244 | 6286 | } | ... | ... |