]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Handle v7 memory fence instructions: ISB DSB DMB and their v6 equivalents:
authorJulian Seward <jseward@acm.org>
Tue, 4 May 2010 08:48:43 +0000 (08:48 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 4 May 2010 08:48:43 +0000 (08:48 +0000)
mcr 15,0,r0,c7,c5,4     mcr 15,0,r0,c7,c10,4    mcr 15,0,r0,c7,c10,5
respectively.  Re-emit them in the v6 form so as not to inhibit possible
support for v6-only platforms in the future.  Extended version of a patch
from Alexander Potapenko (glider@google.com).  Fixes bug 228060.

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

VEX/priv/guest_arm_toIR.c
VEX/priv/host_arm_defs.c
VEX/priv/host_arm_defs.h
VEX/priv/host_arm_isel.c

index 4b8c544da60ebc3f8c3a273ec261b8a6dc967738..db40916431e9246e48009bba05d87b12de03f534 100644 (file)
@@ -1555,6 +1555,24 @@ static Bool decode_NV_instruction ( UInt insn )
       /* fall through */
    }
 
+   /* ------------------- v7 barrier insns ------------------- */
+   switch (insn) {
+      case 0xF57FF06F: /* ISB */
+         stmt( IRStmt_MBE(Imbe_Fence) );
+         DIP("ISB\n");
+         return True;
+      case 0xF57FF04F: /* DSB */
+         stmt( IRStmt_MBE(Imbe_Fence) );
+         DIP("DSB\n");
+         return True;
+      case 0xF57FF05F: /* DMB */
+         stmt( IRStmt_MBE(Imbe_Fence) );
+         DIP("DMB\n");
+         return True;
+      default:
+         break;
+   }
+
    return False;
 
 #  undef INSN_COND
@@ -4697,6 +4715,37 @@ DisResult disInstr_ARM_WRK (
       /* fall through */
    }
 
+   /* Handle various kinds of barriers.  This is rather indiscriminate
+      in the sense that they are all turned into an IR Fence, which
+      means we don't know which they are, so the back end has to
+      re-emit them all when it comes acrosss an IR Fence.
+   */
+   switch (insn) {
+      case 0xEE070F9A: /* v6 */
+         /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
+            Synch Barrier -- ensures completion of memory accesses. */
+         stmt( IRStmt_MBE(Imbe_Fence) );
+         DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
+         goto decode_success;
+      case 0xEE070FBA: /* v6 */
+         /* mcr 15, 0, r0, c7, c10, 5 (v6) equiv to DMB (v7).  Data
+            Memory Barrier -- ensures ordering of memory accesses. */
+         stmt( IRStmt_MBE(Imbe_Fence) );
+         DIP("mcr 15, 0, r0, c7, c10, 5 (data memory barrier)\n");
+         goto decode_success;
+      case 0xEE070F95: /* v6 */
+         /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
+            Instruction Synchronisation Barrier (or Flush Prefetch
+            Buffer) -- a pipe flush, I think.  I suspect we could
+            ignore those, but to be on the safe side emit a fence
+            anyway. */
+         stmt( IRStmt_MBE(Imbe_Fence) );
+         DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
+         goto decode_success;
+      default:
+         break;
+   }
+
    /* ----------------------------------------------------------- */
    /* -- Undecodable                                           -- */
    /* ----------------------------------------------------------- */
index c6687725e5a68accce3298b5b7c472a256e10cfe..7fb7f98ae11963889d8fcae1104255c6d975d35d 100644 (file)
@@ -766,6 +766,11 @@ ARMInstr* ARMInstr_FPSCR ( Bool toFPSCR, HReg iReg ) {
    i->ARMin.FPSCR.iReg    = iReg;
    return i;
 }
+ARMInstr* ARMInstr_MFence ( void ) {
+   ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+   i->tag      = ARMin_MFence;
+   return i;
+}
 
 void ppARMInstr ( ARMInstr* i ) {
    switch (i->tag) {
@@ -1034,6 +1039,11 @@ void ppARMInstr ( ARMInstr* i ) {
             vex_printf(", fpscr");
          }
          return;
+      case ARMin_MFence:
+         vex_printf("mfence (mcr 15,0,r0,c7,c10,4; 15,0,r0,c7,c10,5; "
+                    "15,0,r0,c7,c5,4)");
+         return;
+
       unhandled:
          vex_printf("ppARMInstr: unhandled case (tag %d)", (Int)i->tag);
          vpanic("ppARMInstr(1)");
@@ -1256,6 +1266,8 @@ void getRegUsage_ARMInstr ( HRegUsage* u, ARMInstr* i, Bool mode64 )
          else
             addHRegUse(u, HRmWrite, i->ARMin.FPSCR.iReg);
          return;
+      case ARMin_MFence:
+         return;
       unhandled:
       default:
          ppARMInstr(i);
@@ -1380,6 +1392,8 @@ void mapRegs_ARMInstr ( HRegRemap* m, ARMInstr* i, Bool mode64 )
       case ARMin_FPSCR:
          i->ARMin.FPSCR.iReg = lookupHRegRemap(m, i->ARMin.FPSCR.iReg);
          return;
+      case ARMin_MFence:
+         return;
       unhandled:
       default:
          ppARMInstr(i);
@@ -2262,6 +2276,12 @@ Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
          }
          goto bad; // FPSCR -> iReg case currently ATC
       }
+      case ARMin_MFence: {
+         *p++ = 0xEE070F9A; /* mcr 15,0,r0,c7,c10,4 (DSB) */
+         *p++ = 0xEE070FBA; /* mcr 15,0,r0,c7,c10,5 (DMB) */
+         *p++ = 0xEE070F95; /* mcr 15,0,r0,c7,c5,4  (ISB) */
+         goto done;
+      }
       default: 
          goto bad;
     }
index 0a4c904bb66f0c60019c2ce9dde8095ac38cc644..bc3831228e0ab5064bcb538a479c296b4a9830e1 100644 (file)
@@ -354,7 +354,8 @@ typedef
       ARMin_VXferD,
       ARMin_VXferS,
       ARMin_VCvtID,
-      ARMin_FPSCR
+      ARMin_FPSCR,
+      ARMin_MFence
    }
    ARMInstrTag;
 
@@ -561,6 +562,18 @@ typedef
             Bool toFPSCR;
             HReg iReg;
          } FPSCR;
+         /* Mem fence.  An insn which fences all loads and stores as
+            much as possible before continuing.  On ARM we emit the
+            sequence
+               mcr 15,0,r0,c7,c10,4 (DSB)
+               mcr 15,0,r0,c7,c10,5 (DMB)
+               mcr 15,0,r0,c7,c5,4 (ISB)
+            which is probably total overkill, but better safe than
+            sorry.
+         */
+         struct {
+         } MFence;
+
       } ARMin;
    }
    ARMInstr;
@@ -598,6 +611,7 @@ extern ARMInstr* ARMInstr_VXferS   ( Bool toS, HReg fD, HReg rLo );
 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 void ppARMInstr ( ARMInstr* );
 
index 85ab906744ae19545389757fd7dcaf66f7748350..ed41b8e91e64478e3e4ca6e546b38940ebbf0b69 100644 (file)
@@ -2383,6 +2383,17 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       break;
    }
 
+   /* --------- MEM FENCE --------- */
+   case Ist_MBE:
+      switch (stmt->Ist.MBE.event) {
+         case Imbe_Fence:
+            addInstr(env,ARMInstr_MFence());
+            return;
+         default:
+            break;
+      }
+      break;
+
    /* --------- INSTR MARK --------- */
    /* Doesn't generate any executable code ... */
    case Ist_IMark: