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 | } | ... | ... |