Commit 86753403b282cd1de867e19449c76a3b1c6e47ff

Authored by pbrook
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,7 +40,7 @@
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2) 40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7) 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 /* internal defines */ 45 /* internal defines */
46 typedef struct DisasContext { 46 typedef struct DisasContext {
@@ -6225,11 +6225,35 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6225,11 +6225,35 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6225 rd = (insn >> 12) & 0xf; 6225 rd = (insn >> 12) & 0xf;
6226 if (insn & (1 << 23)) { 6226 if (insn & (1 << 23)) {
6227 /* load/store exclusive */ 6227 /* load/store exclusive */
  6228 + op1 = (insn >> 21) & 0x3;
  6229 + if (op1)
  6230 + ARCH(6T2);
  6231 + else
  6232 + ARCH(6);
6228 gen_movl_T1_reg(s, rn); 6233 gen_movl_T1_reg(s, rn);
6229 addr = cpu_T[1]; 6234 addr = cpu_T[1];
6230 if (insn & (1 << 20)) { 6235 if (insn & (1 << 20)) {
6231 gen_helper_mark_exclusive(cpu_env, cpu_T[1]); 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 store_reg(s, rd, tmp); 6257 store_reg(s, rd, tmp);
6234 } else { 6258 } else {
6235 int label = gen_new_label(); 6259 int label = gen_new_label();
@@ -6238,7 +6262,25 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6238,7 +6262,25 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6238 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 6262 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6239 0, label); 6263 0, label);
6240 tmp = load_reg(s,rm); 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 gen_set_label(label); 6284 gen_set_label(label);
6243 gen_movl_reg_T0(s, rd); 6285 gen_movl_reg_T0(s, rd);
6244 } 6286 }