From: Julian Seward Date: Sun, 24 Oct 2004 19:20:43 +0000 (+0000) Subject: x86 guest: support rcr{bwl}. Includes some cleaning up of macro X-Git-Tag: svn/VALGRIND_3_0_1^2~928 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37cc0ace4ae8661c34f2a638aa98bf1366bf4328;p=thirdparty%2Fvalgrind.git x86 guest: support rcr{bwl}. Includes some cleaning up of macro definitions in gdefs.h and ghelpers.c. git-svn-id: svn://svn.valgrind.org/vex/trunk@406 --- diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 758fe68372..a1d84c9e06 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -42,12 +42,19 @@ IRExpr* x86guest_spechelper ( Char* function_name, /*---------------------------------------------------------*/ /* eflags masks */ -#define CC_MASK_C 0x0001 -#define CC_MASK_P 0x0004 -#define CC_MASK_A 0x0010 -#define CC_MASK_Z 0x0040 -#define CC_MASK_S 0x0080 -#define CC_MASK_O 0x0800 +#define CC_SHIFT_O 11 +#define CC_SHIFT_S 7 +#define CC_SHIFT_Z 6 +#define CC_SHIFT_A 4 +#define CC_SHIFT_C 0 +#define CC_SHIFT_P 2 + +#define CC_MASK_O (1 << CC_SHIFT_O) +#define CC_MASK_S (1 << CC_SHIFT_S) +#define CC_MASK_Z (1 << CC_SHIFT_Z) +#define CC_MASK_A (1 << CC_SHIFT_A) +#define CC_MASK_C (1 << CC_SHIFT_C) +#define CC_MASK_P (1 << CC_SHIFT_P) /* FPU flag masks */ #define FC_MASK_C3 (1 << 14) diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 1717a7dc55..7dea804603 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -14,11 +14,16 @@ #include "guest-x86/gdefs.h" /* --- Forwardses --- */ - UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst ); -static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ); -static UInt calculate_condition ( UInt/*Condcode*/ cond, - UInt cc_op, UInt cc_src, UInt cc_dst ); -static UInt calculate_FXAM ( UInt tag, ULong dbl ); + +/* --- CLEAN HELPERS --- */ +static UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst ); +static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ); +static UInt calculate_condition ( UInt/*Condcode*/ cond, + UInt cc_op, UInt cc_src, UInt cc_dst ); +static UInt calculate_FXAM ( UInt tag, ULong dbl ); +static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ); + +/* --- DIRTY HELPERS --- */ static ULong loadF80le ( UInt ); static void storeF80le ( UInt, ULong ); @@ -49,44 +54,40 @@ static void storeF80le ( UInt, ULong ); typedef UChar uint8_t; typedef UInt uint32_t; -#define CC_O CC_MASK_O -#define CC_P CC_MASK_P -#define CC_C CC_MASK_C - static const uint8_t parity_table[256] = { - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + CC_MASK_P, 0, 0, CC_MASK_P, 0, CC_MASK_P, CC_MASK_P, 0, + 0, CC_MASK_P, CC_MASK_P, 0, CC_MASK_P, 0, 0, CC_MASK_P, }; /* n must be a constant to be efficient */ @@ -131,7 +132,7 @@ inline static Int lshift ( Int x, Int n ) zf = ((DATA_UTYPE)dst == 0) << 6; \ sf = lshift(dst, 8 - DATA_BITS) & 0x80; \ of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), \ - 12 - DATA_BITS) & CC_O; \ + 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -151,7 +152,7 @@ inline static Int lshift ( Int x, Int n ) zf = ((DATA_UTYPE)dst == 0) << 6; \ sf = lshift(dst, 8 - DATA_BITS) & 0x80; \ of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), \ - 12 - DATA_BITS) & CC_O; \ + 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -171,7 +172,7 @@ inline static Int lshift ( Int x, Int n ) zf = ((DATA_UTYPE)dst == 0) << 6; \ sf = lshift(dst, 8 - DATA_BITS) & 0x80; \ of = lshift((src1 ^ src2) & (src1 ^ dst), \ - 12 - DATA_BITS) & CC_O; \ + 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -191,7 +192,7 @@ inline static Int lshift ( Int x, Int n ) zf = ((DATA_UTYPE)dst == 0) << 6; \ sf = lshift(dst, 8 - DATA_BITS) & 0x80; \ of = lshift((src1 ^ src2) & (src1 ^ dst), \ - 12 - DATA_BITS) & CC_O; \ + 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -253,13 +254,13 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ int cf, pf, af, zf, sf, of; \ - cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C; \ + cf = (CC_SRC >> (DATA_BITS - 1)) & CC_MASK_C; \ pf = parity_table[(uint8_t)CC_DST]; \ af = 0; /* undefined */ \ zf = ((DATA_UTYPE)CC_DST == 0) << 6; \ sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \ /* of is defined if shift count == 1 */ \ - of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; \ + of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -275,7 +276,7 @@ inline static Int lshift ( Int x, Int n ) zf = ((DATA_UTYPE)CC_DST == 0) << 6; \ sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \ /* of is defined if shift count == 1 */ \ - of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O; \ + of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_MASK_O; \ return cf | pf | af | zf | sf | of; \ } @@ -287,9 +288,9 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ int fl \ - = (CC_SRC & ~(CC_O | CC_C)) \ - | (CC_C & CC_DST) \ - | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1)) \ + = (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))); \ return fl; \ } @@ -302,9 +303,9 @@ inline static Int lshift ( Int x, Int n ) { \ PREAMBLE(DATA_BITS); \ int fl \ - = (CC_SRC & ~(CC_O | CC_C)) \ - | (CC_C & (CC_DST >> (DATA_BITS-1))) \ - | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1)) \ + = (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))); \ return fl; \ } @@ -414,9 +415,9 @@ static void initCounts ( void ) #endif /* PROFILE_EFLAGS */ -/* CALLED FROM GENERATED CODE */ +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate all the 6 flags from the supplied thunk parameters. */ -/*static*/ +static UInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal ) { # if PROFILE_EFLAGS @@ -489,7 +490,7 @@ UInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal ) } -/* CALLED FROM GENERATED CODE */ +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate just the carry flag from the supplied thunk parameters. */ static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ) { @@ -523,7 +524,7 @@ static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ) } -/* CALLED FROM GENERATED CODE */ +/* 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 ) @@ -614,6 +615,8 @@ Addr64 x86guest_findhelper ( Char* function_name ) return (Addr64)(Addr32)(& storeF80le); if (vex_streq(function_name, "loadF80le")) return (Addr64)(Addr32)(& loadF80le); + if (vex_streq(function_name, "calculate_RCR")) + return (Addr64)(Addr32)(& calculate_RCR); vex_printf("\nx86 guest: can't find helper: %s\n", function_name); vpanic("x86guest_findhelper"); } @@ -857,6 +860,7 @@ static inline Bool host_is_little_endian ( void ) return (*p == 0x10); } +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ static UInt calculate_FXAM ( UInt tag, ULong dbl ) { Bool mantissaIsZero; @@ -1355,6 +1359,64 @@ void vex_initialise_x87 ( /* MOD*/VexGuestX86State* vex_state ) } +/*----------------------------------------------*/ +/*--- Misc integer helpers ---*/ +/*----------------------------------------------*/ + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +/* Calculate both flags and value result for rotate right + through the carry bit. Result in low 32 bits, + new flags (OSZACP) in high 32 bits. +*/ +static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ) +{ + UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf; + + switch (sz) { + case 4: + cf = (eflags_in >> CC_SHIFT_C) & 1; + of = ((arg >> 31) ^ cf) & 1; + while (tempCOUNT > 0) { + tempcf = arg & 1; + arg = (arg >> 1) | (cf << 31); + cf = tempcf; + tempCOUNT--; + } + break; + case 2: + while (tempCOUNT >= 17) tempCOUNT -= 17; + cf = (eflags_in >> CC_SHIFT_C) & 1; + of = ((arg >> 15) ^ cf) & 1; + while (tempCOUNT > 0) { + tempcf = arg & 1; + arg = ((arg >> 1) & 0x7FFF) | (cf << 15); + cf = tempcf; + tempCOUNT--; + } + break; + case 1: + while (tempCOUNT >= 9) tempCOUNT -= 9; + cf = (eflags_in >> CC_SHIFT_C) & 1; + of = ((arg >> 7) ^ cf) & 1; + while (tempCOUNT > 0) { + tempcf = arg & 1; + arg = ((arg >> 1) & 0x7F) | (cf << 7); + cf = tempcf; + tempCOUNT--; + } + break; + default: + vpanic("calculate_RCR: invalid size"); + } + + cf &= 1; + of &= 1; + eflags_in &= ~(CC_MASK_C | CC_MASK_O); + eflags_in |= (cf << CC_SHIFT_C) | (of << CC_SHIFT_O); + + return (((ULong)eflags_in) << 32) | ((ULong)arg); +} + /*---------------------------------------------------------------*/ /*--- end guest-x86/ghelpers.c ---*/ /*---------------------------------------------------------------*/ diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index a8c439b8eb..181cbd5a38 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -2296,7 +2296,7 @@ UInt dis_Grp2 ( UChar sorb, /* delta on entry points at the modrm byte. */ UChar dis_buf[50]; Int len; - Bool isShift, isRotate; + Bool isShift, isRotate, isRotateRC; IRType ty = szToITy(sz); IRTemp dst0 = newTemp(ty); IRTemp dst1 = newTemp(ty); @@ -2320,11 +2320,31 @@ UInt dis_Grp2 ( UChar sorb, isRotate = False; switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; } - if (!isShift && !isRotate) { + isRotateRC = gregOfRM(modrm) == 3; + + if (!isShift && !isRotate && !isRotateRC) { vex_printf("\ncase %d\n", gregOfRM(modrm)); vpanic("dis_Grp2(Reg): unhandled case(x86)"); } + if (isRotateRC) { + /* call a helper; this insn is so ridiculous it does not deserve + better */ + IRTemp r64 = newTemp(Ity_I64); + IRExpr** args = LibVEX_Alloc(5 * sizeof(IRExpr*)); + args[0] = widenUto32(mkexpr(dst0)); /* thing to rotate */ + args[1] = widenUto32(shift_expr); /* rotate amount */ + args[2] = widenUto32(mk_calculate_eflags_all()); + args[3] = mkU32(sz); + args[4] = NULL; + assign( r64, IRExpr_CCall("calculate_RCR", Ity_I64, args) ); + /* 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) )); + } + if (isShift) { IRTemp pre32 = newTemp(Ity_I32);