|
From: <sv...@va...> - 2015-01-19 10:29:45
|
Author: sewardj
Date: Mon Jan 19 10:29:37 2015
New Revision: 14874
Log:
Make LOADV32le on 64 bit targets into a template. With this in
place, both 32- and 64-bit shadow loads are generated in-line.
Modified:
branches/NCODE/memcheck/mc_include.h
branches/NCODE/memcheck/mc_main.c
branches/NCODE/memcheck/mc_translate.c
Modified: branches/NCODE/memcheck/mc_include.h
==============================================================================
--- branches/NCODE/memcheck/mc_include.h (original)
+++ branches/NCODE/memcheck/mc_include.h Mon Jan 19 10:29:37 2015
@@ -601,6 +601,7 @@
void MC_(create_ncode_templates) ( void );
extern NCodeTemplate* MC_(tmpl__LOADV64le_on_64);
+extern NCodeTemplate* MC_(tmpl__LOADV32le_on_64);
/* Helper functions defined in mc_main.c */
Modified: branches/NCODE/memcheck/mc_main.c
==============================================================================
--- branches/NCODE/memcheck/mc_main.c (original)
+++ branches/NCODE/memcheck/mc_main.c Mon Jan 19 10:29:37 2015
@@ -4274,7 +4274,8 @@
/*--- Creating NCode templates ---*/
/*------------------------------------------------------------*/
-static ULong mc_LOADV64le_slow ( Addr a );
+VG_REGPARM(1) static ULong mc_LOADV64le_on_64_slow ( Addr a );
+VG_REGPARM(1) static ULong mc_LOADV32le_on_64_slow ( Addr a );
static void* ncode_alloc ( UInt n ) {
return VG_(malloc)("mc.ncode_alloc (NCode, permanent)", n);
@@ -4292,6 +4293,7 @@
}
NCodeTemplate* MC_(tmpl__LOADV64le_on_64) = NULL;
+NCodeTemplate* MC_(tmpl__LOADV32le_on_64) = NULL;
static NCodeTemplate* mk_tmpl__LOADV64le_on_64 ( NAlloc na )
{
@@ -4322,8 +4324,8 @@
cold[2] = NInstr_SetFlagsWri (na, Nsf_CMP, s0, VA_BITS16_UNDEFINED);
cold[3] = NInstr_Branch (na, Ncc_Z, mkNLabel(Nlz_Hot, 10));
cold[4] = NInstr_Call (na, rINVALID, r0, mkNRegVec1(na, a0),
- (void*)& mc_LOADV64le_slow,
- "mc_LOADV64le_slow");
+ (void*)& mc_LOADV64le_on_64_slow,
+ "mc_LOADV64le_on_64_slow");
cold[5] = NInstr_Branch(na, Ncc_ALWAYS, mkNLabel(Nlz_Hot, 10));
hot[11] = cold[6] = NULL;
@@ -4333,10 +4335,54 @@
return tmpl;
}
+static NCodeTemplate* mk_tmpl__LOADV32le_on_64 ( NAlloc na )
+{
+ NInstr** hot = na((11+1) * sizeof(NInstr*));
+ NInstr** cold = na((6+1) * sizeof(NInstr*));
+
+ NReg rINVALID = mkNRegINVALID();
+
+ NReg r0 = mkNReg(Nrr_Result, 0);
+ NReg a0 = mkNReg(Nrr_Argument, 0);
+ NReg s0 = mkNReg(Nrr_Scratch, 0);
+
+ hot[0] = NInstr_SetFlagsWri (na, Nsf_TEST, a0, MASK(4));
+ hot[1] = NInstr_Branch (na, Ncc_NZ, mkNLabel(Nlz_Cold, 4));
+ hot[2] = NInstr_ShiftWri (na, Nsh_SHR, s0, a0, 16);
+ hot[3] = NInstr_LoadU (na, s0, NEA_IRS(na, (HWord)&primary_map[0],
+ s0, 3), 8);
+ hot[4] = NInstr_AluWri (na, Nalu_AND, r0, a0, 0xFFFF);
+ hot[5] = NInstr_ShiftWri (na, Nsh_SHR, r0, r0, 2);
+ hot[6] = NInstr_LoadU (na, r0, NEA_RRS(na, s0, r0, 0), 1);
+ hot[7] = NInstr_SetFlagsWri (na, Nsf_CMP, r0, VA_BITS8_DEFINED);
+ hot[8] = NInstr_Branch (na, Ncc_NZ, mkNLabel(Nlz_Cold, 0));
+ hot[9] = NInstr_ImmW (na, r0, 0xFFFFFFFF00000000ULL
+ | (ULong)V_BITS32_DEFINED);
+ hot[10] = NInstr_Nop (na);
+
+ cold[0] = NInstr_MovW (na, s0, r0);
+ cold[1] = NInstr_ImmW (na, r0, 0xFFFFFFFF00000000ULL
+ | (ULong)V_BITS32_UNDEFINED);
+ cold[2] = NInstr_SetFlagsWri (na, Nsf_CMP, s0, VA_BITS8_UNDEFINED);
+ cold[3] = NInstr_Branch (na, Ncc_Z, mkNLabel(Nlz_Hot, 10));
+ cold[4] = NInstr_Call (na, rINVALID, r0, mkNRegVec1(na, a0),
+ (void*)& mc_LOADV32le_on_64_slow,
+ "mc_LOADV32le_on_64_slow");
+ cold[5] = NInstr_Branch(na, Ncc_ALWAYS, mkNLabel(Nlz_Hot, 10));
+
+ hot[11] = cold[6] = NULL;
+ NCodeTemplate* tmpl
+ = mkNCodeTemplate(na,"LOADV32le_on_64",
+ /*res, parms, scratch*/1, 1, 1, hot, cold);
+ return tmpl;
+}
+
void MC_(create_ncode_templates) ( void )
{
tl_assert(MC_(tmpl__LOADV64le_on_64) == NULL);
+ tl_assert(MC_(tmpl__LOADV32le_on_64) == NULL);
MC_(tmpl__LOADV64le_on_64) = mk_tmpl__LOADV64le_on_64(ncode_alloc);
+ MC_(tmpl__LOADV32le_on_64) = mk_tmpl__LOADV32le_on_64(ncode_alloc);
}
@@ -4471,8 +4517,7 @@
{
return mc_LOADV64(a, False);
}
-
-static ULong mc_LOADV64le_slow ( Addr a )
+VG_REGPARM(1) static ULong mc_LOADV64le_on_64_slow ( Addr a )
{
return mc_LOADVn_slow( a, 64, False/*!isBigEndian*/ );
}
@@ -4593,6 +4638,10 @@
{
return mc_LOADV32(a, False);
}
+VG_REGPARM(1) static ULong mc_LOADV32le_on_64_slow ( Addr a )
+{
+ return mc_LOADVn_slow( a, 32, False/*!isBigEndian*/ );
+}
static INLINE
Modified: branches/NCODE/memcheck/mc_translate.c
==============================================================================
--- branches/NCODE/memcheck/mc_translate.c (original)
+++ branches/NCODE/memcheck/mc_translate.c Mon Jan 19 10:29:37 2015
@@ -4556,6 +4556,23 @@
}
+/* Checks to see if a guard for expr2vbits_Load_WRK denotes 'always true'.
+ Either by being NULL or by being the constant 1:I1. */
+static Bool guardIsAlwaysTrue ( IRAtom* guard )
+{
+ if (guard == NULL)
+ return True;
+ if (guard->tag == Iex_Const) {
+ IRConst* c = guard->Iex.Const.con;
+ tl_assert(c->tag == Ico_U1); /* else ill-typed IR */
+ if (c->Ico.U1 == True) return True;
+ if (c->Ico.U1 == False) return False;
+ tl_assert(0); /* invalid constant */
+ }
+ return False;
+}
+
+
/* Worker function -- do not call directly. See comments on
expr2vbits_Load for the meaning of |guard|.
@@ -4599,23 +4616,40 @@
/* We need to have a place to park the V bits we're just about to
read. */
ty = shadowTypeV(ty);
- IRTemp datavbits = newTemp(mce, ty, VSh);
+ /* ty is now the shadow type for the load. */
/* ------ BEGIN inline NCode ? ------ */
- if (guard == NULL
- && end == Iend_LE && ty == Ity_I64 && mce->hWordTy == Ity_I64) {
- /* Unconditional LOAD64le on 64 bit host. Generate inline code. */
- NCodeTemplate* tmpl = MC_(tmpl__LOADV64le_on_64);
- IRAtom** args = mkIRExprVec_1( addrAct );
- IRTemp* ress = mkIRTempVec_1( datavbits );
- stmt( 'V', mce, IRStmt_NCode(tmpl, args, ress) );
- return mkexpr(datavbits);
+ if (guardIsAlwaysTrue(guard) && mce->hWordTy == Ity_I64 && end == Iend_LE) {
+ if (ty == Ity_I64) {
+ /* Unconditional LOAD64le on 64 bit host. Generate inline code. */
+ IRTemp datavbits64 = newTemp(mce, Ity_I64, VSh);
+ NCodeTemplate* tmpl = MC_(tmpl__LOADV64le_on_64);
+ IRAtom** args = mkIRExprVec_1( addrAct );
+ IRTemp* ress = mkIRTempVec_1( datavbits64 );
+ stmt( 'V', mce, IRStmt_NCode(tmpl, args, ress) );
+ return mkexpr(datavbits64);
+ }
+ if (ty == Ity_I32) {
+ /* Unconditional LOAD32le on 64 bit host. Generate inline code. */
+ IRTemp datavbits64 = newTemp(mce, Ity_I64, VSh);
+ NCodeTemplate* tmpl = MC_(tmpl__LOADV32le_on_64);
+ IRAtom** args = mkIRExprVec_1( addrAct );
+ IRTemp* ress = mkIRTempVec_1( datavbits64 );
+ /* The NCode block produces a 64 bit value, but we need to
+ truncate it to 32 bits. */
+ stmt( 'V', mce, IRStmt_NCode(tmpl, args, ress) );
+ IRAtom* datavbits32
+ = assignNew('V', mce, Ity_I32, unop(Iop_64to32, mkexpr(datavbits64)));
+ return datavbits32;
+ }
+ /* else fall through */
}
/* ------ END inline NCode ? ------ */
/* Now cook up a call to the relevant helper function, to read the
data V bits from shadow memory. */
+ IRTemp datavbits = newTemp(mce, ty, VSh);
void* helper = NULL;
const HChar* hname = NULL;
Bool ret_via_outparam = False;
|