|
From: <sv...@va...> - 2015-04-14 19:23:35
|
Author: sewardj
Date: Tue Apr 14 20:23:28 2015
New Revision: 15090
Log:
Add an NCode template for 32-bit loads on 32 bit targets.
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 Tue Apr 14 20:23:28 2015
@@ -605,6 +605,8 @@
extern NCodeTemplate* MC_(tmpl__LOADV16le_on_64);
extern NCodeTemplate* MC_(tmpl__LOADV8_on_64);
+extern NCodeTemplate* MC_(tmpl__LOADV32le_on_32);
+
/* 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 Tue Apr 14 20:23:28 2015
@@ -4279,6 +4279,8 @@
VG_REGPARM(1) static ULong mc_LOADV16le_on_64_slow ( Addr a );
VG_REGPARM(1) static ULong mc_LOADV8_on_64_slow ( Addr a );
+VG_REGPARM(1) static UInt mc_LOADV32le_on_32_slow ( Addr a );
+
static void* ncode_alloc ( UInt n ) {
return VG_(malloc)("mc.ncode_alloc (NCode, permanent)", n);
}
@@ -4299,6 +4301,8 @@
NCodeTemplate* MC_(tmpl__LOADV16le_on_64) = NULL;
NCodeTemplate* MC_(tmpl__LOADV8_on_64) = NULL;
+NCodeTemplate* MC_(tmpl__LOADV32le_on_32) = NULL;
+
static NCodeTemplate* mk_tmpl__LOADV64le_on_64 ( NAlloc na )
{
NInstr** hot = na((11+1) * sizeof(NInstr*));
@@ -4609,6 +4613,68 @@
return tmpl;
}
+static NCodeTemplate* mk_tmpl__LOADV32le_on_32 ( 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);
+
+ /* NCode [r0] = "LOADV32le_on_32" [a0] s0 {
+ hot:
+ 0 tst.w a0, #3 high?
+ 1 bnz cold.4 yes, goto slow path
+ 2 shr.w s0, a0, #16 s0 = pri-map-ix
+ 3 ld.32 s0, [&pri_map[0] + s0 << #2] s0 = sec-map
+ 4 and.w r0, a0, #0xFFFF r0 = sec-map-offB
+ 5 shr.w r0, r0, #2 r0 = sec-map-ix
+ 6 ld.8 r0, [s0 + r0] r0 = sec-map-VABITS8
+ 7 cmp.w r0, #0xAA r0 == VABITS8_DEFINED?
+ 8 bnz cold.0 no, goto cold.0
+ 9 imm.w r0, #0x0 VBITS32_DEFINED
+ 10 nop continue
+ cold:
+ 0 mov.w s0, r0 s0 = sec-map-VABITS8
+ 1 imm.w r0, #0xFFFFFFFF VBITS32_UNDEFINED
+ 2 cmp.w s0, #0x55 s0 == VABITS8_UNDEFINED?
+ 3 bz hot.10 yes, continue
+ 4 call r0 = mc_LOADV32le_on_32_slow[..](a0) call helper
+ 5 b hot.10 continue
+ }
+ */
+ 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, 8, s0, NEA_IRS(na, (HWord)&primary_map[0],
+ s0, 2));
+ 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, 1, r0, NEA_RRS(na, s0, r0, 0));
+ 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, V_BITS32_DEFINED);
+ hot[10] = NInstr_Nop (na);
+
+ cold[0] = NInstr_MovW (na, s0, r0);
+ cold[1] = NInstr_ImmW (na, r0, 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_32_slow,
+ "mc_LOADV32le_on_32_slow");
+ cold[5] = NInstr_Branch (na, Ncc_ALWAYS, mkNLabel(Nlz_Hot, 10));
+
+ hot[11] = cold[6] = NULL;
+ NCodeTemplate* tmpl
+ = mkNCodeTemplate(na,"LOADV32le_on_32",
+ /*res, parms, scratch*/1, 1, 1, hot, cold);
+ return tmpl;
+}
+
void MC_(create_ncode_templates) ( void )
{
@@ -4620,6 +4686,9 @@
MC_(tmpl__LOADV32le_on_64) = mk_tmpl__LOADV32le_on_64(ncode_alloc);
MC_(tmpl__LOADV16le_on_64) = mk_tmpl__LOADV16le_on_64(ncode_alloc);
MC_(tmpl__LOADV8_on_64) = mk_tmpl__LOADV8_on_64(ncode_alloc);
+
+ tl_assert(MC_(tmpl__LOADV32le_on_32) == NULL);
+ MC_(tmpl__LOADV32le_on_32) = mk_tmpl__LOADV32le_on_32(ncode_alloc);
}
@@ -4879,6 +4948,10 @@
{
return mc_LOADVn_slow( a, 32, False/*!isBigEndian*/ );
}
+VG_REGPARM(1) static UInt mc_LOADV32le_on_32_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 Tue Apr 14 20:23:28 2015
@@ -4625,6 +4625,7 @@
/* ty is now the shadow type for the load. */
/* ------ BEGIN inline NCode ? ------ */
+ /* NCode load cases for 64 bit hosts */
if (guardIsAlwaysTrue(guard) && mce->hWordTy == Ity_I64 && end == Iend_LE) {
switch (ty) {
case Ity_I64: {
@@ -4683,6 +4684,25 @@
break;
}
}
+ else
+ /* NCode load cases for 32 bit hosts */
+ if (guardIsAlwaysTrue(guard) && mce->hWordTy == Ity_I32 && end == Iend_LE) {
+ switch (ty) {
+ case Ity_I32: {
+ /* Unconditional LOAD32le on 32 bit host. Generate inline code. */
+ IRTemp datavbits32 = newTemp(mce, Ity_I32, VSh);
+ NCodeTemplate* tmpl = MC_(tmpl__LOADV32le_on_32);
+ IRAtom** args = mkIRExprVec_1( addrAct );
+ IRTemp* ress = mkIRTempVec_1( datavbits32 );
+ stmt( 'V', mce, IRStmt_NCode(tmpl, args, ress) );
+ return mkexpr(datavbits32);
+ }
+ default:
+ /* else fall through */
+ break;
+ }
+ }
+
/* ------ END inline NCode ? ------ */
/* Now cook up a call to the relevant helper function, to read the
|
|
From: Matthias S. <zz...@ge...> - 2015-04-17 04:50:16
|
On 14.04.2015 21:23, sv...@va... wrote:
>
> +static NCodeTemplate* mk_tmpl__LOADV32le_on_32 ( 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);
> +
> + /* NCode [r0] = "LOADV32le_on_32" [a0] s0 {
> + hot:
> + 0 tst.w a0, #3 high?
I guess here it should say "unaligned".
Regards
Matthias
|
|
From: Julian S. <js...@ac...> - 2015-04-17 07:28:49
|
On 17/04/15 06:50, Matthias Schwarzott wrote:
>> + /* NCode [r0] = "LOADV32le_on_32" [a0] s0 {
>> + hot:
>> + 0 tst.w a0, #3 high?
>
> I guess here it should say "unaligned".
Wow, I didn't think anybody was reading these in so much detail.
So .. actually .. no. On 32 bit targets, the primary_map covers
the entire address space in 64k chunks, so we only need to check the
address for misalignment; it can't be "high". And this is for a
32-bit target -- hence the "_on_32" suffix.
You can see the equivalent test for a 64 bit target is against
0xFFFF FFF0 0000 0003, since if any of the top 28 bits of the
address are set, then it can't be indexed via the primary_map.
J
|
|
From: Julian S. <js...@ac...> - 2015-04-17 07:35:35
|
> On 17/04/15 06:50, Matthias Schwarzott wrote:
>
>>> + /* NCode [r0] = "LOADV32le_on_32" [a0] s0 {
>>> + hot:
>>> + 0 tst.w a0, #3 high?
>>
>> I guess here it should say "unaligned".
>
> So .. actually .. no.
Hmm ok, I shouldn't write email with so little coffee in the system.
Yes you are right. Should be "unaligned".
J
|