qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [5517] Fix ARMv6t2 strex instructions.


From: Paul Brook
Subject: [Qemu-devel] [5517] Fix ARMv6t2 strex instructions.
Date: Wed, 22 Oct 2008 20:35:54 +0000

Revision: 5517
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5517
Author:   pbrook
Date:     2008-10-22 20:35:54 +0000 (Wed, 22 Oct 2008)

Log Message:
-----------
Fix ARMv6t2 strex instructions.

Signed-off-by: Paul Brook <address@hidden>

Modified Paths:
--------------
    trunk/target-arm/translate.c

Modified: trunk/target-arm/translate.c
===================================================================
--- trunk/target-arm/translate.c        2008-10-22 19:58:32 UTC (rev 5516)
+++ trunk/target-arm/translate.c        2008-10-22 20:35:54 UTC (rev 5517)
@@ -40,7 +40,7 @@
 #define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
 #define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
 
-#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
+#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
 
 /* internal defines */
 typedef struct DisasContext {
@@ -6225,11 +6225,35 @@
                     rd = (insn >> 12) & 0xf;
                     if (insn & (1 << 23)) {
                         /* load/store exclusive */
+                        op1 = (insn >> 21) & 0x3;
+                        if (op1)
+                            ARCH(6T2);
+                        else
+                            ARCH(6);
                         gen_movl_T1_reg(s, rn);
                         addr = cpu_T[1];
                         if (insn & (1 << 20)) {
                             gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
-                            tmp = gen_ld32(addr, IS_USER(s));
+                            switch (op1) {
+                            case 0: /* ldrex */
+                                tmp = gen_ld32(addr, IS_USER(s));
+                                break;
+                            case 1: /* ldrexd */
+                                tmp = gen_ld32(addr, IS_USER(s));
+                                store_reg(s, rd, tmp);
+                                tcg_gen_addi_i32(addr, addr, 4);
+                                tmp = gen_ld32(addr, IS_USER(s));
+                                rd++;
+                                break;
+                            case 2: /* ldrexb */
+                                tmp = gen_ld8u(addr, IS_USER(s));
+                                break;
+                            case 3: /* ldrexh */
+                                tmp = gen_ld16u(addr, IS_USER(s));
+                                break;
+                            default:
+                                abort();
+                            }
                             store_reg(s, rd, tmp);
                         } else {
                             int label = gen_new_label();
@@ -6238,7 +6262,25 @@
                             tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
                                                 0, label);
                             tmp = load_reg(s,rm);
-                            gen_st32(tmp, cpu_T[1], IS_USER(s));
+                            switch (op1) {
+                            case 0:  /*  strex */
+                                gen_st32(tmp, addr, IS_USER(s));
+                                break;
+                            case 1: /*  strexd */
+                                gen_st32(tmp, addr, IS_USER(s));
+                                tcg_gen_addi_i32(addr, addr, 4);
+                                tmp = load_reg(s, rm + 1);
+                                gen_st32(tmp, addr, IS_USER(s));
+                                break;
+                            case 2: /*  strexb */
+                                gen_st8(tmp, addr, IS_USER(s));
+                                break;
+                            case 3: /* strexh */
+                                gen_st16(tmp, addr, IS_USER(s));
+                                break;
+                            default:
+                                abort();
+                            }
                             gen_set_label(label);
                             gen_movl_reg_T0(s, rd);
                         }






reply via email to

[Prev in Thread] Current Thread [Next in Thread]