From: Julian Seward Date: Mon, 8 Nov 2004 13:14:06 +0000 (+0000) Subject: x86 guest: majorly rehash eflags thunk scheme for a second time. See X-Git-Tag: svn/VALGRIND_3_0_1^2~809 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c14dc7f9375547eec92ad701e362fb3fb209350;p=thirdparty%2Fvalgrind.git x86 guest: majorly rehash eflags thunk scheme for a second time. See detailed comment in priv/guest-x86/gdefs.h. In short we move to a 4-word thunk so as to be able to present Memcheck with the data dependencies we want, and at the same time allow iropt to easily optimise away most of the helper calls that evaluate the thunk. Hopefully this is the last change. Comment in priv/guest-x86/gdefs.h also explains properly the relationship between the thunk arrangements and how we expect Memcheck to behave with respect to definedness of flags. git-svn-id: svn://svn.valgrind.org/vex/trunk@525 --- diff --git a/VEX/head20041019/coregrind/vg_translate.c b/VEX/head20041019/coregrind/vg_translate.c index 7178fb62d7..1cc0c3fbc6 100644 --- a/VEX/head20041019/coregrind/vg_translate.c +++ b/VEX/head20041019/coregrind/vg_translate.c @@ -1661,8 +1661,8 @@ Bool VG_(translate) ( ThreadId tid, Addr orig_addr, if (redir != orig_addr && VG_(clo_verbosity) >= 2) { Char name1[64] = ""; Char name2[64] = ""; - VG_(get_fnname_if_entry)(orig_addr, name1, 64); - VG_(get_fnname_if_entry)(redir, name2, 64); + VG_(get_fnname_w_offset)(orig_addr, name1, 64); + VG_(get_fnname_w_offset)(redir, name2, 64); VG_(message)(Vg_UserMsg, "TRANSLATE: %p (%s) redirected to %p (%s)", orig_addr, name1, @@ -1702,7 +1702,7 @@ Bool VG_(translate) ( ThreadId tid, Addr orig_addr, /* If doing any code printing, print a basic block start marker */ if (VG_(clo_trace_codegen)) { Char fnname[64] = ""; - VG_(get_fnname_if_entry)(orig_addr, fnname, 64); + VG_(get_fnname_w_offset)(orig_addr, fnname, 64); VG_(printf)( "==== BB %d %s(%p) approx BBs exec'd %llu ====\n", VG_(get_bbs_translated)(), fnname, orig_addr, diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 84782fe0e6..893849628e 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -46,16 +46,27 @@ VexGuestLayout x86guest_layout; /*---------------------------------------------------------*/ /* --- CLEAN HELPERS --- */ -extern UInt calculate_eflags_all ( UInt cc_op, UInt cc_res, UInt cc_aux ); -extern UInt calculate_eflags_c ( UInt cc_op, UInt cc_res, UInt cc_aux ); + +extern UInt calculate_eflags_all ( UInt cc_op, + UInt cc_dep1, UInt cc_dep2, UInt cc_ndep ); + +extern UInt calculate_eflags_c ( UInt cc_op, + UInt cc_dep1, UInt cc_dep2, UInt cc_ndep ); + extern UInt calculate_condition ( UInt/*Condcode*/ cond, - UInt cc_op, UInt cc_res, UInt cc_aux ); + UInt cc_op, + UInt cc_dep1, UInt cc_dep2, UInt cc_ndep ); + extern UInt calculate_FXAM ( UInt tag, ULong dbl ); + extern ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ); /* --- DIRTY HELPERS --- */ + extern ULong loadF80le ( UInt ); + extern void storeF80le ( UInt, ULong ); + extern void dirtyhelper_CPUID ( VexGuestX86State* ); @@ -84,84 +95,177 @@ extern void dirtyhelper_CPUID ( VexGuestX86State* ); #define FC_MASK_C1 (1 << 9) #define FC_MASK_C0 (1 << 8) -/* %EFLAGS thunk descriptors. This encoding is slightly non-obvious, - for the benefit of Memcheck. The intention is to make RES be the - actual operation result -- or, in the case of multiply longs, at - least have a complete data dependency on the real result. That - means that the AUX field needs to carry -- in the case of {S,U}MULL - -- a value which allows the real result to be recovered from the - RES field. - - Note, for cases in which some or all of the old flags are also an - input (INC, DEC, ROL, ROR) we could have chosen to xor in the old - flags into the RES field. The effect would be that Memcheck then - considers the result of the operation to also be dependent on the - definedness of the old flags. This seems a step too far -- if the - compiler creates conditional jumps/moves partially dependent on - flags it is unsure of the definedness of -- then it is generating - buggy code. So we don't do this. - - In short, we need to roll into the RES field all inputs to the - computation that we want Memcheck to think have a bearing on the - definedness of the result. We then tell Memcheck that only the RES - field needs to have its definedness tracked, and the AUX and OP - fields can be ignored. The upshot is that we need to put in the - AUX field whatever info is needed to actually compute the flags - given the potentially strange mixture of stuff in the RES field. +/* %EFLAGS thunk descriptors. A four-word thunk is used to record + details of the most recent flag-setting operation, so the flags can + be computed later if needed. It is possible to do this a little + more efficiently using a 3-word thunk, but that makes it impossible + to describe the flag data dependencies sufficiently accurately for + Memcheck. Hence 4 words are used, with minimal loss of efficiency. + + The four words are: + + CC_OP, which describes the operation. + + CC_DEP1 and CC_DEP2. These are arguments to the operation. + We want Memcheck to believe that the resulting flags are + data-dependent on both CC_DEP1 and CC_DEP2, hence the + name DEP. + + CC_NDEP. This is a 3rd argument to the operation which is + sometimes needed. We arrange things so that Memcheck does + not believe the resulting flags are data-dependent on CC_NDEP + ("not dependent"). + + To make Memcheck believe that (the definedness of) the encoded + flags depends only on (the definedness of) CC_DEP1 and CC_DEP2 + requires two things: + + (1) In the guest state layout info (x86guest_layout), CC_OP and + CC_NDEP are marked as always defined. + + (2) When passing the thunk components to an evaluation function + (calculate_condition, calculate_eflags, calculate_eflags_c) the + IRCallee's mcx_mask must be set so as to exclude from + consideration all passed args except CC_DEP1 and CC_DEP2. + + Strictly speaking only (2) is necessary for correctness. However, + (1) helps efficiency in that since (2) means we never ask about the + definedness of CC_OP or CC_NDEP, we may as well not even bother to + track their definedness. + + When building the thunk, it is always necessary to write words into + CC_DEP1 and CC_DEP2, even if those args are not used given the + CC_OP field (eg, CC_DEP2 is not used if CC_OP is CC_LOGIC1/2/4). + This is important because otherwise Memcheck could give false + positives as it does not understand the relationship between the + CC_OP field and CC_DEP1 and CC_DEP2, and so believes that the + definedness of the stored flags always depends on both CC_DEP1 and + CC_DEP2. + + However, it is only necessary to set CC_NDEP when the CC_OP value + requires it, because Memcheck ignores CC_NDEP, and the evaluation + functions do understand the CC_OP fields and will only examine + CC_NDEP for suitable values of CC_OP. + + A summary of the field usages is: + + Operation DEP1 DEP2 NDEP + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + add/sub/mul first arg second arg unused + + adc/sbb first arg (second arg) + XOR old_carry old_carry + + and/or/xor result zero unused + + inc/dec result zero old_carry + + shl/shr/sar result subshifted- unused + result + + rol/ror result zero old_flags + + copy old_flags zero unused. + + + Therefore Memcheck will believe the following: + + * add/sub/mul -- definedness of result flags depends on definedness + of both args. + + * adc/sbb -- definedness of result flags depends on definedness of + both args and definedness of the old C flag. Because only two + DEP fields are available, the old C flag is XOR'd into the second + arg so that Memcheck sees the data dependency on it. That means + the NDEP field must contain a second copy of the old C flag + so that the evaluation functions can correctly recover the second + arg. + + * and/or/xor are straightforward -- definedness of result flags + depends on definedness of result value. + + * inc/dec -- definedness of result flags depends only on + definedness of result. This isn't really true -- it also depends + on the old C flag. However, we don't want Memcheck to see that, + and so the old C flag must be passed in NDEP and not in DEP2. + It's inconceivable that a compiler would generate code that puts + the C flag in an undefined state, then does an inc/dec, which + leaves C unchanged, and then makes a conditional jump/move based + on C. So our fiction seems a good approximation. + + * shl/shr/sar -- straightforward, again, definedness of result + flags depends on definedness of result value. The subshifted + value (value shifted one less) is also needed, but its + definedness is the same as the definedness of the shifted value. + + * rol/ror -- these only set O and C, and leave A Z C P alone. + However it seems prudent (as per inc/dec) to say the definedness + of all resulting flags depends on the definedness of the result, + hence the old flags must go in as NDEP and not DEP2. + + * rcl/rcr are too difficult to do in-line, and so are done by a + helper function. They are not part of this scheme. The helper + function takes the value to be rotated, the rotate amount and the + old flags, and returns the new flags and the rotated value. + Since the helper's mcx_mask does not have any set bits, Memcheck + will lazily propagate undefinedness from any of the 3 args into + both results (flags and actual value). */ enum { - CC_OP_COPY, /* RES = current flags, AUX = 0, do nothing */ + CC_OP_COPY, /* DEP1 = current flags, DEP2 = 0, NDEP = unused */ + /* just copy DEP1 to output */ - CC_OP_ADDB, /* RES = argL+argR, AUX = argR */ - CC_OP_ADDW, + CC_OP_ADDB, /* 1 */ + CC_OP_ADDW, /* 2 DEP1 = argL, DEP2 = argR, NDEP = unused */ CC_OP_ADDL, /* 3 */ - CC_OP_ADCB, /* RES = argL+argR, AUX = argR */ - CC_OP_ADCW, - CC_OP_ADCL, /* 6 */ + CC_OP_SUBB, /* 4 */ + CC_OP_SUBW, /* 5 DEP1 = argL, DEP2 = argR, NDEP = unused */ + CC_OP_SUBL, /* 6 */ - CC_OP_SUBB, /* RES = argL-argR, AUX = argR */ - CC_OP_SUBW, - CC_OP_SUBL, /* 9 */ + CC_OP_ADCB, /* 7 */ + CC_OP_ADCW, /* 8 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */ + CC_OP_ADCL, /* 9 */ - CC_OP_SBBB, /* RES = argL-argR, AUX = argR */ - CC_OP_SBBW, + CC_OP_SBBB, /* 10 */ + CC_OP_SBBW, /* 11 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */ CC_OP_SBBL, /* 12 */ - CC_OP_LOGICB, /* RES = and/or/xor(argL,argR), AUX = 0 */ - CC_OP_LOGICW, + CC_OP_LOGICB, /* 13 */ + CC_OP_LOGICW, /* 14 DEP1 = result, DEP2 = 0, NDEP = unused */ CC_OP_LOGICL, /* 15 */ - CC_OP_INCB, /* RES = arg+1, AUX = old C flag (0 or 1) */ - CC_OP_INCW, + CC_OP_INCB, /* 16 */ + CC_OP_INCW, /* 17 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */ CC_OP_INCL, /* 18 */ - CC_OP_DECB, /* RES = arg-1, AUX = old C flag (0 or 1) */ - CC_OP_DECW, + CC_OP_DECB, /* 19 */ + CC_OP_DECW, /* 20 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */ CC_OP_DECL, /* 21 */ - CC_OP_SHLB, /* RES = res, AUX = res' */ - CC_OP_SHLW, /* where res' is like res but shifted one bit less */ + CC_OP_SHLB, /* 22 DEP1 = res, DEP2 = res', NDEP = unused */ + CC_OP_SHLW, /* 23 where res' is like res but shifted one bit less */ CC_OP_SHLL, /* 24 */ - CC_OP_SARB, /* RES = res, AUX = res' */ - CC_OP_SARW, /* where res' is like res but shifted one bit less */ - CC_OP_SARL, /* 27 */ + CC_OP_SHRB, /* 25 DEP1 = res, DEP2 = res', NDEP = unused */ + CC_OP_SHRW, /* 26 where res' is like res but shifted one bit less */ + CC_OP_SHRL, /* 27 */ - CC_OP_ROLB, /* RES = res, AUX = old flags */ - CC_OP_ROLW, + CC_OP_ROLB, /* 28 */ + CC_OP_ROLW, /* 29 DEP1 = res, DEP2 = 0, NDEP = old flags */ CC_OP_ROLL, /* 30 */ - CC_OP_RORB, /* RES = res, AUX = old flags */ - CC_OP_RORW, + CC_OP_RORB, /* 31 */ + CC_OP_RORW, /* 32 DEP1 = res, DEP2 = 0, NDEP = old flags */ CC_OP_RORL, /* 33 */ - CC_OP_UMULB, /* RES = hiHalf(result) ^ loHalf(result) */ - CC_OP_UMULW, /* AUX = loHalf(result) */ + CC_OP_UMULB, /* 34 */ + CC_OP_UMULW, /* 35 DEP1 = argL, DEP2 = argR, NDEP = unused */ CC_OP_UMULL, /* 36 */ - CC_OP_SMULB, /* RES = hiHalf(result) ^ loHalf(result) */ - CC_OP_SMULW, /* AUX = loHalf(result) */ + CC_OP_SMULB, /* 37 */ + CC_OP_SMULW, /* 38 DEP1 = argL, DEP2 = argR, NDEP = unused */ CC_OP_SMULL, /* 39 */ CC_OP_NUMBER diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 2126a7ca6c..84f52bf52a 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -87,14 +87,16 @@ inline static Int lshift ( Int x, Int n ) : (__data_bits==16 ? 0xFFFF \ : 0xFFFFFFFF); \ /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1); \ - /* const */ UInt CC_RES = cc_res_formal; \ - /* const */ UInt CC_AUX = cc_aux_formal; \ - /* Three bogus assignments, which hopefully gcc can */ \ + /* const */ UInt CC_DEP1 = cc_dep1_formal; \ + /* const */ UInt CC_DEP2 = cc_dep2_formal; \ + /* const */ UInt CC_NDEP = cc_ndep_formal; \ + /* Four bogus assignments, which hopefully gcc can */ \ /* optimise away, and which stop it complaining about */ \ /* unused variables. */ \ SIGN_MASK = SIGN_MASK; \ DATA_MASK = DATA_MASK; \ - CC_AUX = CC_AUX; + CC_DEP2 = CC_DEP2; \ + CC_NDEP = CC_NDEP; /*-------------------------------------------------------------*/ @@ -104,9 +106,9 @@ inline static Int lshift ( Int x, Int n ) PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ Int argL, argR, res; \ - argL = CC_RES - CC_AUX; \ - argR = CC_AUX; \ - res = CC_RES; \ + argL = CC_DEP1; \ + argR = CC_DEP2; \ + res = argL + argR; \ cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \ pf = parity_table[(UChar)res]; \ af = (res ^ argL ^ argR) & 0x10; \ @@ -119,41 +121,45 @@ inline static Int lshift ( Int x, Int n ) /*-------------------------------------------------------------*/ -#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \ +#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \ { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ Int argL, argR, res; \ - argL = CC_RES - CC_AUX - 1; \ - argR = CC_AUX; \ - res = CC_RES; \ - cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL; \ + argL = CC_DEP1; \ + argR = CC_DEP2; \ + res = argL - argR; \ + cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ pf = parity_table[(UChar)res]; \ af = (res ^ argL ^ argR) & 0x10; \ zf = ((DATA_UTYPE)res == 0) << 6; \ sf = lshift(res, 8 - DATA_BITS) & 0x80; \ - of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ - 12 - DATA_BITS) & CC_MASK_O; \ + of = lshift((argL ^ argR) & (argL ^ res), \ + 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } /*-------------------------------------------------------------*/ -#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \ +#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \ { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ - Int argL, argR, res; \ - argL = CC_RES + CC_AUX; \ - argR = CC_AUX; \ - res = CC_RES; \ - cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ + Int argL, argR, oldC, res; \ + oldC = CC_NDEP & CC_MASK_C; \ + argL = CC_DEP1; \ + argR = CC_DEP2 ^ oldC; \ + res = (argL + argR) + oldC; \ + if (oldC) \ + cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL; \ + else \ + cf = (DATA_UTYPE)res < (DATA_UTYPE)argL; \ pf = parity_table[(UChar)res]; \ af = (res ^ argL ^ argR) & 0x10; \ zf = ((DATA_UTYPE)res == 0) << 6; \ sf = lshift(res, 8 - DATA_BITS) & 0x80; \ - of = lshift((argL ^ argR) & (argL ^ res), \ - 12 - DATA_BITS) & CC_MASK_O; \ + of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ + 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -163,11 +169,15 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ - Int argL, argR, res; \ - argL = CC_RES + CC_AUX + 1; \ - argR = CC_AUX; \ - res = CC_RES; \ - cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR; \ + Int argL, argR, oldC, res; \ + oldC = CC_NDEP & CC_MASK_C; \ + argL = CC_DEP1; \ + argR = CC_DEP2 ^ oldC; \ + res = (argL - argR) - oldC; \ + if (oldC) \ + cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR; \ + else \ + cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR; \ pf = parity_table[(UChar)res]; \ af = (res ^ argL ^ argR) & 0x10; \ zf = ((DATA_UTYPE)res == 0) << 6; \ @@ -184,10 +194,10 @@ inline static Int lshift ( Int x, Int n ) PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ cf = 0; \ - pf = parity_table[(UChar)CC_RES]; \ + pf = parity_table[(UChar)CC_DEP1]; \ af = 0; \ - zf = ((DATA_UTYPE)CC_RES == 0) << 6; \ - sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \ + zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ + sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ of = 0; \ return cf | pf | af | zf | sf | of; \ } @@ -198,15 +208,16 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ - Int argL, argR; \ - argL = CC_RES - 1; \ + Int argL, argR, res; \ + res = CC_DEP1; \ + argL = res - 1; \ argR = 1; \ - cf = CC_AUX & CC_MASK_C; \ - pf = parity_table[(UChar)CC_RES]; \ - af = (CC_RES ^ argL ^ argR) & 0x10; \ - zf = ((DATA_UTYPE)CC_RES == 0) << 6; \ - sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \ - of = ((CC_RES & DATA_MASK) == SIGN_MASK) << 11; \ + cf = CC_NDEP & CC_MASK_C; \ + pf = parity_table[(UChar)res]; \ + af = (res ^ argL ^ argR) & 0x10; \ + zf = ((DATA_UTYPE)res == 0) << 6; \ + sf = lshift(res, 8 - DATA_BITS) & 0x80; \ + of = ((res & DATA_MASK) == SIGN_MASK) << 11; \ return cf | pf | af | zf | sf | of; \ } @@ -216,15 +227,16 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ - Int argL, argR; \ - argL = CC_RES + 1; \ + Int argL, argR, res; \ + res = CC_DEP1; \ + argL = res + 1; \ argR = 1; \ - cf = CC_AUX & CC_MASK_C; \ - pf = parity_table[(UChar)CC_RES]; \ - af = (CC_RES ^ argL ^ argR) & 0x10; \ - zf = ((DATA_UTYPE)CC_RES == 0) << 6; \ - sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \ - of = ((CC_RES & DATA_MASK) \ + cf = CC_NDEP & CC_MASK_C; \ + pf = parity_table[(UChar)res]; \ + af = (res ^ argL ^ argR) & 0x10; \ + zf = ((DATA_UTYPE)res == 0) << 6; \ + sf = lshift(res, 8 - DATA_BITS) & 0x80; \ + of = ((res & DATA_MASK) \ == ((UInt)SIGN_MASK - 1)) << 11; \ return cf | pf | af | zf | sf | of; \ } @@ -235,105 +247,105 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ - cf = (CC_AUX >> (DATA_BITS - 1)) & CC_MASK_C; \ - pf = parity_table[(UChar)CC_RES]; \ + cf = (CC_DEP2 >> (DATA_BITS - 1)) & CC_MASK_C; \ + pf = parity_table[(UChar)CC_DEP1]; \ af = 0; /* undefined */ \ - zf = ((DATA_UTYPE)CC_RES == 0) << 6; \ - sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \ + zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ + sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ /* of is defined if shift count == 1 */ \ - of = lshift(CC_AUX ^ CC_RES, 12 - DATA_BITS) & CC_MASK_O; \ + of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } /*-------------------------------------------------------------*/ -#define ACTIONS_SAR(DATA_BITS,DATA_UTYPE) \ +#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE) \ { \ PREAMBLE(DATA_BITS); \ Int cf, pf, af, zf, sf, of; \ - cf = CC_AUX & 1; \ - pf = parity_table[(UChar)CC_RES]; \ + cf = CC_DEP2 & 1; \ + pf = parity_table[(UChar)CC_DEP1]; \ af = 0; /* undefined */ \ - zf = ((DATA_UTYPE)CC_RES == 0) << 6; \ - sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \ + zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ + sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ /* of is defined if shift count == 1 */ \ - of = lshift(CC_AUX ^ CC_RES, 12 - DATA_BITS) & CC_MASK_O; \ + of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } /*-------------------------------------------------------------*/ /* ROL: cf' = lsb(result). of' = msb(result) ^ lsb(result). */ -/* DST = result, SRC = old flags */ +/* DEP1 = result, NDEP = old flags */ #define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \ { \ PREAMBLE(DATA_BITS); \ Int fl \ - = (CC_AUX & ~(CC_MASK_O | CC_MASK_C)) \ - | (CC_MASK_C & CC_RES) \ - | (CC_MASK_O & (lshift(CC_RES, 11-(DATA_BITS-1)) \ - ^ lshift(CC_RES, 11))); \ + = (CC_NDEP & ~(CC_MASK_O | CC_MASK_C)) \ + | (CC_MASK_C & CC_DEP1) \ + | (CC_MASK_O & (lshift(CC_DEP1, 11-(DATA_BITS-1)) \ + ^ lshift(CC_DEP1, 11))); \ return fl; \ } /*-------------------------------------------------------------*/ /* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */ -/* DST = result, SRC = old flags */ +/* DEP1 = result, NDEP = old flags */ #define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \ { \ PREAMBLE(DATA_BITS); \ Int fl \ - = (CC_AUX & ~(CC_MASK_O | CC_MASK_C)) \ - | (CC_MASK_C & (CC_RES >> (DATA_BITS-1))) \ - | (CC_MASK_O & (lshift(CC_RES, 11-(DATA_BITS-1)) \ - ^ lshift(CC_RES, 11-(DATA_BITS-1)+1))); \ + = (CC_NDEP & ~(CC_MASK_O | CC_MASK_C)) \ + | (CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1))) \ + | (CC_MASK_O & (lshift(CC_DEP1, 11-(DATA_BITS-1)) \ + ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1))); \ return fl; \ } /*-------------------------------------------------------------*/ -#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE) \ -{ \ - PREAMBLE(DATA_BITS); \ - Int cf, pf, af, zf, sf, of; \ - DATA_UTYPE resHi = DATA_MASK & (CC_RES ^ CC_AUX); \ - DATA_UTYPE resLo = DATA_MASK & CC_AUX; \ - cf = (resHi != 0); \ - pf = parity_table[(UChar)resLo]; \ - af = 0; /* undefined */ \ - zf = (resLo == 0) << 6; \ - sf = lshift(resLo, 8 - DATA_BITS) & 0x80; \ - of = cf << 11; \ - return cf | pf | af | zf | sf | of; \ +#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + Int cf, pf, af, zf, sf, of; \ + DATA_UTYPE hi; \ + DATA_UTYPE lo = ((DATA_UTYPE)CC_DEP1) \ + * ((DATA_UTYPE)CC_DEP2); \ + DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1)) \ + * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2)); \ + hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS); \ + cf = (hi != 0); \ + pf = parity_table[(UChar)lo]; \ + af = 0; /* undefined */ \ + zf = (lo == 0) << 6; \ + sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ + of = cf << 11; \ + return cf | pf | af | zf | sf | of; \ } /*-------------------------------------------------------------*/ -#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE) \ -{ \ - PREAMBLE(DATA_BITS); \ - Int cf, pf, af, zf, sf, of; \ - DATA_STYPE resHi = DATA_MASK & (CC_RES ^ CC_AUX); \ - DATA_STYPE resLo = DATA_MASK & CC_AUX; \ - cf = (resHi != (resLo >>/*s*/ (DATA_BITS-1))); \ - pf = parity_table[(UChar)resLo]; \ - af = 0; /* undefined */ \ - zf = (resLo == 0) << 6; \ - sf = lshift(resLo, 8 - DATA_BITS) & 0x80; \ - of = cf << 11; \ - return cf | pf | af | zf | sf | of; \ +#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + Int cf, pf, af, zf, sf, of; \ + DATA_STYPE hi; \ + DATA_STYPE lo = ((DATA_STYPE)CC_DEP1) \ + * ((DATA_STYPE)CC_DEP2); \ + DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1)) \ + * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2)); \ + hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS); \ + cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \ + pf = parity_table[(UChar)lo]; \ + af = 0; /* undefined */ \ + zf = (lo == 0) << 6; \ + sf = lshift(lo, 8 - DATA_BITS) & 0x80; \ + of = cf << 11; \ + return cf | pf | af | zf | sf | of; \ } - -#define CC_SHIFT_C 0 -#define CC_SHIFT_P 2 -#define CC_SHIFT_A 4 -#define CC_SHIFT_Z 6 -#define CC_SHIFT_S 7 -#define CC_SHIFT_O 11 - #if PROFILE_EFLAGS static UInt tabc[CC_OP_NUMBER]; @@ -392,14 +404,17 @@ static void initCounts ( void ) /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate all the 6 flags from the supplied thunk parameters. */ -UInt calculate_eflags_all ( UInt cc_op, UInt cc_res_formal, UInt cc_aux_formal ) +UInt calculate_eflags_all ( UInt cc_op, + UInt cc_dep1_formal, + UInt cc_dep2_formal, + UInt cc_ndep_formal ) { # if PROFILE_EFLAGS n_calc_all++; # endif switch (cc_op) { case CC_OP_COPY: - return cc_res_formal + return cc_dep1_formal & (CC_MASK_O | CC_MASK_S | CC_MASK_Z | CC_MASK_A | CC_MASK_C | CC_MASK_P); @@ -435,9 +450,9 @@ UInt calculate_eflags_all ( UInt cc_op, UInt cc_res_formal, UInt cc_aux_formal ) case CC_OP_SHLW: ACTIONS_SHL( 16, UShort ); case CC_OP_SHLL: ACTIONS_SHL( 32, UInt ); - case CC_OP_SARB: ACTIONS_SAR( 8, UChar ); - case CC_OP_SARW: ACTIONS_SAR( 16, UShort ); - case CC_OP_SARL: ACTIONS_SAR( 32, UInt ); + case CC_OP_SHRB: ACTIONS_SHR( 8, UChar ); + case CC_OP_SHRW: ACTIONS_SHR( 16, UShort ); + case CC_OP_SHRL: ACTIONS_SHR( 32, UInt ); case CC_OP_ROLB: ACTIONS_ROL( 8, UChar ); case CC_OP_ROLW: ACTIONS_ROL( 16, UShort ); @@ -447,18 +462,18 @@ UInt calculate_eflags_all ( UInt cc_op, UInt cc_res_formal, UInt cc_aux_formal ) case CC_OP_RORW: ACTIONS_ROR( 16, UShort ); case CC_OP_RORL: ACTIONS_ROR( 32, UInt ); - case CC_OP_UMULB: ACTIONS_UMUL( 8, UChar ); - case CC_OP_UMULW: ACTIONS_UMUL( 16, UShort ); - case CC_OP_UMULL: ACTIONS_UMUL( 32, UInt ); + case CC_OP_UMULB: ACTIONS_UMUL( 8, UChar, UShort ); + case CC_OP_UMULW: ACTIONS_UMUL( 16, UShort, UInt ); + case CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, ULong ); - case CC_OP_SMULB: ACTIONS_SMUL( 8, Char ); - case CC_OP_SMULW: ACTIONS_SMUL( 16, Short ); - case CC_OP_SMULL: ACTIONS_SMUL( 32, Int ); + case CC_OP_SMULB: ACTIONS_SMUL( 8, Char, Short ); + case CC_OP_SMULW: ACTIONS_SMUL( 16, Short, Int ); + case CC_OP_SMULL: ACTIONS_SMUL( 32, Int, Long ); default: /* shouldn't really make these calls from generated code */ - vex_printf("calculate_eflags_all( %d, 0x%x, 0x%x )\n", - cc_op, cc_res_formal, cc_res_formal ); + vex_printf("calculate_eflags_all( %d, 0x%x, 0x%x, 0x%x )\n", + cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal ); vpanic("calculate_eflags_all"); } } @@ -466,7 +481,10 @@ UInt calculate_eflags_all ( UInt cc_op, UInt cc_res_formal, UInt cc_aux_formal ) /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate just the carry flag from the supplied thunk parameters. */ -UInt calculate_eflags_c ( UInt cc_op, UInt cc_res, UInt cc_aux ) +UInt calculate_eflags_c ( UInt cc_op, + UInt cc_dep1, + UInt cc_dep2, + UInt cc_ndep ) { /* Fast-case some common ones. */ switch (cc_op) { @@ -496,16 +514,19 @@ UInt calculate_eflags_c ( UInt cc_op, UInt cc_res, UInt cc_aux ) n_calc_c++; # endif - return calculate_eflags_all(cc_op,cc_res,cc_aux) & CC_MASK_C; + return calculate_eflags_all(cc_op,cc_dep1,cc_dep2,cc_ndep) & CC_MASK_C; } /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* returns 1 or 0 */ /*static*/ UInt calculate_condition ( UInt/*Condcode*/ cond, - UInt cc_op, UInt cc_res, UInt cc_aux ) + UInt cc_op, + UInt cc_dep1, + UInt cc_dep2, + UInt cc_ndep ) { - UInt eflags = calculate_eflags_all(cc_op, cc_res, cc_aux); + UInt eflags = calculate_eflags_all(cc_op, cc_dep1, cc_dep2, cc_ndep); UInt of,sf,zf,cf,pf; UInt inv = cond & 1; @@ -570,8 +591,8 @@ UInt calculate_eflags_c ( UInt cc_op, UInt cc_res, UInt cc_aux ) default: /* shouldn't really make these calls from generated code */ - vex_printf("calculate_condition( %d, %d, 0x%x, 0x%x )\n", - cond, cc_op, cc_res, cc_aux ); + vex_printf("calculate_condition( %d, %d, 0x%x, 0x%x, 0x%x )\n", + cond, cc_op, cc_dep1, cc_dep2, cc_ndep ); vpanic("calculate_condition"); } } @@ -1278,9 +1299,10 @@ void LibVEX_GuestX86_put_eflags ( UInt eflags_native, &= (CC_MASK_C | CC_MASK_P | CC_MASK_A | CC_MASK_Z | CC_MASK_S | CC_MASK_O); - vex_state->guest_CC_OP = CC_OP_COPY; - vex_state->guest_CC_AUX = 0; - vex_state->guest_CC_RES = eflags_native; + vex_state->guest_CC_OP = CC_OP_COPY; + vex_state->guest_CC_DEP1 = eflags_native; + vex_state->guest_CC_DEP2 = 0; + vex_state->guest_CC_NDEP = 0; /* unnecessary paranoia */ } @@ -1289,8 +1311,9 @@ UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state ) { UInt eflags = calculate_eflags_all( vex_state->guest_CC_OP, - vex_state->guest_CC_RES, - vex_state->guest_CC_AUX + vex_state->guest_CC_DEP1, + vex_state->guest_CC_DEP2, + vex_state->guest_CC_NDEP ); UInt dflag = vex_state->guest_DFLAG; vassert(dflag == 1 || dflag == 0xFFFFFFFF); @@ -1316,11 +1339,12 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) vex_state->guest_ESI = 0; vex_state->guest_EDI = 0; - vex_state->guest_CC_OP = CC_OP_COPY; - vex_state->guest_CC_RES = 0; - vex_state->guest_CC_AUX = 0; - vex_state->guest_DFLAG = 1; /* forwards */ - vex_state->guest_IDFLAG = 0; + vex_state->guest_CC_OP = CC_OP_COPY; + vex_state->guest_CC_DEP1 = 0; + vex_state->guest_CC_DEP2 = 0; + vex_state->guest_CC_NDEP = 0; + vex_state->guest_DFLAG = 1; /* forwards */ + vex_state->guest_IDFLAG = 0; vex_state->guest_EIP = 0; @@ -1476,11 +1500,11 @@ VexGuestLayout /* Describe any sections to be regarded by Memcheck as 'always-defined'. */ .n_alwaysDefd = 15, - /* flags thunk: OP and AUX are always defd; only RES isn't. - See detailed comment in gdefs.h on meaning of thunk - fields. */ + /* flags thunk: OP and NDEP are always defd, whereas DEP1 + and DEP2 have to be tracked. See detailed comment in + gdefs.h on meaning of thunk fields. */ .alwaysDefd[0] = ALWAYSDEFD(guest_CC_OP), - .alwaysDefd[1] = ALWAYSDEFD(guest_CC_AUX), + .alwaysDefd[1] = ALWAYSDEFD(guest_CC_NDEP), .alwaysDefd[2] = ALWAYSDEFD(guest_DFLAG), .alwaysDefd[3] = ALWAYSDEFD(guest_IDFLAG), diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index f28d5865c2..1bbf41804f 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -77,21 +77,24 @@ static IRBB* irbb; /*--- Offsets of various parts of the x86 guest state. ---*/ /*------------------------------------------------------------*/ -#define OFFB_FPREGS offsetof(VexGuestX86State,guest_FPREG[0]) -#define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0]) -#define OFFB_EAX offsetof(VexGuestX86State,guest_EAX) -#define OFFB_EBX offsetof(VexGuestX86State,guest_EBX) -#define OFFB_ECX offsetof(VexGuestX86State,guest_ECX) -#define OFFB_EDX offsetof(VexGuestX86State,guest_EDX) -#define OFFB_EIP offsetof(VexGuestX86State,guest_EIP) -#define OFFB_CC_OP offsetof(VexGuestX86State,guest_CC_OP) -#define OFFB_CC_RES offsetof(VexGuestX86State,guest_CC_RES) -#define OFFB_CC_AUX offsetof(VexGuestX86State,guest_CC_AUX) -#define OFFB_DFLAG offsetof(VexGuestX86State,guest_DFLAG) -#define OFFB_IDFLAG offsetof(VexGuestX86State,guest_IDFLAG) -#define OFFB_FTOP offsetof(VexGuestX86State,guest_FTOP) -#define OFFB_FC3210 offsetof(VexGuestX86State,guest_FC3210) -#define OFFB_FPUCW offsetof(VexGuestX86State,guest_FPUCW) +#define OFFB_FPREGS offsetof(VexGuestX86State,guest_FPREG[0]) +#define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0]) +#define OFFB_EAX offsetof(VexGuestX86State,guest_EAX) +#define OFFB_EBX offsetof(VexGuestX86State,guest_EBX) +#define OFFB_ECX offsetof(VexGuestX86State,guest_ECX) +#define OFFB_EDX offsetof(VexGuestX86State,guest_EDX) +#define OFFB_EIP offsetof(VexGuestX86State,guest_EIP) + +#define OFFB_CC_OP offsetof(VexGuestX86State,guest_CC_OP) +#define OFFB_CC_DEP1 offsetof(VexGuestX86State,guest_CC_DEP1) +#define OFFB_CC_DEP2 offsetof(VexGuestX86State,guest_CC_DEP2) +#define OFFB_CC_NDEP offsetof(VexGuestX86State,guest_CC_NDEP) + +#define OFFB_DFLAG offsetof(VexGuestX86State,guest_DFLAG) +#define OFFB_IDFLAG offsetof(VexGuestX86State,guest_IDFLAG) +#define OFFB_FTOP offsetof(VexGuestX86State,guest_FTOP) +#define OFFB_FC3210 offsetof(VexGuestX86State,guest_FC3210) +#define OFFB_FPUCW offsetof(VexGuestX86State,guest_FPUCW) /*------------------------------------------------------------*/ @@ -552,21 +555,6 @@ static IROp mkSizedOp ( IRType ty, IROp op8 ) { Int adj; vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); - - switch (op8) { - case Iop_MullS8: - return ty==Ity_I8 ? Iop_MullS8 - : (ty==Ity_I16 ? Iop_MullS16 : Iop_MullS32); - case Iop_16HIto8: - return ty==Ity_I8 ? Iop_16HIto8 - : (ty==Ity_I16 ? Iop_32HIto16 : Iop_64HIto32); - case Iop_16to8: - return ty==Ity_I8 ? Iop_16to8 - : (ty==Ity_I16 ? Iop_32to16 : Iop_64to32); - default: - break; - } - vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 @@ -591,15 +579,6 @@ static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd ) vpanic("mkWidenOp(x86,guest)"); } -static IRType doubleLengthType ( IRType ty ) -{ - switch (ty) { - case Ity_I8: return Ity_I16; - case Ity_I16: return Ity_I32; - case Ity_I32: return Ity_I64; - default: vpanic("doubleLengthType(x86,guest)"); - } -} /*------------------------------------------------------------*/ /*--- Helpers for %eflags. ---*/ @@ -608,13 +587,15 @@ static IRType doubleLengthType ( IRType ty ) /* -------------- Evaluating the flags-thunk. -------------- */ /* Build IR to calculate all the eflags from stored - CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_I32. */ + CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: + Ity_I32. */ static IRExpr* mk_calculate_eflags_all ( void ) { IRExpr** args - = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32), - IRExpr_Get(OFFB_CC_RES, Ity_I32), - IRExpr_Get(OFFB_CC_AUX, Ity_I32) ); + = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32), + IRExpr_Get(OFFB_CC_DEP1, Ity_I32), + IRExpr_Get(OFFB_CC_DEP2, Ity_I32), + IRExpr_Get(OFFB_CC_NDEP, Ity_I32) ); IRExpr* call = mkIRExprCCall( Ity_I32, @@ -622,21 +603,23 @@ static IRExpr* mk_calculate_eflags_all ( void ) "calculate_eflags_all", &calculate_eflags_all, args ); - /* Exclude OP and AUX from definedness checking. We're only - interested in RES. */ - call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<2); + /* Exclude OP and NDEP from definedness checking. We're only + interested in DEP1 and DEP2. */ + call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3); return call; } /* Build IR to calculate some particular condition from stored - CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_Bit. */ + CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: + Ity_Bit. */ static IRExpr* mk_calculate_condition ( Condcode cond ) { IRExpr** args - = mkIRExprVec_4( mkU32(cond), + = mkIRExprVec_5( mkU32(cond), IRExpr_Get(OFFB_CC_OP, Ity_I32), - IRExpr_Get(OFFB_CC_RES, Ity_I32), - IRExpr_Get(OFFB_CC_AUX, Ity_I32) ); + IRExpr_Get(OFFB_CC_DEP1, Ity_I32), + IRExpr_Get(OFFB_CC_DEP2, Ity_I32), + IRExpr_Get(OFFB_CC_NDEP, Ity_I32) ); IRExpr* call = mkIRExprCCall( Ity_I32, @@ -644,20 +627,21 @@ static IRExpr* mk_calculate_condition ( Condcode cond ) "calculate_condition", &calculate_condition, args ); - /* Exclude the requested condition, OP and AUX from definedness - checking. We're only interested in RES. */ - call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1 << 3); + /* Exclude the requested condition, OP and NDEP from definedness + checking. We're only interested in DEP1 and DEP2. */ + call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4); return unop(Iop_32to1, call); } /* Build IR to calculate just the carry flag from stored - CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_I32. */ + CC_OP/CC_DEP1/CC_DEP2/CC_NDEP. Returns an expression :: Ity_I32. */ static IRExpr* mk_calculate_eflags_c ( void ) { IRExpr** args - = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32), - IRExpr_Get(OFFB_CC_RES, Ity_I32), - IRExpr_Get(OFFB_CC_AUX, Ity_I32) ); + = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP, Ity_I32), + IRExpr_Get(OFFB_CC_DEP1, Ity_I32), + IRExpr_Get(OFFB_CC_DEP2, Ity_I32), + IRExpr_Get(OFFB_CC_NDEP, Ity_I32) ); IRExpr* call = mkIRExprCCall( Ity_I32, @@ -665,9 +649,9 @@ static IRExpr* mk_calculate_eflags_c ( void ) "calculate_eflags_c", &calculate_eflags_c, args ); - /* Exclude OP and AUX from definedness checking. We're only - interested in RES. */ - call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<2); + /* Exclude OP and NDEP from definedness checking. We're only + interested in DEP1 and DEP2. */ + call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3); return call; } @@ -683,6 +667,11 @@ static Bool isAddSub ( IROp op8 ) return op8 == Iop_Add8 || op8 == Iop_Sub8; } +static Bool isLogic ( IROp op8 ) +{ + return op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8; +} + /* U-widen 8/16/32 bit int expr to 32. */ static IRExpr* widenUto32 ( IRExpr* e ) { @@ -726,13 +715,11 @@ static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e ) } -/* Set the flags thunk for add/sub operations.. The supplied op is +/* Set the flags thunk OP, DEP1 and DEP2 fields. The supplied op is auto-sized up to the real op. */ -static void setFlags_RES_AUX ( IROp op8, - IRTemp res, - IRTemp aux, - IRType ty ) +static +void setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty ) { Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2); @@ -742,20 +729,18 @@ static void setFlags_RES_AUX ( IROp op8, case Iop_Add8: ccOp += CC_OP_ADDB; break; case Iop_Sub8: ccOp += CC_OP_SUBB; break; default: ppIROp(op8); - vpanic("setFlags_RES_AUX(x86)"); + vpanic("setFlags_DEP1_DEP2(x86)"); } - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); - stmt( IRStmt_Put( OFFB_CC_RES, widenUto32(mkexpr(res))) ); - stmt( IRStmt_Put( OFFB_CC_AUX, widenUto32(mkexpr(aux))) ); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) ); + stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(dep2))) ); } -/* For and/or/xor, only the result is important. However, put zero in - CC_AUX since we're paranoid. */ +/* Set the OP and DEP1 fields only, and write zero to DEP2. */ -static void setFlags_LOGIC ( IROp op8, - IRTemp res, - IRType ty ) +static +void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty ) { Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2); @@ -766,11 +751,11 @@ static void setFlags_LOGIC ( IROp op8, case Iop_And8: case Iop_Xor8: ccOp += CC_OP_LOGICB; break; default: ppIROp(op8); - vpanic("setFlags_LOGIC(x86)"); + vpanic("setFlags_DEP1(x86)"); } - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); - stmt( IRStmt_Put( OFFB_CC_RES, widenUto32(mkexpr(res))) ); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0)) ); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) ); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) ); } @@ -778,42 +763,44 @@ static void setFlags_LOGIC ( IROp op8, result. Except if the shift amount is zero, the thunk is left unchanged. */ -static void setFlags_RES_RESus ( IROp op32, - IRTemp res, - IRTemp resUS, - IRType ty, - IRTemp guard ) +static void setFlags_DEP1_DEP2_shift ( IROp op32, + IRTemp res, + IRTemp resUS, + IRType ty, + IRTemp guard ) { Int ccOp = ty==Ity_I8 ? 2 : (ty==Ity_I16 ? 1 : 0); vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); vassert(guard); + /* Both kinds of right shifts are handled by the same thunk + operation. */ switch (op32) { case Iop_Shr32: - case Iop_Sar32: ccOp = CC_OP_SARL - ccOp; break; + case Iop_Sar32: ccOp = CC_OP_SHRL - ccOp; break; case Iop_Shl32: ccOp = CC_OP_SHLL - ccOp; break; default: ppIROp(op32); - vpanic("setFlags_RES_RESus(x86)"); + vpanic("setFlags_DEP1_DEP2_shift(x86)"); } - /* RES contains the result, AUX contains the undershifted value. */ + /* DEP1 contains the result, DEP2 contains the undershifted value. */ stmt( IRStmt_Put( OFFB_CC_OP, IRExpr_Mux0X( mkexpr(guard), IRExpr_Get(OFFB_CC_OP,Ity_I32), mkU32(ccOp))) ); - stmt( IRStmt_Put( OFFB_CC_RES, + stmt( IRStmt_Put( OFFB_CC_DEP1, IRExpr_Mux0X( mkexpr(guard), - IRExpr_Get(OFFB_CC_RES,Ity_I32), + IRExpr_Get(OFFB_CC_DEP1,Ity_I32), widenUto32(mkexpr(res)))) ); - stmt( IRStmt_Put( OFFB_CC_AUX, + stmt( IRStmt_Put( OFFB_CC_DEP2, IRExpr_Mux0X( mkexpr(guard), - IRExpr_Get(OFFB_CC_AUX,Ity_I32), + IRExpr_Get(OFFB_CC_DEP2,Ity_I32), widenUto32(mkexpr(resUS)))) ); } -/* For the inc/dec case, we store in RES the result value and in AUX +/* For the inc/dec case, we store in DEP1 the result value and in NDEP the former value of the carry flag, which unfortunately we have to compute. */ @@ -825,44 +812,35 @@ static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty ) vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); /* This has to come first, because calculating the C flag - may require reading all three OFFB_CC fields. */ - stmt( IRStmt_Put( OFFB_CC_AUX, mk_calculate_eflags_c()) ); - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); - stmt( IRStmt_Put( OFFB_CC_RES, mkexpr(res)) ); + may require reading all four thunk fields. */ + stmt( IRStmt_Put( OFFB_CC_NDEP, mk_calculate_eflags_c()) ); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(res)) ); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) ); } -/* For multiplies, RES is the xor of the upper and lower halves of the - result, and AUX is the lower half. See long comment in gdefs.h for - explanation of the weirdness involving Xor. */ +/* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the + two arguments. */ static -void setFlags_MUL ( IRType ty, IRTemp resHi, IRTemp resLo, UInt base_op ) +void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, UInt base_op ) { switch (ty) { - case Ity_I8: - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) ); - stmt( IRStmt_Put( OFFB_CC_AUX, unop(Iop_8Uto32,mkexpr(resLo)) ) ); - stmt( IRStmt_Put( OFFB_CC_RES, - unop(Iop_8Uto32, - binop(Iop_Xor8, mkexpr(resHi), mkexpr(resLo))) )); - break; - case Ity_I16: - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) ); - stmt( IRStmt_Put( OFFB_CC_AUX, unop(Iop_16Uto32,mkexpr(resLo)) ) ); - stmt( IRStmt_Put( OFFB_CC_RES, - unop(Iop_16Uto32, - binop(Iop_Xor16, mkexpr(resHi), mkexpr(resLo))) )); - break; - case Ity_I32: - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) ); - stmt( IRStmt_Put( OFFB_CC_AUX, mkexpr(resLo) ) ); - stmt( IRStmt_Put( OFFB_CC_RES, - binop(Iop_Xor32, mkexpr(resHi), mkexpr(resLo)) )); - break; - default: - vpanic("setFlags_MUL(x86)"); + case Ity_I8: + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) ); + break; + case Ity_I16: + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) ); + break; + case Ity_I32: + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) ); + break; + default: + vpanic("setFlags_MUL(x86)"); } + stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) )); } @@ -911,80 +889,70 @@ static Condcode positiveIse_Condcode ( Condcode cond, /* -------------- Helpers for ADD/SUB with carry. -------------- */ /* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags - appropriately. Depends critically on the relative ordering of - CC_OP_ADD{B,W,L} vs CC_OP_ADC{B,W,L}. + appropriately. */ static void helper_ADC ( Int sz, IRTemp tres, IRTemp ta1, IRTemp ta2 ) { UInt thunkOp; - IRExpr* thunkExpr; - IRType ty = szToITy(sz); - IRTemp oldc = newTemp(Ity_I32); - IROp plus = mkSizedOp(ty,Iop_Add8); + IRType ty = szToITy(sz); + IRTemp oldc = newTemp(Ity_I32); + IRTemp oldcn = newTemp(ty); + IROp plus = mkSizedOp(ty, Iop_Add8); + IROp xor = mkSizedOp(ty, Iop_Xor8); + + vassert(sz == 1 || sz == 2 || sz == 4); + thunkOp = sz==4 ? CC_OP_ADCL : (sz==2 ? CC_OP_ADCW : CC_OP_ADCB); /* oldc = old carry flag, 0 or 1 */ - assign( oldc, binop(Iop_And32, - mk_calculate_eflags_c(), - mkU32(1)) ); + assign( oldc, binop(Iop_And32, + mk_calculate_eflags_c(), + mkU32(1)) ); - assign(tres, binop(plus, - binop(plus,mkexpr(ta1),mkexpr(ta2)), - narrowTo(ty,mkexpr(oldc)))); + assign( oldcn, narrowTo(ty, mkexpr(oldc)) ); - vassert(sz == 1 || sz == 2 || sz == 4); - thunkOp = sz==4 ? CC_OP_ADDL : (sz==2 ? CC_OP_ADDW : CC_OP_ADDB); - - /* This dynamically calculates the thunk op number. - 3 * the old carry flag is added, so (eg) it gives - CC_OP_ADDL if old carry was zero, and CC_OP_ADCL if - old carry was one. */ - thunkExpr = binop(Iop_Add32, - mkU32(thunkOp), - binop(Iop_Mul32, mkexpr(oldc), mkU32(3))); - - stmt( IRStmt_Put( OFFB_CC_OP, thunkExpr ) ); - stmt( IRStmt_Put( OFFB_CC_RES, mkexpr(tres) ) ); - stmt( IRStmt_Put( OFFB_CC_AUX, mkexpr(ta2) ) ); + assign( tres, binop(plus, + binop(plus,mkexpr(ta1),mkexpr(ta2)), + mkexpr(oldcn)) ); + + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(thunkOp) ) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(ta1) ) ); + stmt( IRStmt_Put( OFFB_CC_DEP2, binop(xor, mkexpr(ta2), mkexpr(oldcn)) ) ); + stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) ); } /* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags - appropriately. Depends critically on the relative ordering of - CC_OP_SUB{B,W,L} vs CC_OP_SBB{B,W,L}. + appropriately. */ static void helper_SBB ( Int sz, IRTemp tres, IRTemp ta1, IRTemp ta2 ) { UInt thunkOp; - IRExpr* thunkExpr; - IRType ty = szToITy(sz); - IRTemp oldc = newTemp(Ity_I32); - IROp minus = mkSizedOp(ty,Iop_Sub8); + IRType ty = szToITy(sz); + IRTemp oldc = newTemp(Ity_I32); + IRTemp oldcn = newTemp(ty); + IROp minus = mkSizedOp(ty, Iop_Sub8); + IROp xor = mkSizedOp(ty, Iop_Xor8); + + vassert(sz == 1 || sz == 2 || sz == 4); + thunkOp = sz==4 ? CC_OP_SBBL : (sz==2 ? CC_OP_SBBW : CC_OP_SBBB); /* oldc = old carry flag, 0 or 1 */ assign( oldc, binop(Iop_And32, mk_calculate_eflags_c(), mkU32(1)) ); - assign(tres, binop(minus, - binop(minus,mkexpr(ta1),mkexpr(ta2)), - narrowTo(ty,mkexpr(oldc)))); + assign( oldcn, narrowTo(ty, mkexpr(oldc)) ); - vassert(sz == 1 || sz == 2 || sz == 4); - thunkOp = sz==4 ? CC_OP_SUBL : (sz==2 ? CC_OP_SUBW : CC_OP_SUBB); - - /* This dynamically calculates the thunk op number. - 3 * the old carry flag is added, so (eg) it gives - CC_OP_SUBL if old carry was zero, and CC_OP_SBBL if - old carry was one. */ - thunkExpr = binop(Iop_Add32, - mkU32(thunkOp), - binop(Iop_Mul32, mkexpr(oldc), mkU32(3))); - - stmt( IRStmt_Put( OFFB_CC_OP, thunkExpr ) ); - stmt( IRStmt_Put( OFFB_CC_RES, mkexpr(tres) ) ); - stmt( IRStmt_Put( OFFB_CC_AUX, mkexpr(ta2) ) ); + assign( tres, binop(minus, + binop(minus,mkexpr(ta1),mkexpr(ta2)), + mkexpr(oldcn)) ); + + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(thunkOp) ) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(ta1) ) ); + stmt( IRStmt_Put( OFFB_CC_DEP2, binop(xor, mkexpr(ta2), mkexpr(oldcn)) ) ); + stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) ); } @@ -1801,9 +1769,9 @@ void codegen_XOR_reg_with_itself ( Int size, Int ge_reg ) /* reg := 0 */ putIReg(size, ge_reg, mkU(ty,0)); /* Flags: C,A,O=0, Z=1, S=0, P=1 */ - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_RES, mkU32(CC_MASK_Z|CC_MASK_P) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP1, mkU32(CC_MASK_Z|CC_MASK_P) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); DIP("xor%c %s, %s\n", nameISize(size), nameIReg(size,ge_reg), nameIReg(size,ge_reg) ); } @@ -1884,9 +1852,9 @@ UInt dis_op2_E_G ( UChar sorb, } else { assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + setFlags_DEP1(op8, dst1, ty); if (keep) putIReg(size, gregOfRM(rm), mkexpr(dst1)); } @@ -1911,9 +1879,9 @@ UInt dis_op2_E_G ( UChar sorb, } else { assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + setFlags_DEP1(op8, dst1, ty); if (keep) putIReg(size, gregOfRM(rm), mkexpr(dst1)); } @@ -1992,9 +1960,9 @@ UInt dis_op2_G_E ( UChar sorb, } else { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src))); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + setFlags_DEP1(op8, dst1, ty); if (keep) putIReg(size, eregOfRM(rm), mkexpr(dst1)); } @@ -2021,9 +1989,9 @@ UInt dis_op2_G_E ( UChar sorb, } else { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src))); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + setFlags_DEP1(op8, dst1, ty); if (keep) storeLE(mkexpr(addr), mkexpr(dst1)); } @@ -2140,9 +2108,12 @@ UInt dis_op_imm_A ( Int size, assign(src, mkU(ty,lit)); assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + if (isLogic(op8)) + setFlags_DEP1(op8, dst1, ty); + else + vpanic("dis_op_imm_A(x86,guest)"); if (keep) putIReg(size, R_EAX, mkexpr(dst1)); @@ -2318,9 +2289,9 @@ UInt dis_Grp1 ( UChar sorb, } else { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src))); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + setFlags_DEP1(op8, dst1, ty); } if (gregOfRM(modrm) < 7) @@ -2343,9 +2314,9 @@ UInt dis_Grp1 ( UChar sorb, } else { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src))); if (isAddSub(op8)) - setFlags_RES_AUX(op8, dst1, src, ty); + setFlags_DEP1_DEP2(op8, dst0, src, ty); else - setFlags_LOGIC(op8, dst1, ty); + setFlags_DEP1(op8, dst1, ty); } if (gregOfRM(modrm) < 7) @@ -2420,9 +2391,9 @@ UInt dis_Grp2 ( UChar sorb, ); /* new eflags in hi half r64; new value in lo half r64 */ assign( dst1, narrowTo(ty, unop(Iop_64to32, mkexpr(r64))) ); - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_RES, unop(Iop_64HIto32, mkexpr(r64)) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP1, unop(Iop_64HIto32, mkexpr(r64)) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); } if (isShift) { @@ -2470,7 +2441,7 @@ UInt dis_Grp2 ( UChar sorb, mkU8(31))) ); /* Build the flags thunk. */ - setFlags_RES_RESus(op32, res32, res32ss, ty, shift_amt); + setFlags_DEP1_DEP2_shift(op32, res32, res32ss, ty, shift_amt); /* Narrow the result back down. */ assign( dst1, narrowTo(ty, mkexpr(res32)) ); @@ -2538,18 +2509,22 @@ UInt dis_Grp2 ( UChar sorb, assign(oldFlags, mk_calculate_eflags_all()); - /* CC_RES is the rotated value. CC_AUX is flags before. */ + /* CC_DEP1 is the rotated value. CC_NDEP is flags before. */ stmt( IRStmt_Put( OFFB_CC_OP, IRExpr_Mux0X( mkexpr(rot_amt32), IRExpr_Get(OFFB_CC_OP,Ity_I32), mkU32(ccOp))) ); - stmt( IRStmt_Put( OFFB_CC_RES, + stmt( IRStmt_Put( OFFB_CC_DEP1, IRExpr_Mux0X( mkexpr(rot_amt32), - IRExpr_Get(OFFB_CC_RES,Ity_I32), + IRExpr_Get(OFFB_CC_DEP1,Ity_I32), widenUto32(mkexpr(dst1)))) ); - stmt( IRStmt_Put( OFFB_CC_AUX, + stmt( IRStmt_Put( OFFB_CC_DEP2, + IRExpr_Mux0X( mkexpr(rot_amt32), + IRExpr_Get(OFFB_CC_DEP2,Ity_I32), + mkU32(0))) ); + stmt( IRStmt_Put( OFFB_CC_NDEP, IRExpr_Mux0X( mkexpr(rot_amt32), - IRExpr_Get(OFFB_CC_AUX,Ity_I32), + IRExpr_Get(OFFB_CC_NDEP,Ity_I32), mkexpr(oldFlags))) ); } /* if (isRotate) */ @@ -2713,10 +2688,10 @@ static void codegen_mulL_A_D ( Int sz, Bool syned, IRTemp resLo = newTemp(Ity_I32); IROp mulOp = syned ? Iop_MullS32 : Iop_MullU32; UInt tBaseOp = syned ? CC_OP_SMULB : CC_OP_UMULB; + setFlags_MUL ( Ity_I32, t1, tmp, tBaseOp ); assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) ); assign( resHi, unop(Iop_64HIto32,mkexpr(res64))); assign( resLo, unop(Iop_64to32,mkexpr(res64))); - setFlags_MUL ( Ity_I32, resHi, resLo, tBaseOp ); putIReg(4, R_EDX, mkexpr(resHi)); putIReg(4, R_EAX, mkexpr(resLo)); break; @@ -2727,10 +2702,10 @@ static void codegen_mulL_A_D ( Int sz, Bool syned, IRTemp resLo = newTemp(Ity_I16); IROp mulOp = syned ? Iop_MullS16 : Iop_MullU16; UInt tBaseOp = syned ? CC_OP_SMULB : CC_OP_UMULB; + setFlags_MUL ( Ity_I16, t1, tmp, tBaseOp ); assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) ); assign( resHi, unop(Iop_32HIto16,mkexpr(res32))); assign( resLo, unop(Iop_32to16,mkexpr(res32))); - setFlags_MUL ( Ity_I16, resHi, resLo, tBaseOp ); putIReg(2, R_EDX, mkexpr(resHi)); putIReg(2, R_EAX, mkexpr(resLo)); break; @@ -2741,10 +2716,10 @@ static void codegen_mulL_A_D ( Int sz, Bool syned, IRTemp resLo = newTemp(Ity_I8); IROp mulOp = syned ? Iop_MullS8 : Iop_MullU8; UInt tBaseOp = syned ? CC_OP_SMULB : CC_OP_UMULB; + setFlags_MUL ( Ity_I8, t1, tmp, tBaseOp ); assign( res16, binop(mulOp, mkexpr(t1), mkexpr(tmp)) ); assign( resHi, unop(Iop_16HIto8,mkexpr(res16))); assign( resLo, unop(Iop_16to8,mkexpr(res16))); - setFlags_MUL ( Ity_I8, resHi, resLo, tBaseOp ); putIReg(2, R_EAX, mkexpr(res16)); break; } @@ -2777,7 +2752,7 @@ UInt dis_Grp3 ( UChar sorb, Int sz, UInt delta ) assign(dst1, binop(mkSizedOp(ty,Iop_And8), getIReg(sz,eregOfRM(modrm)), mkU(ty,d32))); - setFlags_LOGIC( Iop_And8, dst1, ty ); + setFlags_DEP1( Iop_And8, dst1, ty ); DIP("test%c $0x%x, %s\n", nameISize(sz), d32, nameIReg(sz, eregOfRM(modrm))); break; @@ -2797,7 +2772,7 @@ UInt dis_Grp3 ( UChar sorb, Int sz, UInt delta ) assign(dst0, mkU(ty,0)); assign(src, getIReg(sz,eregOfRM(modrm))); assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src))); - setFlags_RES_AUX(Iop_Sub8, dst1, src, ty); + setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty); putIReg(sz, eregOfRM(modrm), mkexpr(dst1)); DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm))); break; @@ -2841,7 +2816,7 @@ UInt dis_Grp3 ( UChar sorb, Int sz, UInt delta ) dst1 = newTemp(ty); assign(dst1, binop(mkSizedOp(ty,Iop_And8), mkexpr(t1), mkU(ty,d32))); - setFlags_LOGIC( Iop_And8, dst1, ty ); + setFlags_DEP1( Iop_And8, dst1, ty ); DIP("test%c $0x%x, %s\n", nameISize(sz), d32, dis_buf); break; } @@ -2857,7 +2832,7 @@ UInt dis_Grp3 ( UChar sorb, Int sz, UInt delta ) assign(dst0, mkU(ty,0)); assign(src, mkexpr(t1)); assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src))); - setFlags_RES_AUX(Iop_Sub8, dst1, src, ty); + setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty); storeLE( mkexpr(addr), mkexpr(dst1) ); DIP("neg%c %s\n", nameISize(sz), dis_buf); break; @@ -3139,7 +3114,7 @@ void dis_CMPS ( Int sz, IRTemp t_inc ) IRType ty = szToITy(sz); IRTemp tdv = newTemp(ty); /* (EDI) */ IRTemp tsv = newTemp(ty); /* (ESI) */ - IRTemp res = newTemp(ty); + //IRTemp res = newTemp(ty); IRTemp td = newTemp(Ity_I32); /* EDI */ IRTemp ts = newTemp(Ity_I32); /* ESI */ @@ -3157,8 +3132,8 @@ void dis_CMPS ( Int sz, IRTemp t_inc ) //uInstr2(cb, SUB, sz, TempReg, tdv, TempReg, tsv); //setFlagsFromUOpcode(cb, SUB); - assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(tsv), mkexpr(tdv)) ); - setFlags_RES_AUX ( Iop_Sub8, res, tdv, ty ); + //assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(tsv), mkexpr(tdv)) ); + setFlags_DEP1_DEP2 ( Iop_Sub8, tsv, tdv, ty ); //uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td); //uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, ts); @@ -3177,7 +3152,7 @@ void dis_SCAS ( Int sz, IRTemp t_inc ) IRTemp ta = newTemp(ty); /* EAX */ IRTemp td = newTemp(Ity_I32); /* EDI */ IRTemp tdv = newTemp(ty); /* (EDI) */ - IRTemp res = newTemp(ty); + //IRTemp res = newTemp(ty); //uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta); assign( ta, getIReg(sz, R_EAX) ); @@ -3190,8 +3165,8 @@ void dis_SCAS ( Int sz, IRTemp t_inc ) //uInstr2(cb, SUB, sz, TempReg, tdv, TempReg, ta); //setFlagsFromUOpcode(cb, SUB); - assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(ta), mkexpr(tdv)) ); - setFlags_RES_AUX ( Iop_Sub8, res, tdv, ty ); + //assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(ta), mkexpr(tdv)) ); + setFlags_DEP1_DEP2 ( Iop_Sub8, ta, tdv, ty ); //uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td); //uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI); @@ -3239,12 +3214,11 @@ void dis_REP_op ( Condcode cond, /*--- Arithmetic, etc. ---*/ /*------------------------------------------------------------*/ -/* (I)MUL E, G. Supplied eip points to the modR/M byte. */ +/* IMUL E, G. Supplied eip points to the modR/M byte. */ static UInt dis_mul_E_G ( UChar sorb, Int size, - UInt delta0, - Bool syned ) + UInt delta0 ) { Int alen; UChar dis_buf[50]; @@ -3252,11 +3226,7 @@ UInt dis_mul_E_G ( UChar sorb, IRType ty = szToITy(size); IRTemp te = newTemp(ty); IRTemp tg = newTemp(ty); - IRTemp resHi = newTemp(ty); IRTemp resLo = newTemp(ty); - IRTemp res2L = newTemp(doubleLengthType(ty)); - - vassert(syned); assign( tg, getIReg(size, gregOfRM(rm)) ); if (epartIsReg(rm)) { @@ -3266,25 +3236,20 @@ UInt dis_mul_E_G ( UChar sorb, assign( te, loadLE(ty,mkexpr(addr)) ); } - assign( res2L, binop( mkSizedOp(ty, syned ? Iop_MullS8 : Iop_MullU8), - mkexpr(te), mkexpr(tg) )); - assign( resHi, unop( mkSizedOp(ty, Iop_16HIto8), mkexpr(res2L) )); - assign( resLo, unop( mkSizedOp(ty, Iop_16to8), mkexpr(res2L) )); + setFlags_MUL ( ty, te, tg, CC_OP_SMULB ); - setFlags_MUL ( ty, resHi, resLo, syned ? CC_OP_SMULB : CC_OP_UMULB ); + assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tg) ) ); putIReg(size, gregOfRM(rm), mkexpr(resLo) ); if (epartIsReg(rm)) { - DIP("%smul%c %s, %s\n", syned ? "i" : "", - nameISize(size), - nameIReg(size,eregOfRM(rm)), - nameIReg(size,gregOfRM(rm))); + DIP("imul%c %s, %s\n", nameISize(size), + nameIReg(size,eregOfRM(rm)), + nameIReg(size,gregOfRM(rm))); return 1+delta0; } else { - DIP("%smul%c %s, %s\n", syned ? "i" : "", - nameISize(size), - dis_buf, nameIReg(size,gregOfRM(rm))); + DIP("imul%c %s, %s\n", nameISize(size), + dis_buf, nameIReg(size,gregOfRM(rm))); return alen+delta0; } } @@ -3303,9 +3268,7 @@ UInt dis_imul_I_E_G ( UChar sorb, IRType ty = szToITy(size); IRTemp te = newTemp(ty); IRTemp tl = newTemp(ty); - IRTemp resHi = newTemp(ty); IRTemp resLo = newTemp(ty); - IRTemp res2L = newTemp(doubleLengthType(ty)); vassert(size == 1 || size == 2 || size == 4); @@ -3325,12 +3288,9 @@ UInt dis_imul_I_E_G ( UChar sorb, assign(tl, mkU(ty,d32)); - assign( res2L, binop( mkSizedOp(ty, Iop_MullS8), - mkexpr(te), mkexpr(tl) )); - assign( resHi, unop( mkSizedOp(ty, Iop_16HIto8), mkexpr(res2L) )); - assign( resLo, unop( mkSizedOp(ty, Iop_16to8), mkexpr(res2L) )); + assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tl) )); - setFlags_MUL ( ty, resHi, resLo, CC_OP_SMULB ); + setFlags_MUL ( ty, te, tl, CC_OP_SMULB ); putIReg(size, gregOfRM(rm), mkexpr(resLo)); @@ -3607,9 +3567,9 @@ static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after ) Z,P,C,O correctly, but forces A and S to zero, whereas the Intel documentation implies A and S are unchanged. */ - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); - stmt( IRStmt_Put( OFFB_CC_RES, + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); + stmt( IRStmt_Put( OFFB_CC_DEP1, binop( Iop_And32, binop(Iop_CmpF64, get_ST(0), get_ST(i)), mkU32(0x45) @@ -4970,8 +4930,8 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb, binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ), mask))) ); - setFlags_RES_RESus ( left_shift ? Iop_Shl32 : Iop_Sar32, - tmpRes, tmpSubSh, ty, tmpSH ); + setFlags_DEP1_DEP2_shift ( left_shift ? Iop_Shl32 : Iop_Sar32, + tmpRes, tmpSubSh, ty, tmpSH ); /* Put result back. */ @@ -5103,11 +5063,11 @@ UInt dis_bt_G_E ( UChar sorb, Int sz, UInt delta, BtOp op ) } /* Side effect done; now get selected bit into Carry flag */ - /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */ - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); + /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */ + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); stmt( IRStmt_Put( - OFFB_CC_RES, + OFFB_CC_DEP1, binop(Iop_And32, binop(Iop_Shr32, unop(Iop_8Uto32, mkexpr(t_fetched)), @@ -5175,10 +5135,10 @@ UInt dis_bs_E_G ( UChar sorb, Int sz, UInt delta, Bool fwds ) /* Flags: Z is 1 iff source value is zero. All others are undefined -- we force them to zero. */ - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); stmt( IRStmt_Put( - OFFB_CC_RES, + OFFB_CC_DEP1, IRExpr_Mux0X( mkexpr(src8), /* src==0 */ mkU32(CC_MASK_Z), @@ -5259,12 +5219,12 @@ void codegen_SAHF ( void ) (calculate_flags_all() & CC_MASK_O) -- retain the old O flag | (%AH & (CC_MASK_S|CC_MASK_Z|CC_MASK_A|CC_MASK_P|CC_MASK_C) */ - UInt mask_SZACP = CC_MASK_S|CC_MASK_Z|CC_MASK_A|CC_MASK_P|CC_MASK_C; + UInt mask_SZACP = CC_MASK_S|CC_MASK_Z|CC_MASK_A|CC_MASK_C|CC_MASK_P; IRTemp oldflags = newTemp(Ity_I32); assign( oldflags, mk_calculate_eflags_all() ); - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); - stmt( IRStmt_Put( OFFB_CC_RES, + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); + stmt( IRStmt_Put( OFFB_CC_DEP1, binop(Iop_Or32, binop(Iop_And32, mkexpr(oldflags), mkU32(CC_MASK_O)), binop(Iop_And32, @@ -5307,7 +5267,7 @@ UInt dis_cmpxchg_G_E ( UChar sorb, IRType ty = szToITy(size); IRTemp acc = newTemp(ty); IRTemp src = newTemp(ty); - IRTemp res = newTemp(ty); + //IRTemp res = newTemp(ty); IRTemp dest = newTemp(ty); IRTemp dest2 = newTemp(ty); IRTemp acc2 = newTemp(ty); @@ -5331,8 +5291,8 @@ UInt dis_cmpxchg_G_E ( UChar sorb, assign( src, getIReg(size, gregOfRM(rm)) ); assign( acc, getIReg(size, R_EAX) ); - assign( res, binop( mkSizedOp(ty,Iop_Sub8), mkexpr(acc), mkexpr(dest) )); - setFlags_RES_AUX(Iop_Sub8, res, dest, ty); + //assign( res, binop( mkSizedOp(ty,Iop_Sub8), mkexpr(acc), mkexpr(dest) )); + setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty); assign( cond8, unop(Iop_1Uto8, mk_calculate_condition(CondZ)) ); assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) ); assign( acc2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) ); @@ -5517,7 +5477,7 @@ UInt dis_xadd_G_E ( UChar sorb, Int sz, UInt delta0 ) assign( tmpd, loadLE(ty, mkexpr(addr)) ); assign( tmpt0, getIReg(sz, gregOfRM(rm)) ); assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8), mkexpr(tmpd), mkexpr(tmpt0)) ); - setFlags_RES_AUX( Iop_Add8, tmpt1, tmpt0, ty ); + setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty ); storeLE( mkexpr(addr), mkexpr(tmpt1) ); putIReg(sz, gregOfRM(rm), mkexpr(tmpd)); DIP("xadd%c %s, %s\n", @@ -8312,9 +8272,9 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz))); /* t1 is the flag word. Mask out everything except OSZACP and set the flags thunk to CC_OP_COPY. */ - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); - stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) )); - stmt( IRStmt_Put( OFFB_CC_RES, + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) )); + stmt( IRStmt_Put( OFFB_CC_DEP1, binop(Iop_And32, mkexpr(t1), mkU32( CC_MASK_C | CC_MASK_P | CC_MASK_A @@ -9175,7 +9135,7 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */ case 0xAF: /* IMUL Ev, Gv */ - delta = dis_mul_E_G ( sorb, sz, delta, True ); + delta = dis_mul_E_G ( sorb, sz, delta ); break; /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */ diff --git a/VEX/pub/libvex_guest_x86.h b/VEX/pub/libvex_guest_x86.h index 43f98218fd..a80eebfc5c 100644 --- a/VEX/pub/libvex_guest_x86.h +++ b/VEX/pub/libvex_guest_x86.h @@ -81,11 +81,12 @@ typedef UInt guest_EBP; UInt guest_ESI; UInt guest_EDI; - /* 3-word thunk used to calculate O S Z A C P flags. */ + /* 4-word thunk used to calculate O S Z A C P flags. */ UInt guest_CC_OP; - UInt guest_CC_RES; - UInt guest_CC_AUX; - /* The D flag is stored here, as either -1 or +1 */ + UInt guest_CC_DEP1; + UInt guest_CC_DEP2; + UInt guest_CC_NDEP; + /* The D flag is stored here, encoded as either -1 or +1 */ UInt guest_DFLAG; /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */ UInt guest_IDFLAG; @@ -105,7 +106,7 @@ typedef UShort guest_GS; UShort guest_SS; /* Padding to make it have an 8-aligned size */ - /* UInt padding; */ + UInt padding; } VexGuestX86State;