From: Julian Seward Date: Fri, 26 Apr 2013 10:24:31 +0000 (+0000) Subject: STRD (both ARM and Thumb): for push-like cases -- specifically, STRD X-Git-Tag: svn/VALGRIND_3_9_0^2~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bf83f89584d408bc3f1c62c1d4ee899ea7bd6d7;p=thirdparty%2Fvalgrind.git STRD (both ARM and Thumb): for push-like cases -- specifically, STRD rD1,rD2, [sp, #-8], generate IR for the SP writeback before the stores. This loses restartability of the instruction but avoids Memcheck complaining that we're writing below the stack pointer. git-svn-id: svn://svn.valgrind.org/vex/trunk@2714 --- diff --git a/VEX/priv/guest_arm_toIR.c b/VEX/priv/guest_arm_toIR.c index 9dc1926b0f..17cdce1959 100644 --- a/VEX/priv/guest_arm_toIR.c +++ b/VEX/priv/guest_arm_toIR.c @@ -67,7 +67,9 @@ /* Limitations, etc - - pretty dodgy exception semantics for {LD,ST}Mxx, no doubt + - pretty dodgy exception semantics for {LD,ST}Mxx and {LD,ST}RD. + These instructions are non-restartable in the case where the + transfer(s) fault. - SWP: the restart jump back is Ijk_Boring; it should be Ijk_NoRedir but that's expensive. See comments on casLE() in @@ -15148,6 +15150,20 @@ DisResult disInstr_ARM_WRK ( /* XXX: but the A8 doesn't seem to trap for misaligned loads, so, ignore alignment issues for the time being. */ + /* For almost all cases, we do the writeback after the transfers. + However, that leaves the stack "uncovered" in this case: + strd rD, [sp, #-8] + In which case, do the writeback to SP now, instead of later. + This is bad in that it makes the insn non-restartable if the + accesses fault, but at least keeps Memcheck happy. */ + Bool writeback_already_done = False; + if (bS == 1 /*store*/ && summary == (2 | 16) + && rN == 13 && rN != rD && rN != rD+1 + && bU == 0/*minus*/ && imm8 == 8) { + putIRegA( rN, mkexpr(eaT), condT, Ijk_Boring ); + writeback_already_done = True; + } + /* doubleword store S 1 doubleword load S 0 */ @@ -15186,7 +15202,8 @@ DisResult disInstr_ARM_WRK ( vassert(rD+0 != rN); /* since we just wrote rD+0 */ vassert(rD+1 != rN); /* since we just wrote rD+1 */ } - putIRegA( rN, mkexpr(eaT), condT, Ijk_Boring ); + if (!writeback_already_done) + putIRegA( rN, mkexpr(eaT), condT, Ijk_Boring ); break; } @@ -18669,6 +18686,20 @@ DisResult disInstr_THUMB_WRK ( IRTemp transAddr = bP == 1 ? postAddr : preAddr; + /* For almost all cases, we do the writeback after the transfers. + However, that leaves the stack "uncovered" in this case: + strd rD, [sp, #-8] + In which case, do the writeback to SP now, instead of later. + This is bad in that it makes the insn non-restartable if the + accesses fault, but at least keeps Memcheck happy. */ + Bool writeback_already_done = False; + if (bL == 0/*store*/ && bW == 1/*wb*/ + && rN == 13 && rN != rT && rN != rT2 + && bU == 0/*minus*/ && (imm8 << 2) == 8) { + putIRegT(rN, mkexpr(postAddr), condT); + writeback_already_done = True; + } + if (bL == 0) { IRTemp oldRt = newTemp(Ity_I32); IRTemp oldRt2 = newTemp(Ity_I32); @@ -18697,7 +18728,7 @@ DisResult disInstr_THUMB_WRK ( putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID); } - if (bW == 1) { + if (bW == 1 && !writeback_already_done) { putIRegT(rN, mkexpr(postAddr), condT); }