From: Julian Seward Date: Mon, 14 Feb 2011 13:50:19 +0000 (+0000) Subject: Merge from trunk, r2085 (Implement LOOPNEL (32-bit version of LOOPNE).) X-Git-Tag: svn/VALGRIND_3_6_1^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39e818a2cfbdf0458d82e4427da79090c59fb3b9;p=thirdparty%2Fvalgrind.git Merge from trunk, r2085 (Implement LOOPNEL (32-bit version of LOOPNE).) git-svn-id: svn://svn.valgrind.org/vex/branches/VEX_3_6_BRANCH@2099 --- diff --git a/VEX/priv/guest_amd64_toIR.c b/VEX/priv/guest_amd64_toIR.c index 489ada2a9e..7ccbb968dc 100644 --- a/VEX/priv/guest_amd64_toIR.c +++ b/VEX/priv/guest_amd64_toIR.c @@ -16401,18 +16401,33 @@ DisResult disInstr_AMD64_WRK ( case 0xE1: /* LOOPE disp8: decrement count, jump if count != 0 && ZF==1 */ case 0xE2: /* LOOP disp8: decrement count, jump if count != 0 */ { /* The docs say this uses rCX as a count depending on the - address size override, not the operand one. Since we don't - handle address size overrides, I guess that means RCX. */ + address size override, not the operand one. */ IRExpr* zbit = NULL; IRExpr* count = NULL; IRExpr* cond = NULL; HChar* xtra = NULL; - if (have66orF2orF3(pfx) || haveASO(pfx)) goto decode_failure; + if (have66orF2orF3(pfx) || 1==getRexW(pfx)) goto decode_failure; + /* So at this point we've rejected any variants which appear to + be governed by the usual operand-size modifiers. Hence only + the address size prefix can have an effect. It changes the + size from 64 (default) to 32. */ d64 = guest_RIP_bbstart+delta+1 + getSDisp8(delta); delta++; - putIReg64(R_RCX, binop(Iop_Sub64, getIReg64(R_RCX), mkU64(1))); + if (haveASO(pfx)) { + /* 64to32 of 64-bit get is merely a get-put improvement + trick. */ + putIReg32(R_RCX, binop(Iop_Sub32, + unop(Iop_64to32, getIReg64(R_RCX)), + mkU32(1))); + } else { + putIReg64(R_RCX, binop(Iop_Sub64, getIReg64(R_RCX), mkU64(1))); + } + /* This is correct, both for 32- and 64-bit versions. If we're + doing a 32-bit dec and the result is zero then the default + zero extension rule will cause the upper 32 bits to be zero + too. Hence a 64-bit check against zero is OK. */ count = getIReg64(R_RCX); cond = binop(Iop_CmpNE64, count, mkU64(0)); switch (opc) { @@ -16422,19 +16437,19 @@ DisResult disInstr_AMD64_WRK ( case 0xE1: xtra = "e"; zbit = mk_amd64g_calculate_condition( AMD64CondZ ); - cond = mkAnd1(cond, zbit); + cond = mkAnd1(cond, zbit); break; case 0xE0: xtra = "ne"; zbit = mk_amd64g_calculate_condition( AMD64CondNZ ); - cond = mkAnd1(cond, zbit); + cond = mkAnd1(cond, zbit); break; default: vassert(0); } stmt( IRStmt_Exit(cond, Ijk_Boring, IRConst_U64(d64)) ); - DIP("loop%s 0x%llx\n", xtra, d64); + DIP("loop%s%s 0x%llx\n", xtra, haveASO(pfx) ? "l" : "", d64); break; }