From: Julian Seward Date: Mon, 7 Feb 2005 18:55:29 +0000 (+0000) Subject: Make rflag-thunk evaluation work (ghelpers); fix various missing cases X-Git-Tag: svn/VALGRIND_3_0_1^2~468 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8264d18514c6d960c8d3144b5de3aff81db7d697;p=thirdparty%2Fvalgrind.git Make rflag-thunk evaluation work (ghelpers); fix various missing cases (toIR, isel). git-svn-id: svn://svn.valgrind.org/vex/trunk@866 --- diff --git a/VEX/priv/guest-amd64/ghelpers.c b/VEX/priv/guest-amd64/ghelpers.c index 4d32ec0716..b5ff928f56 100644 --- a/VEX/priv/guest-amd64/ghelpers.c +++ b/VEX/priv/guest-amd64/ghelpers.c @@ -43,42 +43,1068 @@ #include "guest-amd64/gdefs.h" -ULong amd64g_calculate_rflags_all ( - ULong cc_op, - ULong cc_dep1, ULong cc_dep2, ULong cc_ndep - ) + +/* This file contains helper functions for amd64 guest code. + Calls to these functions are generated by the back end. + These calls are of course in the host machine code and + this file will be compiled to host machine code, so that + all makes sense. + + Only change the signatures of these helper functions very + carefully. If you change the signature here, you'll have to change + the parameters passed to it in the IR calls constructed by + guest-amd64/toIR.c. + + The convention used is that all functions called from generated + code are named amd64g_, and any function whose name lacks + that prefix is not called from generated code. Note that some + LibVEX_* functions can however be called by VEX's client, but that + is not the same as calling them from VEX-generated code. +*/ + + +/* Set to 1 to get detailed profiling info about use of the flag + machinery. */ +#define PROFILE_RFLAGS 0 + + +/*---------------------------------------------------------------*/ +/*--- %rflags run-time helpers. ---*/ +/*---------------------------------------------------------------*/ + +static const UChar parity_table[256] = { + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, + 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, +}; + +/* n must be a constant to be efficient */ +inline static Long lshift ( Long x, Int n ) +{ + if (n >= 0) + return x << n; + else + return x >> (-n); +} + + +#define PREAMBLE(__data_bits) \ + /* const */ ULong DATA_MASK \ + = __data_bits==8 \ + ? 0xFFULL \ + : (__data_bits==16 \ + ? 0xFFFFULL \ + : (__data_bits==32 \ + ? 0xFFFFFFFFULL \ + : 0xFFFFFFFFFFFFFFFFULL)); \ + /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1); \ + /* const */ ULong CC_DEP1 = cc_dep1_formal; \ + /* const */ ULong CC_DEP2 = cc_dep2_formal; \ + /* const */ ULong 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_DEP2 = CC_DEP2; \ + CC_NDEP = CC_NDEP; + + +/*-------------------------------------------------------------*/ + +#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + Long argL, argR, 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; \ + zf = ((DATA_UTYPE)res == 0) << 6; \ + sf = lshift(res, 8 - DATA_BITS) & 0x80; \ + of = lshift((argL ^ argR ^ -1) & (argL ^ res), \ + 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + Long argL, argR, res; \ + 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) & (argL ^ res), \ + 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + Long argL, argR, oldC, res; \ + oldC = CC_NDEP & AMD64G_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 ^ -1) & (argL ^ res), \ + 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + Long argL, argR, oldC, res; \ + oldC = CC_NDEP & AMD64G_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; \ + sf = lshift(res, 8 - DATA_BITS) & 0x80; \ + of = lshift((argL ^ argR) & (argL ^ res), \ + 12 - DATA_BITS) & AMD64G_CC_MASK_O; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + cf = 0; \ + pf = parity_table[(UChar)CC_DEP1]; \ + af = 0; \ + zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6; \ + sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80; \ + of = 0; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_INC(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + Long argL, argR, res; \ + res = CC_DEP1; \ + argL = res - 1; \ + argR = 1; \ + cf = CC_NDEP & AMD64G_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; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + Long argL, argR, res; \ + res = CC_DEP1; \ + argL = res + 1; \ + argR = 1; \ + cf = CC_NDEP & AMD64G_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) \ + == ((ULong)SIGN_MASK - 1)) << 11; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C; \ + pf = parity_table[(UChar)CC_DEP1]; \ + af = 0; /* undefined */ \ + 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_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \ + & AMD64G_CC_MASK_O; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long cf, pf, af, zf, sf, of; \ + cf = CC_DEP2 & 1; \ + pf = parity_table[(UChar)CC_DEP1]; \ + af = 0; /* undefined */ \ + 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_DEP2 ^ CC_DEP1, 12 - DATA_BITS) \ + & AMD64G_CC_MASK_O; \ + return cf | pf | af | zf | sf | of; \ + } \ +} + +/*-------------------------------------------------------------*/ + +/* ROL: cf' = lsb(result). of' = msb(result) ^ lsb(result). */ +/* DEP1 = result, NDEP = old flags */ +#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long fl \ + = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C)) \ + | (AMD64G_CC_MASK_C & CC_DEP1) \ + | (AMD64G_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). */ +/* DEP1 = result, NDEP = old flags */ +#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long fl \ + = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C)) \ + | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1))) \ + | (AMD64G_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,DATA_U2TYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long 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,DATA_S2TYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + { Long 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; \ + } \ +} + + +#if PROFILE_EFLAGS + +static Bool initted = False; + +/* C flag, fast route */ +static UInt tabc_fast[AMD64G_CC_OP_NUMBER]; +/* C flag, slow route */ +static UInt tabc_slow[AMD64G_CC_OP_NUMBER]; +/* table for calculate_cond */ +static UInt tab_cond[AMD64G_CC_OP_NUMBER][16]; +/* total entry counts for calc_all, calc_c, calc_cond. */ +static UInt n_calc_all = 0; +static UInt n_calc_c = 0; +static UInt n_calc_cond = 0; + +#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond))) + + +static void showCounts ( void ) +{ + Int op, co; + Char ch; + vex_printf("\nTotal calls: calc_all=%d calc_cond=%d calc_c=%d\n", + n_calc_all, n_calc_cond, n_calc_c); + + vex_printf(" cSLOW cFAST O NO B NB Z NZ BE NBE" + " S NS P NP L NL LE NLE\n"); + vex_printf(" -----------------------------------------------------" + "----------------------------------------\n"); + for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) { + + ch = ' '; + if (op > 0 && (op-1) % 3 == 0) + ch = 'B'; + if (op > 0 && (op-1) % 3 == 1) + ch = 'W'; + if (op > 0 && (op-1) % 3 == 2) + ch = 'L'; + + vex_printf("%2d%c: ", op, ch); + vex_printf("%6d ", tabc_slow[op]); + vex_printf("%6d ", tabc_fast[op]); + for (co = 0; co < 16; co++) { + Int n = tab_cond[op][co]; + if (n >= 1000) { + vex_printf(" %3dK", n / 1000); + } else + if (n >= 0) { + vex_printf(" %3d ", n ); + } else { + vex_printf(" "); + } + } + vex_printf("\n"); + } + vex_printf("\n"); +} + +static void initCounts ( void ) +{ + Int op, co; + initted = True; + for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) { + tabc_fast[op] = tabc_slow[op] = 0; + for (co = 0; co < 16; co++) + tab_cond[op][co] = 0; + } +} + +#endif /* PROFILE_EFLAGS */ + + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +/* Calculate all the 6 flags from the supplied thunk parameters. + Worker function, not directly called from generated code. */ +static +ULong amd64g_calculate_rflags_all_WRK ( ULong cc_op, + ULong cc_dep1_formal, + ULong cc_dep2_formal, + ULong cc_ndep_formal ) { - vassert(0); - return 0; + switch (cc_op) { + case AMD64G_CC_OP_COPY: + return cc_dep1_formal + & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z + | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P); + + case AMD64G_CC_OP_ADDB: ACTIONS_ADD( 8, UChar ); + case AMD64G_CC_OP_ADDW: ACTIONS_ADD( 16, UShort ); + case AMD64G_CC_OP_ADDL: ACTIONS_ADD( 32, UInt ); + + case AMD64G_CC_OP_ADCB: ACTIONS_ADC( 8, UChar ); + case AMD64G_CC_OP_ADCW: ACTIONS_ADC( 16, UShort ); + case AMD64G_CC_OP_ADCL: ACTIONS_ADC( 32, UInt ); + + case AMD64G_CC_OP_SUBB: ACTIONS_SUB( 8, UChar ); + case AMD64G_CC_OP_SUBW: ACTIONS_SUB( 16, UShort ); + case AMD64G_CC_OP_SUBL: ACTIONS_SUB( 32, UInt ); + case AMD64G_CC_OP_SUBQ: ACTIONS_SUB( 64, ULong ); + + case AMD64G_CC_OP_SBBB: ACTIONS_SBB( 8, UChar ); + case AMD64G_CC_OP_SBBW: ACTIONS_SBB( 16, UShort ); + case AMD64G_CC_OP_SBBL: ACTIONS_SBB( 32, UInt ); + + case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar ); + case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort ); + case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt ); + case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong ); + + case AMD64G_CC_OP_INCB: ACTIONS_INC( 8, UChar ); + case AMD64G_CC_OP_INCW: ACTIONS_INC( 16, UShort ); + case AMD64G_CC_OP_INCL: ACTIONS_INC( 32, UInt ); + + case AMD64G_CC_OP_DECB: ACTIONS_DEC( 8, UChar ); + case AMD64G_CC_OP_DECW: ACTIONS_DEC( 16, UShort ); + case AMD64G_CC_OP_DECL: ACTIONS_DEC( 32, UInt ); + + case AMD64G_CC_OP_SHLB: ACTIONS_SHL( 8, UChar ); + case AMD64G_CC_OP_SHLW: ACTIONS_SHL( 16, UShort ); + case AMD64G_CC_OP_SHLL: ACTIONS_SHL( 32, UInt ); + + case AMD64G_CC_OP_SHRB: ACTIONS_SHR( 8, UChar ); + case AMD64G_CC_OP_SHRW: ACTIONS_SHR( 16, UShort ); + case AMD64G_CC_OP_SHRL: ACTIONS_SHR( 32, UInt ); + + case AMD64G_CC_OP_ROLB: ACTIONS_ROL( 8, UChar ); + case AMD64G_CC_OP_ROLW: ACTIONS_ROL( 16, UShort ); + case AMD64G_CC_OP_ROLL: ACTIONS_ROL( 32, UInt ); + + case AMD64G_CC_OP_RORB: ACTIONS_ROR( 8, UChar ); + case AMD64G_CC_OP_RORW: ACTIONS_ROR( 16, UShort ); + case AMD64G_CC_OP_RORL: ACTIONS_ROR( 32, UInt ); + + case AMD64G_CC_OP_UMULB: ACTIONS_UMUL( 8, UChar, UShort ); + case AMD64G_CC_OP_UMULW: ACTIONS_UMUL( 16, UShort, UInt ); + case AMD64G_CC_OP_UMULL: ACTIONS_UMUL( 32, UInt, ULong ); + + case AMD64G_CC_OP_SMULB: ACTIONS_SMUL( 8, Char, Short ); + case AMD64G_CC_OP_SMULW: ACTIONS_SMUL( 16, Short, Int ); + case AMD64G_CC_OP_SMULL: ACTIONS_SMUL( 32, Int, Long ); + + default: + /* shouldn't really make these calls from generated code */ + vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)" + "( %lld, 0x%llx, 0x%llx, 0x%llx )\n", + cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal ); + vpanic("amd64g_calculate_rflags_all_WRK(AMD64)"); + } +} + + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +/* Calculate all the 6 flags from the supplied thunk parameters. */ +ULong amd64g_calculate_rflags_all ( ULong cc_op, + ULong cc_dep1, + ULong cc_dep2, + ULong cc_ndep ) +{ +# if PROFILE_EFLAGS + if (!initted) initCounts(); + n_calc_all++; + if (SHOW_COUNTS_NOW) showCounts(); +# endif + return + amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep ); +} + + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +/* Calculate just the carry flag from the supplied thunk parameters. */ +ULong amd64g_calculate_rflags_c ( ULong cc_op, + ULong cc_dep1, + ULong cc_dep2, + ULong cc_ndep ) +{ +# if PROFILE_EFLAGS + if (!initted) initCounts(); + n_calc_c++; + tabc_fast[cc_op]++; + if (SHOW_COUNTS_NOW) showCounts(); +# endif + + /* Fast-case some common ones. */ + switch (cc_op) { +# if 0 // REINSTATE CAREFULLY + case AMD64G_CC_OP_LOGICL: + case AMD64G_CC_OP_LOGICW: + case AMD64G_CC_OP_LOGICB: + return 0; + case AMD64G_CC_OP_SUBL: + return ((UInt)cc_dep1) < ((UInt)cc_dep2) + ? AMD64G_CC_MASK_C : 0; + case AMD64G_CC_OP_SUBW: + return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF)) + ? AMD64G_CC_MASK_C : 0; + case AMD64G_CC_OP_SUBB: + return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF)) + ? AMD64G_CC_MASK_C : 0; + case AMD64G_CC_OP_INCL: + case AMD64G_CC_OP_DECL: + return cc_ndep & AMD64G_CC_MASK_C; +# endif // REINSTATE CAREFULLY + default: + break; + } + +# if PROFILE_EFLAGS + tabc_fast[cc_op]--; + tabc_slow[cc_op]++; +# endif + + return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep) + & AMD64G_CC_MASK_C; } -ULong amd64g_calculate_rflags_c ( - ULong cc_op, - ULong cc_dep1, ULong cc_dep2, ULong cc_ndep - ) +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +/* returns 1 or 0 */ +ULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond, + ULong cc_op, + ULong cc_dep1, + ULong cc_dep2, + ULong cc_ndep ) { - vassert(0); - return 0; + ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1, + cc_dep2, cc_ndep); + ULong of,sf,zf,cf,pf; + ULong inv = cond & 1; + +# if PROFILE_EFLAGS + if (!initted) initCounts(); + tab_cond[cc_op][cond]++; + n_calc_cond++; + if (SHOW_COUNTS_NOW) showCounts(); +# endif + + switch (cond) { + case AMD64CondNO: + case AMD64CondO: /* OF == 1 */ + of = rflags >> AMD64G_CC_SHIFT_O; + return 1 & (inv ^ of); + + case AMD64CondNZ: + case AMD64CondZ: /* ZF == 1 */ + zf = rflags >> AMD64G_CC_SHIFT_Z; + return 1 & (inv ^ zf); + + case AMD64CondNB: + case AMD64CondB: /* CF == 1 */ + cf = rflags >> AMD64G_CC_SHIFT_C; + return 1 & (inv ^ cf); + break; + + case AMD64CondNBE: + case AMD64CondBE: /* (CF or ZF) == 1 */ + cf = rflags >> AMD64G_CC_SHIFT_C; + zf = rflags >> AMD64G_CC_SHIFT_Z; + return 1 & (inv ^ (cf | zf)); + break; + + case AMD64CondNS: + case AMD64CondS: /* SF == 1 */ + sf = rflags >> AMD64G_CC_SHIFT_S; + return 1 & (inv ^ sf); + + case AMD64CondNP: + case AMD64CondP: /* PF == 1 */ + pf = rflags >> AMD64G_CC_SHIFT_P; + return 1 & (inv ^ pf); + + case AMD64CondNL: + case AMD64CondL: /* (SF xor OF) == 1 */ + sf = rflags >> AMD64G_CC_SHIFT_S; + of = rflags >> AMD64G_CC_SHIFT_O; + return 1 & (inv ^ (sf ^ of)); + break; + + case AMD64CondNLE: + case AMD64CondLE: /* ((SF xor OF) or ZF) == 1 */ + sf = rflags >> AMD64G_CC_SHIFT_S; + of = rflags >> AMD64G_CC_SHIFT_O; + zf = rflags >> AMD64G_CC_SHIFT_Z; + return 1 & (inv ^ ((sf ^ of) | zf)); + break; + + default: + /* shouldn't really make these calls from generated code */ + vex_printf("amd64g_calculate_condition" + "( %lld, %lld, 0x%llx, 0x%llx, 0x%llx )\n", + cond, cc_op, cc_dep1, cc_dep2, cc_ndep ); + vpanic("amd64g_calculate_condition"); + } } -ULong amd64g_calculate_condition ( - ULong/*AMD64Condcode*/ cond, - ULong cc_op, - ULong cc_dep1, ULong cc_dep2, ULong cc_ndep - ) + +/* VISIBLE TO LIBVEX CLIENT */ +#if 0 +ULong LibVEX_GuestAMD64_get_rflags ( /*IN*/VexGuestAMD64State* vex_state ) { - vassert(0); - return 0; + ULong rflags = amd64g_calculate_rflags_all_WRK( + vex_state->guest_CC_OP, + vex_state->guest_CC_DEP1, + vex_state->guest_CC_DEP2, + vex_state->guest_CC_NDEP + ); + // UInt dflag = vex_state->guest_DFLAG; + vassert(0); //FIXME +#if 0 + vassert(dflag == 1 || dflag == 0xFFFFFFFF); + if (dflag == 0xFFFFFFFF) + rflags |= (1<<10); + if (vex_state->guest_IDFLAG == 1) + rflags |= (1<<21); +#endif + return rflags; } +#endif + + +/*---------------------------------------------------------------*/ +/*--- %rflags translation-time function specialisers. ---*/ +/*--- These help iropt specialise calls the above run-time ---*/ +/*--- %rflags functions. ---*/ +/*---------------------------------------------------------------*/ +//.. /* Used by the optimiser to try specialisations. Returns an +//.. equivalent expression, or NULL if none. */ +//.. +//.. static Bool isU32 ( IRExpr* e, UInt n ) +//.. { +//.. return e->tag == Iex_Const +//.. && e->Iex.Const.con->tag == Ico_U32 +//.. && e->Iex.Const.con->Ico.U32 == n; +//.. } IRExpr* guest_amd64_spechelper ( HChar* function_name, IRExpr** args ) { - return NULL; +//.. # define unop(_op,_a1) IRExpr_Unop((_op),(_a1)) +//.. # define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2)) +//.. # define mkU32(_n) IRExpr_Const(IRConst_U32(_n)) +//.. # define mkU8(_n) IRExpr_Const(IRConst_U8(_n)) +//.. +//.. Int i, arity = 0; +//.. for (i = 0; args[i]; i++) +//.. arity++; +//.. # if 0 +//.. vex_printf("spec request:\n"); +//.. vex_printf(" %s ", function_name); +//.. for (i = 0; i < arity; i++) { +//.. vex_printf(" "); +//.. ppIRExpr(args[i]); +//.. } +//.. vex_printf("\n"); +//.. # endif +//.. +//.. /* --------- specialising "x86g_calculate_condition" --------- */ +//.. +//.. if (vex_streq(function_name, "x86g_calculate_condition")) { +//.. /* specialise calls to above "calculate condition" function */ +//.. IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2; +//.. vassert(arity == 5); +//.. cond = args[0]; +//.. cc_op = args[1]; +//.. cc_dep1 = args[2]; +//.. cc_dep2 = args[3]; +//.. +//.. /*---------------- ADDL ----------------*/ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_ADDL) && isU32(cond, X86CondZ)) { +//.. /* long add, then Z --> test (dst+src == 0) */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpEQ32, +//.. binop(Iop_Add32, cc_dep1, cc_dep2), +//.. mkU32(0))); +//.. } +//.. +//.. /*---------------- SUBL ----------------*/ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondZ)) { +//.. /* long sub/cmp, then Z --> test dst==src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpEQ32, cc_dep1, cc_dep2)); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondNZ)) { +//.. /* long sub/cmp, then NZ --> test dst!=src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpNE32, cc_dep1, cc_dep2)); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondL)) { +//.. /* long sub/cmp, then L (signed less than) +//.. --> test dst test dst <=s src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpLE32S, cc_dep1, cc_dep2)); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondBE)) { +//.. /* long sub/cmp, then BE (unsigned less than or equal) +//.. --> test dst <=u src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpLE32U, cc_dep1, cc_dep2)); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondB)) { +//.. /* long sub/cmp, then B (unsigned less than) +//.. --> test dst test dst==src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpEQ16, +//.. unop(Iop_32to16,cc_dep1), +//.. unop(Iop_32to16,cc_dep2))); +//.. } +//.. +//.. /*---------------- SUBB ----------------*/ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBB) && isU32(cond, X86CondZ)) { +//.. /* byte sub/cmp, then Z --> test dst==src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpEQ8, +//.. unop(Iop_32to8,cc_dep1), +//.. unop(Iop_32to8,cc_dep2))); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) { +//.. /* byte sub/cmp, then NZ --> test dst!=src */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpNE8, +//.. unop(Iop_32to8,cc_dep1), +//.. unop(Iop_32to8,cc_dep2))); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) { +//.. /* long sub/cmp, then NBE (unsigned greater than) +//.. --> test src <=u dst */ +//.. /* Note, args are opposite way round from the usual */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpLT32U, +//.. binop(Iop_And32,cc_dep2,mkU32(0xFF)), +//.. binop(Iop_And32,cc_dep1,mkU32(0xFF)))); +//.. } +//.. +//.. /*---------------- LOGICL ----------------*/ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) { +//.. /* long and/or/xor, then Z --> test dst==0 */ +//.. return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondS)) { +//.. /* long and/or/xor, then S --> test dst test dst==0 */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)), +//.. mkU32(0))); +//.. } +//.. +//.. /*---------------- LOGICB ----------------*/ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) { +//.. /* byte and/or/xor, then Z --> test dst==0 */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)), +//.. mkU32(0))); +//.. } +//.. +//.. /*---------------- DECL ----------------*/ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_DECL) && isU32(cond, X86CondZ)) { +//.. /* dec L, then Z --> test dst == 0 */ +//.. return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_DECL) && isU32(cond, X86CondS)) { +//.. /* dec L, then S --> compare DST test dep1 == 0 */ +//.. return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); +//.. } +//.. +//.. /*---------------- COPY ----------------*/ +//.. /* This can happen, as a result of x87 FP compares: "fcom ... ; +//.. fnstsw %ax ; sahf ; jbe" for example. */ +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_COPY) && +//.. (isU32(cond, X86CondBE) || isU32(cond, X86CondNBE))) { +//.. /* COPY, then BE --> extract C and Z from dep1, and test (C +//.. or Z == 1). */ +//.. /* COPY, then NBE --> extract C and Z from dep1, and test (C +//.. or Z == 0). */ +//.. UInt nnn = isU32(cond, X86CondBE) ? 1 : 0; +//.. return +//.. unop( +//.. Iop_1Uto32, +//.. binop( +//.. Iop_CmpEQ32, +//.. binop( +//.. Iop_And32, +//.. binop( +//.. Iop_Or32, +//.. binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), +//.. binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)) +//.. ), +//.. mkU32(1) +//.. ), +//.. mkU32(nnn) +//.. ) +//.. ); +//.. } +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_COPY) && isU32(cond, X86CondB)) { +//.. /* COPY, then B --> extract C dep1, and test (C == 1). */ +//.. return +//.. unop( +//.. Iop_1Uto32, +//.. binop( +//.. Iop_CmpNE32, +//.. binop( +//.. Iop_And32, +//.. binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), +//.. mkU32(1) +//.. ), +//.. mkU32(0) +//.. ) +//.. ); +//.. } +//.. +//.. return NULL; +//.. } +//.. +//.. /* --------- specialising "x86g_calculate_eflags_c" --------- */ +//.. +//.. if (vex_streq(function_name, "x86g_calculate_eflags_c")) { +//.. /* specialise calls to above "calculate_eflags_c" function */ +//.. IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep; +//.. vassert(arity == 4); +//.. cc_op = args[0]; +//.. cc_dep1 = args[1]; +//.. cc_dep2 = args[2]; +//.. cc_ndep = args[3]; +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL)) { +//.. /* C after sub denotes unsigned less than */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpLT32U, cc_dep1, cc_dep2)); +//.. } +//.. if (isU32(cc_op, AMD64G_CC_OP_SUBB)) { +//.. /* C after sub denotes unsigned less than */ +//.. return unop(Iop_1Uto32, +//.. binop(Iop_CmpLT32U, +//.. binop(Iop_And32,cc_dep1,mkU32(0xFF)), +//.. binop(Iop_And32,cc_dep2,mkU32(0xFF)))); +//.. } +//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICL) +//.. || isU32(cc_op, AMD64G_CC_OP_LOGICW) +//.. || isU32(cc_op, AMD64G_CC_OP_LOGICB)) { +//.. /* cflag after logic is zero */ +//.. return mkU32(0); +//.. } +//.. if (isU32(cc_op, AMD64G_CC_OP_DECL) || isU32(cc_op, AMD64G_CC_OP_INCL)) { +//.. /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */ +//.. return cc_ndep; +//.. } +//.. if (isU32(cc_op, AMD64G_CC_OP_COPY)) { +//.. /* cflag after COPY is stored in DEP1. */ +//.. return +//.. binop( +//.. Iop_And32, +//.. binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), +//.. mkU32(1) +//.. ); +//.. } +//.. # if 0 +//.. if (cc_op->tag == Iex_Const) { +//.. vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n"); +//.. } +//.. # endif +//.. +//.. return NULL; +//.. } +//.. +//.. /* --------- specialising "x86g_calculate_eflags_all" --------- */ +//.. +//.. if (vex_streq(function_name, "x86g_calculate_eflags_all")) { +//.. /* specialise calls to above "calculate_eflags_all" function */ +//.. IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep; +//.. vassert(arity == 4); +//.. cc_op = args[0]; +//.. cc_dep1 = args[1]; +//.. cc_dep2 = args[2]; +//.. cc_ndep = args[3]; +//.. +//.. if (isU32(cc_op, AMD64G_CC_OP_COPY)) { +//.. /* eflags after COPY are stored in DEP1. */ +//.. return +//.. binop( +//.. Iop_And32, +//.. cc_dep1, +//.. mkU32(AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z +//.. | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P) +//.. ); +//.. } +//.. return NULL; +//.. } + +# undef unop +# undef binop +# undef mkU32 +# undef mkU8 + + return NULL; +} + + +/*---------------------------------------------------------------*/ +/*--- Helpers for dealing with, and describing, ---*/ +/*--- guest state as a whole. ---*/ +/*---------------------------------------------------------------*/ + +/* Initialise the entire amd64 guest state. */ +/* VISIBLE TO LIBVEX CLIENT */ +void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state ) +{ + //Int i; + + vex_state->guest_RAX = 0; + vex_state->guest_RCX = 0; + vex_state->guest_RDX = 0; + vex_state->guest_RBX = 0; + vex_state->guest_RSP = 0; + vex_state->guest_RBP = 0; + vex_state->guest_RSI = 0; + vex_state->guest_RDI = 0; + vex_state->guest_R8 = 0; + vex_state->guest_R9 = 0; + vex_state->guest_R10 = 0; + vex_state->guest_R11 = 0; + vex_state->guest_R12 = 0; + vex_state->guest_R13 = 0; + vex_state->guest_R14 = 0; + vex_state->guest_R15 = 0; + + vex_state->guest_CC_OP = AMD64G_CC_OP_COPY; + vex_state->guest_CC_DEP1 = 0; + vex_state->guest_CC_DEP2 = 0; + vex_state->guest_CC_NDEP = 0; + + // XXX: add more here later, for D/ID flags + + vex_state->guest_RIP = 0; + + // XXX: add more here later, for segment registers, FPU, etc. + + vex_state->guest_EMWARN = EmWarn_NONE; } + /* Figure out if any part of the guest state contained in minoff .. maxoff requires precise memory exceptions. If in doubt return True (but this is generates significantly slower code). @@ -109,7 +1135,6 @@ Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff, } - #define ALWAYSDEFD(field) \ { offsetof(VexGuestAMD64State, field), \ (sizeof ((VexGuestAMD64State*)0)->field) } @@ -158,42 +1183,6 @@ VexGuestLayout }; -/* VISIBLE TO LIBVEX CLIENT */ -void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state ) -{ - //Int i; - - vex_state->guest_RAX = 0; - vex_state->guest_RCX = 0; - vex_state->guest_RDX = 0; - vex_state->guest_RBX = 0; - vex_state->guest_RSP = 0; - vex_state->guest_RBP = 0; - vex_state->guest_RSI = 0; - vex_state->guest_RDI = 0; - vex_state->guest_R8 = 0; - vex_state->guest_R9 = 0; - vex_state->guest_R10 = 0; - vex_state->guest_R11 = 0; - vex_state->guest_R12 = 0; - vex_state->guest_R13 = 0; - vex_state->guest_R14 = 0; - vex_state->guest_R15 = 0; - - vex_state->guest_CC_OP = AMD64G_CC_OP_COPY; - vex_state->guest_CC_DEP1 = 0; - vex_state->guest_CC_DEP2 = 0; - vex_state->guest_CC_NDEP = 0; - - // XXX: add more here later, for D/ID flags - - vex_state->guest_RIP = 0; - - // XXX: add more here later, for segment registers, FPU, etc. - - vex_state->guest_EMWARN = EmWarn_NONE; -} - /*---------------------------------------------------------------*/ /*--- end guest-amd64/ghelpers.c ---*/ /*---------------------------------------------------------------*/ diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index d47771d03f..ce70a5ac72 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -33,6 +33,9 @@ USA. */ +/* EFLAGS after multiply-Q is wrong because there is no way to do + a 128-bit multiply in C (directly). */ + //.. /* TODO: //.. SBB reg with itself //.. @@ -11106,24 +11109,27 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, //.. whatNext = Dis_StopHere; //.. DIP("int $0x80\n"); //.. break; -//.. -//.. /* ------------------------ Jcond, byte offset --------- */ -//.. -//.. case 0xEB: /* Jb (jump, byte offset) */ -//.. d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta); -//.. delta++; -//.. if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) { -//.. whatNext = Dis_Resteer; -//.. *whereNext = d32; -//.. } else { -//.. jmp_lit(Ijk_Boring,d32); -//.. whatNext = Dis_StopHere; -//.. } -//.. DIP("jmp-8 0x%x\n", d32); -//.. break; + + /* ------------------------ Jcond, byte offset --------- */ + + case 0xEB: /* Jb (jump, byte offset) */ + if (sz != 4) + goto decode_failure; /* JRS added 2004 July 11 */ + d64 = (guest_rip_bbstart+delta+1) + getSDisp8(delta); + delta++; + if (resteerOK && resteerOkFn(d64)) { + whatNext = Dis_Resteer; + *whereNext = d64; + } else { + jmp_lit(Ijk_Boring,d64); + whatNext = Dis_StopHere; + } + DIP("jmp-8 0x%llx\n", d64); + break; case 0xE9: /* Jv (jump, 16/32 offset) */ - if (sz != 4) goto decode_failure; /* JRS added 2004 July 11 */ + if (sz != 4) + goto decode_failure; /* JRS added 2004 July 11 */ d64 = (guest_rip_bbstart+delta+sz) + getSDisp(sz,delta); delta += sz; if (resteerOK && resteerOkFn(d64)) { @@ -11136,29 +11142,31 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, DIP("jmp 0x%llx\n", d64); break; -//.. case 0x70: -//.. case 0x71: -//.. case 0x72: /* JBb/JNAEb (jump below) */ -//.. case 0x73: /* JNBb/JAEb (jump not below) */ -//.. case 0x74: /* JZb/JEb (jump zero) */ -//.. case 0x75: /* JNZb/JNEb (jump not zero) */ -//.. case 0x76: /* JBEb/JNAb (jump below or equal) */ -//.. case 0x77: /* JNBEb/JAb (jump not below or equal) */ -//.. case 0x78: /* JSb (jump negative) */ -//.. case 0x79: /* JSb (jump not negative) */ -//.. case 0x7A: /* JP (jump parity even) */ -//.. case 0x7B: /* JNP/JPO (jump parity odd) */ -//.. case 0x7C: /* JLb/JNGEb (jump less) */ -//.. case 0x7D: /* JGEb/JNLb (jump greater or equal) */ -//.. case 0x7E: /* JLEb/JNGb (jump less or equal) */ -//.. case 0x7F: /* JGb/JNLEb (jump greater) */ -//.. d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta); -//.. delta++; -//.. jcc_01((X86Condcode)(opc - 0x70), (Addr32)(guest_eip_bbstart+delta), d32); -//.. whatNext = Dis_StopHere; -//.. DIP("j%s-8 0x%x\n", name_X86Condcode(opc - 0x70), d32); -//.. break; -//.. + case 0x70: + case 0x71: + case 0x72: /* JBb/JNAEb (jump below) */ + case 0x73: /* JNBb/JAEb (jump not below) */ + case 0x74: /* JZb/JEb (jump zero) */ + case 0x75: /* JNZb/JNEb (jump not zero) */ + case 0x76: /* JBEb/JNAb (jump below or equal) */ + case 0x77: /* JNBEb/JAb (jump not below or equal) */ + case 0x78: /* JSb (jump negative) */ + case 0x79: /* JSb (jump not negative) */ + case 0x7A: /* JP (jump parity even) */ + case 0x7B: /* JNP/JPO (jump parity odd) */ + case 0x7C: /* JLb/JNGEb (jump less) */ + case 0x7D: /* JGEb/JNLb (jump greater or equal) */ + case 0x7E: /* JLEb/JNGb (jump less or equal) */ + case 0x7F: /* JGb/JNLEb (jump greater) */ + d64 = (guest_rip_bbstart+delta+1) + getSDisp8(delta); + delta++; + jcc_01( (AMD64Condcode)(opc - 0x70), + guest_rip_bbstart+delta, + d64 ); + whatNext = Dis_StopHere; + DIP("j%s-8 0x%llx\n", name_AMD64Condcode(opc - 0x70), d64); + break; + //.. case 0xE3: /* JECXZ or perhaps JCXZ, depending on OSO ? Intel //.. manual says it depends on address size override, //.. which doesn't sound right to me. */ diff --git a/VEX/priv/host-amd64/isel.c b/VEX/priv/host-amd64/isel.c index eb99273320..435b7f916b 100644 --- a/VEX/priv/host-amd64/isel.c +++ b/VEX/priv/host-amd64/isel.c @@ -1543,8 +1543,8 @@ static AMD64CondCode iselCondCode ( ISelEnv* env, IRExpr* e ) /* DO NOT CALL THIS DIRECTLY ! */ static AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) { -//.. MatchInfo mi; -//.. DECLARE_PATTERN(p_32to1); + MatchInfo mi; + DECLARE_PATTERN(p_32to1_64to32); //.. DECLARE_PATTERN(p_1Uto32_then_32to1); //.. DECLARE_PATTERN(p_1Sto32_then_32to1); @@ -1582,17 +1582,17 @@ static AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) //.. IRExpr* expr1 = mi.bindee[0]; //.. return iselCondCode(env, expr1); //.. } -//.. -//.. /* pattern: 32to1(expr32) */ -//.. DEFINE_PATTERN(p_32to1, -//.. unop(Iop_32to1,bind(0)) -//.. ); -//.. if (matchIRExpr(&mi,p_32to1,e)) { -//.. X86RM* rm = iselIntExpr_RM(env, mi.bindee[0]); -//.. addInstr(env, X86Instr_Test32(X86RI_Imm(1),rm)); -//.. return Xcc_NZ; -//.. } -//.. + + /* pattern: 32to1(64to32(expr64)) */ + DEFINE_PATTERN(p_32to1_64to32, + unop(Iop_32to1,unop(Iop_64to32, bind(0))) + ); + if (matchIRExpr(&mi,p_32to1_64to32,e)) { + AMD64RM* rm = iselIntExpr_RM(env, mi.bindee[0]); + addInstr(env, AMD64Instr_Test64(AMD64RI_Imm(1),rm)); + return Acc_NZ; + } + //.. /* CmpEQ8 / CmpNE8 */ //.. if (e->tag == Iex_Binop //.. && (e->Iex.Binop.op == Iop_CmpEQ8 @@ -3434,18 +3434,18 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) //.. case Ist_MFence: //.. addInstr(env, X86Instr_MFence(env->subarch)); //.. return; -//.. -//.. /* --------- EXIT --------- */ -//.. case Ist_Exit: { -//.. X86RI* dst; -//.. X86CondCode cc; -//.. if (stmt->Ist.Exit.dst->tag != Ico_U32) -//.. vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value"); -//.. dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst)); -//.. cc = iselCondCode(env,stmt->Ist.Exit.guard); -//.. addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst)); -//.. return; -//.. } + + /* --------- EXIT --------- */ + case Ist_Exit: { + AMD64RI* dst; + AMD64CondCode cc; + if (stmt->Ist.Exit.dst->tag != Ico_U64) + vpanic("iselStmt(amd64): Ist_Exit: dst is not a 64-bit value"); + dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst)); + cc = iselCondCode(env,stmt->Ist.Exit.guard); + addInstr(env, AMD64Instr_Goto(stmt->Ist.Exit.jk, cc, dst)); + return; + } default: break; }