#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_<something>, 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 <s src */
+//.. return unop(Iop_1Uto32,
+//.. binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
+//.. }
+//..
+//.. if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {
+//.. /* long sub/cmp, then LE (signed less than or equal)
+//.. --> 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 <u src */
+//.. return unop(Iop_1Uto32,
+//.. binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
+//.. }
+//..
+//.. /*---------------- SUBW ----------------*/
+//..
+//.. if (isU32(cc_op, AMD64G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {
+//.. /* byte sub/cmp, then Z --> 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 <s 0 */
+//.. return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
+//.. }
+//..
+//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {
+//.. /* long and/or/xor, then LE
+//.. This is pretty subtle. LOGIC sets SF and ZF according to the
+//.. result and makes OF be zero. LE computes (SZ ^ OF) | ZF, but
+//.. OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
+//.. the result is <=signed 0. Hence ...
+//.. */
+//.. return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
+//.. }
+//..
+//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondBE)) {
+//.. /* long and/or/xor, then BE
+//.. LOGIC sets ZF according to the result and makes CF be zero.
+//.. BE computes (CF | ZF), but CF is zero, so this reduces ZF
+//.. -- which will be 1 iff the result is zero. Hence ...
+//.. */
+//.. return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
+//.. }
+//..
+//.. /*---------------- LOGICW ----------------*/
+//..
+//.. if (isU32(cc_op, AMD64G_CC_OP_LOGICW) && 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(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 <s 0 */
+//.. return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
+//.. }
+//..
+//.. /*---------------- SHRL ----------------*/
+//..
+//.. if (isU32(cc_op, AMD64G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
+//.. /* SHRL, then Z --> 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).
}
-
#define ALWAYSDEFD(field) \
{ offsetof(VexGuestAMD64State, field), \
(sizeof ((VexGuestAMD64State*)0)->field) }
};
-/* 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 ---*/
/*---------------------------------------------------------------*/