|
From: <sv...@va...> - 2010-05-04 08:48:51
|
Author: sewardj
Date: 2010-05-04 09:48:43 +0100 (Tue, 04 May 2010)
New Revision: 1979
Log:
Handle v7 memory fence instructions: ISB DSB DMB and their v6 equivalents:
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 (gl...@go...). Fixes bug 228060.
Modified:
trunk/priv/guest_arm_toIR.c
trunk/priv/host_arm_defs.c
trunk/priv/host_arm_defs.h
trunk/priv/host_arm_isel.c
Modified: trunk/priv/guest_arm_toIR.c
===================================================================
--- trunk/priv/guest_arm_toIR.c 2010-05-03 21:58:22 UTC (rev 1978)
+++ trunk/priv/guest_arm_toIR.c 2010-05-04 08:48:43 UTC (rev 1979)
@@ -1555,6 +1555,24 @@
/* 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 @@
/* 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 -- */
/* ----------------------------------------------------------- */
Modified: trunk/priv/host_arm_defs.c
===================================================================
--- trunk/priv/host_arm_defs.c 2010-05-03 21:58:22 UTC (rev 1978)
+++ trunk/priv/host_arm_defs.c 2010-05-04 08:48:43 UTC (rev 1979)
@@ -766,6 +766,11 @@
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 @@
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 @@
else
addHRegUse(u, HRmWrite, i->ARMin.FPSCR.iReg);
return;
+ case ARMin_MFence:
+ return;
unhandled:
default:
ppARMInstr(i);
@@ -1380,6 +1392,8 @@
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 @@
}
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;
}
Modified: trunk/priv/host_arm_defs.h
===================================================================
--- trunk/priv/host_arm_defs.h 2010-05-03 21:58:22 UTC (rev 1978)
+++ trunk/priv/host_arm_defs.h 2010-05-04 08:48:43 UTC (rev 1979)
@@ -354,7 +354,8 @@
ARMin_VXferD,
ARMin_VXferS,
ARMin_VCvtID,
- ARMin_FPSCR
+ ARMin_FPSCR,
+ ARMin_MFence
}
ARMInstrTag;
@@ -561,6 +562,18 @@
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_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* );
Modified: trunk/priv/host_arm_isel.c
===================================================================
--- trunk/priv/host_arm_isel.c 2010-05-03 21:58:22 UTC (rev 1978)
+++ trunk/priv/host_arm_isel.c 2010-05-04 08:48:43 UTC (rev 1979)
@@ -2383,6 +2383,17 @@
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:
|