: (__data_bits==16 ? 0xFFFF \
: 0xFFFFFFFF); \
/* const */ UInt SIGN_MASK = 1 << (__data_bits - 1); \
- /* const */ UInt CC_DST = cc_dst_formal; \
- /* const */ UInt CC_SRC = cc_src_formal; \
+ /* const */ UInt CC_RES = cc_res_formal; \
+ /* const */ UInt CC_AUX = cc_aux_formal; \
/* Three 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_SRC = CC_SRC;
+ CC_AUX = CC_AUX;
/*-------------------------------------------------------------*/
#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- int src1, src2, dst; \
- src1 = CC_SRC; \
- src2 = CC_DST; \
- dst = src1 + src2; \
- cf = (DATA_UTYPE)dst < (DATA_UTYPE)src1; \
- pf = parity_table[(UChar)dst]; \
- af = (dst ^ src1 ^ src2) & 0x10; \
- zf = ((DATA_UTYPE)dst == 0) << 6; \
- sf = lshift(dst, 8 - DATA_BITS) & 0x80; \
- of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), \
+ 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)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) & CC_MASK_O; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- int src1, src2, dst; \
- src1 = CC_SRC; \
- src2 = CC_DST; \
- dst = src1 + src2 + 1; \
- cf = (DATA_UTYPE)dst <= (DATA_UTYPE)src1; \
- pf = parity_table[(UChar)dst]; \
- af = (dst ^ src1 ^ src2) & 0x10; \
- zf = ((DATA_UTYPE)dst == 0) << 6; \
- sf = lshift(dst, 8 - DATA_BITS) & 0x80; \
- of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), \
+ 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; \
+ 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; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- int src1, src2, dst; \
- src1 = CC_DST; \
- src2 = CC_SRC; \
- dst = src1 - src2; \
- cf = (DATA_UTYPE)src1 < (DATA_UTYPE)src2; \
- pf = parity_table[(UChar)dst]; \
- af = (dst ^ src1 ^ src2) & 0x10; \
- zf = ((DATA_UTYPE)dst == 0) << 6; \
- sf = lshift(dst, 8 - DATA_BITS) & 0x80; \
- of = lshift((src1 ^ src2) & (src1 ^ dst), \
+ 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; \
+ 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; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- int src1, src2, dst; \
- src1 = CC_DST; \
- src2 = CC_SRC; \
- dst = (src1 - src2) - 1; \
- cf = (DATA_UTYPE)src1 <= (DATA_UTYPE)src2; \
- pf = parity_table[(UChar)dst]; \
- af = (dst ^ src1 ^ src2) & 0x10; \
- zf = ((DATA_UTYPE)dst == 0) << 6; \
- sf = lshift(dst, 8 - DATA_BITS) & 0x80; \
- of = lshift((src1 ^ src2) & (src1 ^ dst), \
+ 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; \
+ 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; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
+ Int cf, pf, af, zf, sf, of; \
cf = 0; \
- pf = parity_table[(UChar)CC_DST]; \
+ pf = parity_table[(UChar)CC_RES]; \
af = 0; \
- zf = ((DATA_UTYPE)CC_DST == 0) << 6; \
- sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \
+ zf = ((DATA_UTYPE)CC_RES == 0) << 6; \
+ sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \
of = 0; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_INC(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- int src1, src2; \
- src1 = CC_DST - 1; \
- src2 = 1; \
- cf = CC_SRC; \
- pf = parity_table[(UChar)CC_DST]; \
- af = (CC_DST ^ src1 ^ src2) & 0x10; \
- zf = ((DATA_UTYPE)CC_DST == 0) << 6; \
- sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \
- of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11; \
+ Int cf, pf, af, zf, sf, of; \
+ Int argL, argR; \
+ argL = CC_RES - 1; \
+ argR = 1; \
+ cf = CC_AUX & CC_MASK_O; \
+ 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; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- int src1, src2; \
- src1 = CC_DST + 1; \
- src2 = 1; \
- cf = CC_SRC; \
- pf = parity_table[(UChar)CC_DST]; \
- af = (CC_DST ^ src1 ^ src2) & 0x10; \
- zf = ((DATA_UTYPE)CC_DST == 0) << 6; \
- sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \
- of = ((CC_DST & DATA_MASK) \
+ Int cf, pf, af, zf, sf, of; \
+ Int argL, argR; \
+ argL = CC_RES + 1; \
+ argR = 1; \
+ cf = CC_AUX & CC_MASK_O; \
+ 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) \
== ((UInt)SIGN_MASK - 1)) << 11; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- cf = (CC_SRC >> (DATA_BITS - 1)) & CC_MASK_C; \
- pf = parity_table[(UChar)CC_DST]; \
+ Int cf, pf, af, zf, sf, of; \
+ cf = (CC_AUX >> (DATA_BITS - 1)) & CC_MASK_C; \
+ pf = parity_table[(UChar)CC_RES]; \
af = 0; /* undefined */ \
- zf = ((DATA_UTYPE)CC_DST == 0) << 6; \
- sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \
+ zf = ((DATA_UTYPE)CC_RES == 0) << 6; \
+ sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \
/* of is defined if shift count == 1 */ \
- of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_MASK_O; \
+ of = lshift(CC_AUX ^ CC_RES, 12 - DATA_BITS) & CC_MASK_O; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_SAR(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- cf = CC_SRC & 1; \
- pf = parity_table[(UChar)CC_DST]; \
+ Int cf, pf, af, zf, sf, of; \
+ cf = CC_AUX & 1; \
+ pf = parity_table[(UChar)CC_RES]; \
af = 0; /* undefined */ \
- zf = ((DATA_UTYPE)CC_DST == 0) << 6; \
- sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \
+ zf = ((DATA_UTYPE)CC_RES == 0) << 6; \
+ sf = lshift(CC_RES, 8 - DATA_BITS) & 0x80; \
/* of is defined if shift count == 1 */ \
- of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_MASK_O; \
+ of = lshift(CC_AUX ^ CC_RES, 12 - DATA_BITS) & CC_MASK_O; \
return cf | pf | af | zf | sf | of; \
}
#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int fl \
- = (CC_SRC & ~(CC_MASK_O | CC_MASK_C)) \
- | (CC_MASK_C & CC_DST) \
- | (CC_MASK_O & (lshift(CC_DST, 11-(DATA_BITS-1)) \
- ^ lshift(CC_DST, 11))); \
+ 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))); \
return fl; \
}
#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int fl \
- = (CC_SRC & ~(CC_MASK_O | CC_MASK_C)) \
- | (CC_MASK_C & (CC_DST >> (DATA_BITS-1))) \
- | (CC_MASK_O & (lshift(CC_DST, 11-(DATA_BITS-1)) \
- ^ lshift(CC_DST, 11-(DATA_BITS-1)+1))); \
+ 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))); \
return fl; \
}
/*-------------------------------------------------------------*/
-#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE) \
+#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- DATA_UTYPE hi; \
- DATA_UTYPE lo = ((DATA_UTYPE)CC_SRC) * ((DATA_UTYPE)CC_DST);\
- DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_SRC)) \
- * ((DATA_U2TYPE)((DATA_UTYPE)CC_DST)); \
- hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS); \
- cf = (hi != 0); \
- pf = parity_table[(UChar)lo]; \
+ 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 = (lo == 0) << 6; \
- sf = lshift(lo, 8 - DATA_BITS) & 0x80; \
+ 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) \
+#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE) \
{ \
PREAMBLE(DATA_BITS); \
- int cf, pf, af, zf, sf, of; \
- DATA_STYPE hi; \
- DATA_STYPE lo = ((DATA_STYPE)CC_SRC) * ((DATA_STYPE)CC_DST);\
- DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_SRC)) \
- * ((DATA_S2TYPE)((DATA_STYPE)CC_DST)); \
- hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS); \
- cf = (hi != (lo >>/*s*/ (DATA_BITS-1))); \
- pf = parity_table[(UChar)lo]; \
+ 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 = (lo == 0) << 6; \
- sf = lshift(lo, 8 - DATA_BITS) & 0x80; \
+ zf = (resLo == 0) << 6; \
+ sf = lshift(resLo, 8 - DATA_BITS) & 0x80; \
of = cf << 11; \
return cf | pf | af | zf | sf | of; \
}
/* 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_src_formal, UInt cc_dst_formal )
+UInt calculate_eflags_all ( UInt cc_op, UInt cc_res_formal, UInt cc_aux_formal )
{
# if PROFILE_EFLAGS
n_calc_all++;
# endif
switch (cc_op) {
case CC_OP_COPY:
- return cc_src_formal
+ return cc_res_formal
& (CC_MASK_O | CC_MASK_S | CC_MASK_Z
| CC_MASK_A | CC_MASK_C | CC_MASK_P);
case CC_OP_RORW: ACTIONS_ROR( 16, UShort );
case CC_OP_RORL: ACTIONS_ROR( 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_UMULB: ACTIONS_UMUL( 8, UChar );
+ case CC_OP_UMULW: ACTIONS_UMUL( 16, UShort );
+ case CC_OP_UMULL: ACTIONS_UMUL( 32, UInt );
- 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 );
+ case CC_OP_SMULB: ACTIONS_SMUL( 8, Char );
+ case CC_OP_SMULW: ACTIONS_SMUL( 16, Short );
+ case CC_OP_SMULL: ACTIONS_SMUL( 32, Int );
default:
/* shouldn't really make these calls from generated code */
vex_printf("calculate_eflags_all( %d, 0x%x, 0x%x )\n",
- cc_op, cc_src_formal, cc_dst_formal );
+ cc_op, cc_res_formal, cc_res_formal );
vpanic("calculate_eflags_all");
}
}
/* 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_src, UInt cc_dst )
+UInt calculate_eflags_c ( UInt cc_op, UInt cc_res, UInt cc_aux )
{
/* Fast-case some common ones. */
switch (cc_op) {
+#if 0
case CC_OP_LOGICL: case CC_OP_LOGICW: case CC_OP_LOGICB:
return 0;
case CC_OP_DECL:
case CC_OP_SUBB:
return ( ((UInt)(cc_src & 0xFF)) > ((UInt)(cc_dst & 0xFF)) )
? CC_MASK_C : 0;
+#endif
default:
break;
}
n_calc_c++;
# endif
- return calculate_eflags_all(cc_op,cc_src,cc_dst) & CC_MASK_C;
+ return calculate_eflags_all(cc_op,cc_res,cc_aux) & 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_src, UInt cc_dst )
+ UInt cc_op, UInt cc_res, UInt cc_aux )
{
- UInt eflags = calculate_eflags_all(cc_op, cc_src, cc_dst);
+ UInt eflags = calculate_eflags_all(cc_op, cc_res, cc_aux);
UInt of,sf,zf,cf,pf;
UInt inv = cond & 1;
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_src, cc_dst );
+ cond, cc_op, cc_res, cc_aux );
vpanic("calculate_condition");
}
}
}
vex_printf("\n");
# endif
-
+return NULL;
if (vex_streq(function_name, "calculate_eflags_c")) {
/* specialise calls to above "calculate_eflags_c" function */
IRExpr *cc_op, *cc_src, *cc_dst;
| CC_MASK_Z | CC_MASK_S | CC_MASK_O);
vex_state->guest_CC_OP = CC_OP_COPY;
- vex_state->guest_CC_DST = 0;
- vex_state->guest_CC_DST = eflags_native;
+ vex_state->guest_CC_AUX = 0;
+ vex_state->guest_CC_RES = eflags_native;
}
{
UInt eflags = calculate_eflags_all(
vex_state->guest_CC_OP,
- vex_state->guest_CC_SRC,
- vex_state->guest_CC_DST
+ vex_state->guest_CC_RES,
+ vex_state->guest_CC_AUX
);
UInt dflag = vex_state->guest_DFLAG;
vassert(dflag == 1 || dflag == 0xFFFFFFFF);
vex_state->guest_EDI = 0;
vex_state->guest_CC_OP = CC_OP_COPY;
- vex_state->guest_CC_SRC = 0;
- vex_state->guest_CC_DST = 0;
+ vex_state->guest_CC_RES = 0;
+ vex_state->guest_CC_AUX = 0;
vex_state->guest_DFLAG = 1; /* forwards */
vex_state->guest_IDFLAG = 0;
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 14,
+ .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. */
.alwaysDefd[0] = ALWAYSDEFD(guest_CC_OP),
+ .alwaysDefd[14] = ALWAYSDEFD(guest_CC_AUX),
.alwaysDefd[1] = ALWAYSDEFD(guest_DFLAG),
.alwaysDefd[2] = ALWAYSDEFD(guest_IDFLAG),
.alwaysDefd[3] = ALWAYSDEFD(guest_EIP),
#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_SRC offsetof(VexGuestX86State,guest_CC_SRC)
-#define OFFB_CC_DST offsetof(VexGuestX86State,guest_CC_DST)
+#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)
{
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
if (szSmall == 2 && szBig == 4) {
return signd ? Iop_16Sto32 : Iop_16Uto32;
}
- vpanic("mkWidenOp(x86)");
+ 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. ---*/
/* -------------- Evaluating the flags-thunk. -------------- */
/* Build IR to calculate all the eflags from stored
- CC_OP/CC_SRC/CC_DST. Returns an expression :: Ity_I32. */
+ CC_OP/CC_RES/CC_AUX. 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_SRC, Ity_I32),
- IRExpr_Get(OFFB_CC_DST, Ity_I32) );
+ IRExpr_Get(OFFB_CC_RES, Ity_I32),
+ IRExpr_Get(OFFB_CC_AUX, Ity_I32) );
return mkIRExprCCall(
Ity_I32,
0/*regparm*/,
}
/* Build IR to calculate just the carry flag from stored
- CC_OP/CC_SRC/CC_DST. Returns an expression :: Ity_I32. */
+ CC_OP/CC_RES/CC_AUX. 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_SRC, Ity_I32),
- IRExpr_Get(OFFB_CC_DST, Ity_I32) );
+ IRExpr_Get(OFFB_CC_RES, Ity_I32),
+ IRExpr_Get(OFFB_CC_AUX, Ity_I32) );
return mkIRExprCCall(
Ity_I32,
0/*regparm*/,
}
/* Build IR to calculate some particular condition from stored
- CC_OP/CC_SRC/CC_DST. Returns an expression :: Ity_Bit. */
+ CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_Bit. */
static IRExpr* mk_calculate_condition ( Condcode cond )
{
IRExpr** args
= mkIRExprVec_4( mkU32(cond),
IRExpr_Get(OFFB_CC_OP, Ity_I32),
- IRExpr_Get(OFFB_CC_SRC, Ity_I32),
- IRExpr_Get(OFFB_CC_DST, Ity_I32) );
+ IRExpr_Get(OFFB_CC_RES, Ity_I32),
+ IRExpr_Get(OFFB_CC_AUX, Ity_I32) );
return unop(Iop_32to1,
mkIRExprCCall(
Ity_I32,
/* The machinery in this section builds the flag-thunk following a
flag-setting operation. Hence the various setFlags_* functions.
- Note, in reality setFlags_ADD_SUB and setFlags_MUL are pretty much
- the same -- they just store the two operands.
*/
static Bool isAddSub ( IROp op8 )
}
-/* This is for add/sub/adc/sbb, where (like multiply) we simply store
- the two arguments. Note, the args are reversed, so if op8
- indicates subtract, then the value the program is trying to compute
- is src1 - src2. */
+/* Set the flags thunk for add/sub operations.. The supplied op is
+ auto-sized up to the real op. */
-static void setFlags_ADD_SUB ( IROp op8,
- IRTemp src2,
- IRTemp src1,
+static void setFlags_RES_AUX ( IROp op8,
+ IRTemp res,
+ IRTemp aux,
IRType ty )
{
Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
case Iop_Add8: ccOp += CC_OP_ADDB; break;
case Iop_Sub8: ccOp += CC_OP_SUBB; break;
default: ppIROp(op8);
- vpanic("setFlags_ADD_SUB(x86)");
+ vpanic("setFlags_RES_AUX(x86)");
}
stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) );
- stmt( IRStmt_Put( OFFB_CC_SRC, widenUto32(mkexpr(src2))) );
- stmt( IRStmt_Put( OFFB_CC_DST, widenUto32(mkexpr(src1))) );
+ stmt( IRStmt_Put( OFFB_CC_RES, widenUto32(mkexpr(res))) );
+ stmt( IRStmt_Put( OFFB_CC_AUX, widenUto32(mkexpr(aux))) );
}
/* For and/or/xor, only the result is important. However, put zero in
- CC_SRC to keep memcheck happy. */
+ CC_AUX since we're paranoid. */
static void setFlags_LOGIC ( IROp op8,
- IRTemp dst1,
+ IRTemp res,
IRType ty )
{
Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
vpanic("setFlags_LOGIC(x86)");
}
stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) );
- stmt( IRStmt_Put( OFFB_CC_SRC, mkU32(0)) );
- stmt( IRStmt_Put( OFFB_CC_DST, widenUto32(mkexpr(dst1))) );
+ stmt( IRStmt_Put( OFFB_CC_RES, widenUto32(mkexpr(res))) );
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0)) );
}
-/* For all shift and rotate cases, store the result value and the
- result except shifted or rotated one bit less ("undershifted",
- hence US). And then only when the guard is non-zero. */
+/* For shift operations, we put in the result and the undershifted
+ result. Except if the shift amount is zero, the thunk is left
+ unchanged. */
-static void setFlags_DSTus_DST1 ( IROp op32,
- IRTemp dstUS,
- IRTemp dst1,
- IRType ty,
- IRTemp guard )
+static void setFlags_RES_RESus ( IROp op32,
+ IRTemp res,
+ IRTemp resUS,
+ IRType ty,
+ IRTemp guard )
{
Int ccOp = ty==Ity_I8 ? 2 : (ty==Ity_I16 ? 1 : 0);
case Iop_Sar32: ccOp = CC_OP_SARL - ccOp; break;
case Iop_Shl32: ccOp = CC_OP_SHLL - ccOp; break;
default: ppIROp(op32);
- vpanic("setFlags_DSTus_DST1(x86)");
+ vpanic("setFlags_RES_RESus(x86)");
}
- /* CC_SRC = undershifted %d after, CC_DST = %d afterwards */
+ /* RES contains the result, AUX 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_SRC,
+ stmt( IRStmt_Put( OFFB_CC_RES,
IRExpr_Mux0X( mkexpr(guard),
- IRExpr_Get(OFFB_CC_SRC,Ity_I32),
- widenUto32(mkexpr(dstUS)))) );
- stmt( IRStmt_Put( OFFB_CC_DST,
+ IRExpr_Get(OFFB_CC_RES,Ity_I32),
+ widenUto32(mkexpr(res)))) );
+ stmt( IRStmt_Put( OFFB_CC_AUX,
IRExpr_Mux0X( mkexpr(guard),
- IRExpr_Get(OFFB_CC_DST,Ity_I32),
- widenUto32(mkexpr(dst1)))) );
+ IRExpr_Get(OFFB_CC_AUX,Ity_I32),
+ widenUto32(mkexpr(resUS)))) );
}
-/* For the inc/dec case, we store the result value and the former
- value of the carry flag, which unfortunately we have to compute. */
+/* For the inc/dec case, we store in RES the result value and in AUX
+ the former value of the carry flag, which unfortunately we have to
+ compute. */
-static void setFlags_INC_DEC ( Bool inc, IRTemp dst, IRType ty )
+static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
{
- Int ccOp = inc ? CC_OP_INCB : CC_OP_DECB;
+ Int ccOp = inc ? CC_OP_INCB : CC_OP_DECB;
ccOp += ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
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_SRC, mk_calculate_eflags_c()) );
+ stmt( IRStmt_Put( OFFB_CC_AUX, mk_calculate_eflags_c()) );
stmt( IRStmt_Put( OFFB_CC_OP, mkU32(ccOp)) );
- stmt( IRStmt_Put( OFFB_CC_DST, mkexpr(dst)) );
+ stmt( IRStmt_Put( OFFB_CC_RES, mkexpr(res)) );
}
-/* For multiplies, just remember the two operands and a
- description of what kind of multiply. */
+/* 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. */
static
-void setFlags_MUL ( IRType ty, IRTemp src1, IRTemp src2, UInt base_op )
+void setFlags_MUL ( IRType ty, IRTemp resHi, IRTemp resLo, UInt base_op )
{
switch (ty) {
case Ity_I8:
stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) );
- stmt( IRStmt_Put( OFFB_CC_SRC, unop(Iop_8Uto32,mkexpr(src1)) ) );
- stmt( IRStmt_Put( OFFB_CC_DST, unop(Iop_8Uto32,mkexpr(src2)) ) );
+ 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_SRC, unop(Iop_16Uto32,mkexpr(src1)) ) );
- stmt( IRStmt_Put( OFFB_CC_DST, unop(Iop_16Uto32,mkexpr(src2)) ) );
+ 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_SRC, mkexpr(src1) ) );
- stmt( IRStmt_Put( OFFB_CC_DST, mkexpr(src2) ) );
+ 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)");
/* -------------- Helpers for ADD/SUB with carry. -------------- */
-/* Given ta1, ta2 and tdst, compute tdst = ADC(ta1,ta2) and set flags
+/* 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}.
*/
static void helper_ADC ( Int sz,
- IRTemp tdst, IRTemp ta1, IRTemp ta2 )
+ IRTemp tres, IRTemp ta1, IRTemp ta2 )
{
UInt thunkOp;
IRExpr* thunkExpr;
mk_calculate_eflags_c(),
mkU32(1)) );
- assign(tdst, binop(plus,
+ assign(tres, binop(plus,
binop(plus,mkexpr(ta1),mkexpr(ta2)),
narrowTo(ty,mkexpr(oldc))));
binop(Iop_Mul32, mkexpr(oldc), mkU32(3)));
stmt( IRStmt_Put( OFFB_CC_OP, thunkExpr ) );
- stmt( IRStmt_Put( OFFB_CC_SRC, mkexpr(ta2) ) );
- stmt( IRStmt_Put( OFFB_CC_DST, mkexpr(ta1) ) );
+ stmt( IRStmt_Put( OFFB_CC_RES, mkexpr(tres) ) );
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkexpr(ta2) ) );
}
-/* Given ta1, ta2 and tdst, compute tdst = SBB(ta1,ta2) and set flags
+/* 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}.
*/
static void helper_SBB ( Int sz,
- IRTemp tdst, IRTemp ta1, IRTemp ta2 )
+ IRTemp tres, IRTemp ta1, IRTemp ta2 )
{
UInt thunkOp;
IRExpr* thunkExpr;
mk_calculate_eflags_c(),
mkU32(1)) );
- assign(tdst, binop(minus,
+ assign(tres, binop(minus,
binop(minus,mkexpr(ta1),mkexpr(ta2)),
narrowTo(ty,mkexpr(oldc))));
binop(Iop_Mul32, mkexpr(oldc), mkU32(3)));
stmt( IRStmt_Put( OFFB_CC_OP, thunkExpr ) );
- stmt( IRStmt_Put( OFFB_CC_SRC, mkexpr(ta2) ) );
- stmt( IRStmt_Put( OFFB_CC_DST, mkexpr(ta1) ) );
+ stmt( IRStmt_Put( OFFB_CC_RES, mkexpr(tres) ) );
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkexpr(ta2) ) );
}
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_SRC, mkU32(CC_MASK_Z|CC_MASK_P) ));
- stmt( IRStmt_Put( OFFB_CC_DST, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_RES, mkU32(CC_MASK_Z|CC_MASK_P) ));
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
DIP("xor%c %s, %s\n", nameISize(size),
nameIReg(size,ge_reg), nameIReg(size,ge_reg) );
}
} else {
assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
if (keep)
} else {
assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
if (keep)
} else {
assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
if (keep)
} else {
assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
if (keep)
assign(src, mkU(ty,lit));
assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
} else {
assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
}
} else {
assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
if (isAddSub(op8))
- setFlags_ADD_SUB(op8, src, dst0, ty);
+ setFlags_RES_AUX(op8, dst1, src, ty);
else
setFlags_LOGIC(op8, dst1, ty);
}
/* 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_SRC, unop(Iop_64HIto32, mkexpr(r64)) ));
- stmt( IRStmt_Put( OFFB_CC_DST, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_RES, unop(Iop_64HIto32, mkexpr(r64)) ));
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
}
if (isShift) {
mkU8(31))) );
/* Build the flags thunk. */
- setFlags_DSTus_DST1(op32, res32ss, res32, ty, shift_amt);
+ setFlags_RES_RESus(op32, res32, res32ss, ty, shift_amt);
/* Narrow the result back down. */
assign( dst1, narrowTo(ty, mkexpr(res32)) );
assign(oldFlags, mk_calculate_eflags_all());
- /* CC_DST is the rotated value. CC_SRC is flags before. */
+ /* CC_RES is the rotated value. CC_AUX 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_DST,
+ stmt( IRStmt_Put( OFFB_CC_RES,
IRExpr_Mux0X( mkexpr(rot_amt32),
- IRExpr_Get(OFFB_CC_DST,Ity_I32),
+ IRExpr_Get(OFFB_CC_RES,Ity_I32),
widenUto32(mkexpr(dst1)))) );
- stmt( IRStmt_Put( OFFB_CC_SRC,
+ stmt( IRStmt_Put( OFFB_CC_AUX,
IRExpr_Mux0X( mkexpr(rot_amt32),
- IRExpr_Get(OFFB_CC_SRC,Ity_I32),
+ IRExpr_Get(OFFB_CC_AUX,Ity_I32),
mkexpr(oldFlags))) );
} /* if (isRotate) */
switch (ty) {
case Ity_I32: {
IRTemp res64 = newTemp(Ity_I64);
+ IRTemp resHi = newTemp(Ity_I32);
+ 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)) );
- putIReg(4, R_EDX, unop(Iop_64HIto32,mkexpr(res64)));
- putIReg(4, R_EAX, unop(Iop_64to32,mkexpr(res64)));
+ 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;
}
case Ity_I16: {
IRTemp res32 = newTemp(Ity_I32);
+ IRTemp resHi = newTemp(Ity_I16);
+ 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)) );
- putIReg(2, R_EDX, unop(Iop_32HIto16,mkexpr(res32)));
- putIReg(2, R_EAX, unop(Iop_32to16,mkexpr(res32)));
+ 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;
}
case Ity_I8: {
IRTemp res16 = newTemp(Ity_I16);
+ IRTemp resHi = newTemp(Ity_I8);
+ 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;
}
assign(dst0, mkU(ty,0));
assign(src, getIReg(sz,eregOfRM(modrm)));
assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src)));
- setFlags_ADD_SUB(Iop_Sub8, src, dst0, ty);
+ setFlags_RES_AUX(Iop_Sub8, dst1, src, ty);
putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
break;
assign(dst0, mkU(ty,0));
assign(src, mkexpr(t1));
assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src)));
- setFlags_ADD_SUB(Iop_Sub8, src, dst0, ty);
+ setFlags_RES_AUX(Iop_Sub8, dst1, src, ty);
storeLE( mkexpr(addr), mkexpr(dst1) );
DIP("neg%c %s\n", nameISize(sz), dis_buf);
break;
IRType ty = szToITy(sz);
IRTemp tdv = newTemp(ty); /* (EDI) */
IRTemp tsv = newTemp(ty); /* (ESI) */
+ IRTemp res = newTemp(ty);
IRTemp td = newTemp(Ity_I32); /* EDI */
IRTemp ts = newTemp(Ity_I32); /* ESI */
//uInstr2(cb, SUB, sz, TempReg, tdv, TempReg, tsv);
//setFlagsFromUOpcode(cb, SUB);
- setFlags_ADD_SUB ( Iop_Sub8, tdv, tsv, ty );
+ assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(tsv), mkexpr(tdv)) );
+ setFlags_RES_AUX ( Iop_Sub8, res, tdv, ty );
//uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td);
//uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, ts);
IRTemp ta = newTemp(ty); /* EAX */
IRTemp td = newTemp(Ity_I32); /* EDI */
IRTemp tdv = newTemp(ty); /* (EDI) */
+ IRTemp res = newTemp(ty);
//uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta);
assign( ta, getIReg(sz, R_EAX) );
//uInstr2(cb, SUB, sz, TempReg, tdv, TempReg, ta);
//setFlagsFromUOpcode(cb, SUB);
- setFlags_ADD_SUB( Iop_Sub8, tdv, ta, ty );
+ assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(ta), mkexpr(tdv)) );
+ setFlags_RES_AUX ( Iop_Sub8, res, tdv, ty );
//uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td);
//uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI);
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)) {
- assign( tg, getIReg(size, gregOfRM(rm)) );
assign( te, getIReg(size, eregOfRM(rm)) );
- setFlags_MUL ( ty, te, tg, syned ? CC_OP_SMULB : CC_OP_UMULB );
- putIReg(size, gregOfRM(rm),
- binop(mkSizedOp(ty,Iop_Mul8),
- mkexpr(te), mkexpr(tg)));
+ } else {
+ IRTemp addr = disAMode( &alen, sorb, delta0, dis_buf );
+ 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, resHi, resLo, syned ? CC_OP_SMULB : CC_OP_UMULB );
+ 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)));
return 1+delta0;
} else {
- IRTemp addr = disAMode( &alen, sorb, delta0, dis_buf );
- assign( tg, getIReg(size, gregOfRM(rm)) );
- assign( te, loadLE(ty,mkexpr(addr)) );
- setFlags_MUL ( ty, te, tg, syned ? CC_OP_SMULB : CC_OP_UMULB );
- putIReg(size, gregOfRM(rm),
- binop(mkSizedOp(ty,Iop_Mul8),
- mkexpr(te), mkexpr(tg)));
-
DIP("%smul%c %s, %s\n", syned ? "i" : "",
nameISize(size),
dis_buf, nameIReg(size,gregOfRM(rm)));
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);
if (size == 2) d32 &= 0xFFFF;
assign(tl, mkU(ty,d32));
- setFlags_MUL ( ty, te, tl, CC_OP_SMULB );
- putIReg(size, gregOfRM(rm),
- binop(mkSizedOp(ty,Iop_Mul8),
- mkexpr(te), mkexpr(tl)));
+
+ 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) ));
+
+ setFlags_MUL ( ty, resHi, resLo, CC_OP_SMULB );
+
+ putIReg(size, gregOfRM(rm), mkexpr(resLo));
DIP("imul %d, %s, %s\n", d32,
( epartIsReg(rm) ? nameIReg(size,eregOfRM(rm)) : dis_buf ),
nameIReg(size,gregOfRM(rm)) );
return delta;
-}
+}
/*------------------------------------------------------------*/
documentation implies A and S are unchanged.
*/
stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) ));
- stmt( IRStmt_Put( OFFB_CC_DST, mkU32(0) ));
- stmt( IRStmt_Put( OFFB_CC_SRC,
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_RES,
binop( Iop_And32,
binop(Iop_CmpF64, get_ST(0), get_ST(i)),
mkU32(0x45)
binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
mask))) );
- setFlags_DSTus_DST1 ( left_shift ? Iop_Shl32 : Iop_Sar32,
- tmpSubSh, tmpRes, ty, tmpSH );
+ setFlags_RES_RESus ( left_shift ? Iop_Shl32 : Iop_Sar32,
+ tmpRes, tmpSubSh, ty, tmpSH );
/* Put result back. */
/* 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_DST, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
stmt( IRStmt_Put(
- OFFB_CC_SRC,
+ OFFB_CC_RES,
binop(Iop_And32,
binop(Iop_Shr32,
unop(Iop_8Uto32, mkexpr(t_fetched)),
/* 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_DST, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
stmt( IRStmt_Put(
- OFFB_CC_SRC,
+ OFFB_CC_RES,
IRExpr_Mux0X( mkexpr(src8),
/* src==0 */
mkU32(CC_MASK_Z),
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_DST, mkU32(0) ));
- stmt( IRStmt_Put( OFFB_CC_SRC,
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_RES,
binop(Iop_Or32,
binop(Iop_And32, mkexpr(oldflags), mkU32(CC_MASK_O)),
binop(Iop_And32,
IRType ty = szToITy(size);
IRTemp acc = newTemp(ty);
IRTemp src = newTemp(ty);
+ IRTemp res = newTemp(ty);
IRTemp dest = newTemp(ty);
IRTemp dest2 = newTemp(ty);
IRTemp acc2 = newTemp(ty);
assign( src, getIReg(size, gregOfRM(rm)) );
assign( acc, getIReg(size, R_EAX) );
- setFlags_ADD_SUB(Iop_Sub8, dest, acc, ty);
+ assign( res, binop( mkSizedOp(ty,Iop_Sub8), mkexpr(acc), mkexpr(dest) ));
+ setFlags_RES_AUX(Iop_Sub8, res, 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)) );
IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
assign( tmpd, loadLE(ty, mkexpr(addr)) );
assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
- setFlags_ADD_SUB( Iop_Add8, tmpt0, tmpd, ty );
assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8), mkexpr(tmpd), mkexpr(tmpt0)) );
+ setFlags_RES_AUX( Iop_Add8, tmpt1, tmpt0, ty );
storeLE( mkexpr(addr), mkexpr(tmpt1) );
putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
DIP("xadd%c %s, %s\n",
/* 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_DST, mkU32(0) ));
- stmt( IRStmt_Put( OFFB_CC_SRC,
+ stmt( IRStmt_Put( OFFB_CC_AUX, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_RES,
binop(Iop_And32,
mkexpr(t1),
mkU32( CC_MASK_C | CC_MASK_P | CC_MASK_A