]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Support ARM and Thumb "CLREX" instructions since Dalvik generates
authorJulian Seward <jseward@acm.org>
Mon, 26 Sep 2011 16:19:43 +0000 (16:19 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 26 Sep 2011 16:19:43 +0000 (16:19 +0000)
them.  Mucho hassle for something that is used considerably less often
than once in a blue moon.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2209

VEX/priv/guest_arm_toIR.c
VEX/priv/host_arm_defs.c
VEX/priv/host_arm_defs.h
VEX/priv/host_arm_isel.c
VEX/priv/ir_defs.c
VEX/pub/libvex_ir.h

index 675e1b33029aa79d0dea335197e96e852389c08f..6b93da52e62ff42d0c1ab7b5284bf73e750a0882 100644 (file)
@@ -11991,6 +11991,16 @@ static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
          break;
    }
 
+   /* ------------------- CLREX ------------------ */
+   if (insn == 0xF57FF01F) {
+      /* AFAICS, this simply cancels a (all?) reservations made by a
+         (any?) preceding LDREX(es).  Arrange to hand it through to
+         the back end. */
+      stmt( IRStmt_MBE(Imbe_CancelReservation) );
+      DIP("clrex\n");
+      return True;
+   }
+
    /* ------------------- NEON ------------------- */
    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
       Bool ok_neon = decode_NEON_instruction(
@@ -17987,6 +17997,7 @@ DisResult disInstr_THUMB_WRK (
    }
    /* -------------- v7 barrier insns -------------- */
    if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
+      /* FIXME: should this be unconditional? */
       /* XXX this isn't really right, is it?  The generated IR does
          them unconditionally.  I guess it doesn't matter since it
          doesn't do any harm to do them even when the guarding
@@ -18025,6 +18036,7 @@ DisResult disInstr_THUMB_WRK (
 
    /* ---------------------- PLD{,W} ---------------------- */
    if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
+      /* FIXME: should this be unconditional? */
       /* PLD/PLDW immediate, encoding T1 */
       UInt rN    = INSN0(3,0);
       UInt bW    = INSN0(5,5);
@@ -18034,6 +18046,7 @@ DisResult disInstr_THUMB_WRK (
    }
 
    if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
+      /* FIXME: should this be unconditional? */
       /* PLD/PLDW immediate, encoding T2 */
       UInt rN    = INSN0(3,0);
       UInt bW    = INSN0(5,5);
@@ -18043,6 +18056,7 @@ DisResult disInstr_THUMB_WRK (
    }
 
    if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
+      /* FIXME: should this be unconditional? */
       /* PLD/PLDW register, encoding T1 */
       UInt rN   = INSN0(3,0);
       UInt rM   = INSN1(3,0);
@@ -18062,8 +18076,8 @@ DisResult disInstr_THUMB_WRK (
    /* I don't know whether this is really v7-only.  But anyway, we
       have to support it since arm-linux uses TPIDRURO as a thread
       state register. */
-   
    if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
+      /* FIXME: should this be unconditional? */
       UInt rD = INSN1(15,12);
       if (!isBadRegT(rD)) {
          putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
@@ -18073,6 +18087,17 @@ DisResult disInstr_THUMB_WRK (
       /* fall through */
    }
 
+   /* ------------------- CLREX ------------------ */
+   if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
+      /* AFAICS, this simply cancels a (all?) reservations made by a
+         (any?) preceding LDREX(es).  Arrange to hand it through to
+         the back end. */
+      mk_skip_over_T32_if_cond_is_false( condT );
+      stmt( IRStmt_MBE(Imbe_CancelReservation) );
+      DIP("clrex\n");
+      goto decode_success;
+   }
+
    /* ------------------- NOP ------------------ */
    if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
       DIP("nop\n");
index 95236074d8ecfd4bf40eb44fb0b9f66f4a15bf36..6749f49a6d8696fedb32534f9fbe3ca8fc997c5f 100644 (file)
@@ -1338,6 +1338,11 @@ ARMInstr* ARMInstr_MFence ( void ) {
    i->tag      = ARMin_MFence;
    return i;
 }
+ARMInstr* ARMInstr_CLREX( void ) {
+   ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+   i->tag      = ARMin_CLREX;
+   return i;
+}
 
 ARMInstr* ARMInstr_NLdStQ ( Bool isLoad, HReg dQ, ARMAModeN *amode ) {
    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
@@ -1759,6 +1764,9 @@ void ppARMInstr ( ARMInstr* i ) {
          vex_printf("mfence (mcr 15,0,r0,c7,c10,4; 15,0,r0,c7,c10,5; "
                     "15,0,r0,c7,c5,4)");
          return;
+      case ARMin_CLREX:
+         vex_printf("clrex");
+         return;
       case ARMin_NLdStQ:
          if (i->ARMin.NLdStQ.isLoad)
             vex_printf("vld1.32 {");
@@ -2097,6 +2105,8 @@ void getRegUsage_ARMInstr ( HRegUsage* u, ARMInstr* i, Bool mode64 )
          return;
       case ARMin_MFence:
          return;
+      case ARMin_CLREX:
+         return;
       case ARMin_NLdStQ:
          if (i->ARMin.NLdStQ.isLoad)
             addHRegUse(u, HRmWrite, i->ARMin.NLdStQ.dQ);
@@ -2275,6 +2285,8 @@ void mapRegs_ARMInstr ( HRegRemap* m, ARMInstr* i, Bool mode64 )
          return;
       case ARMin_MFence:
          return;
+      case ARMin_CLREX:
+         return;
       case ARMin_NLdStQ:
          i->ARMin.NLdStQ.dQ = lookupHRegRemap(m, i->ARMin.NLdStQ.dQ);
          mapRegs_ARMAModeN(m, i->ARMin.NLdStQ.amode);
@@ -3286,6 +3298,11 @@ Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
          *p++ = 0xEE070F95; /* mcr 15,0,r0,c7,c5,4  (ISB) */
          goto done;
       }
+      case ARMin_CLREX: {
+         *p++ = 0xF57FF01F; /* clrex */
+         goto done;
+      }
+
       case ARMin_NLdStQ: {
          UInt regD = qregNo(i->ARMin.NLdStQ.dQ) << 1;
          UInt regN, regM;
index 92bdbe06f9bd77033514574395ba9b04ff01325d..989f79e30e5849c309914a9d7a18d991140a18f1 100644 (file)
@@ -1,4 +1,3 @@
-
 /*---------------------------------------------------------------*/
 /*--- begin                                   host_arm_defs.h ---*/
 /*---------------------------------------------------------------*/
@@ -587,6 +586,7 @@ typedef
       ARMin_VCvtID,
       ARMin_FPSCR,
       ARMin_MFence,
+      ARMin_CLREX,
       /* Neon */
       ARMin_NLdStQ,
       ARMin_NLdStD,
@@ -827,6 +827,9 @@ typedef
          */
          struct {
          } MFence;
+         /* A CLREX instruction. */
+         struct {
+         } CLREX;
          /* Neon data processing instruction: 3 registers of the same
             length */
          struct {
@@ -940,6 +943,7 @@ extern ARMInstr* ARMInstr_VCvtID   ( Bool iToD, Bool syned,
                                      HReg dst, HReg src );
 extern ARMInstr* ARMInstr_FPSCR    ( Bool toFPSCR, HReg iReg );
 extern ARMInstr* ARMInstr_MFence   ( void );
+extern ARMInstr* ARMInstr_CLREX    ( void );
 extern ARMInstr* ARMInstr_NLdStQ   ( Bool isLoad, HReg, ARMAModeN* );
 extern ARMInstr* ARMInstr_NLdStD   ( Bool isLoad, HReg, ARMAModeN* );
 extern ARMInstr* ARMInstr_NUnary   ( ARMNeonUnOp, HReg, HReg, UInt, Bool );
index 35c4c65b6be9ef0f69ca2319c7c380e5e6d24900..f347eb0d62c377713d2d3467993ddc8826cea3bc 100644 (file)
@@ -5908,7 +5908,10 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
    case Ist_MBE:
       switch (stmt->Ist.MBE.event) {
          case Imbe_Fence:
-            addInstr(env,ARMInstr_MFence());
+            addInstr(env, ARMInstr_MFence());
+            return;
+         case Imbe_CancelReservation:
+            addInstr(env, ARMInstr_CLREX());
             return;
          default:
             break;
index e586d17854aff54d3e0bfb3f4e95779ef5fb6a23..c604ad20c4621d74d531aefadd64190e34f73540 100644 (file)
@@ -1139,8 +1139,12 @@ void ppIRJumpKind ( IRJumpKind kind )
 void ppIRMBusEvent ( IRMBusEvent event )
 {
    switch (event) {
-      case Imbe_Fence: vex_printf("Fence"); break;
-      default:         vpanic("ppIRMBusEvent");
+      case Imbe_Fence:
+         vex_printf("Fence"); break;
+      case Imbe_CancelReservation:
+         vex_printf("CancelReservation"); break;
+      default:
+         vpanic("ppIRMBusEvent");
    }
 }
 
@@ -3408,7 +3412,7 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy )
          break;
       case Ist_MBE:
          switch (stmt->Ist.MBE.event) {
-            case Imbe_Fence:
+            case Imbe_Fence: case Imbe_CancelReservation:
                break;
             default: sanityCheckFail(bb,stmt,"IRStmt.MBE.event: unknown");
                break;
index 3cd6618bddb016a8da79647c365b78a2468a9e50..435090fc2094d47d2356f83557110e6268644feb 100644 (file)
@@ -1772,6 +1772,10 @@ IRDirty* unsafeIRDirty_1_N ( IRTemp dst,
 typedef
    enum { 
       Imbe_Fence=0x18000, 
+      /* Needed only on ARM.  It cancels a reservation made by a
+         preceding Linked-Load, and needs to be handed through to the
+         back end, just as LL and SC themselves are. */
+      Imbe_CancelReservation
    }
    IRMBusEvent;