📄 ghelpers.c
字号:
} 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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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)); } if (isU32(cc_op, X86G_CC_OP_SUBL) && isU32(cond, X86CondS)) { /* long sub/cmp, then S --> test (dst-src <s 0) */ return unop(Iop_1Uto32, binop(Iop_CmpLT32S, binop(Iop_Sub32, cc_dep1, cc_dep2), mkU32(0))); } /*---------------- SUBW ----------------*/ if (isU32(cc_op, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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, X86G_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(X86G_CC_SHIFT_C)), binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)) ), mkU32(1) ), mkU32(nnn) ) ); } if (isU32(cc_op, X86G_CC_OP_COPY) && (isU32(cond, X86CondB) || isU32(cond, X86CondNB))) { /* COPY, then B --> extract C from dep1, and test (C == 1). */ /* COPY, then NB --> extract C from dep1, and test (C == 0). */ UInt nnn = isU32(cond, X86CondB) ? 1 : 0; return unop( Iop_1Uto32, binop( Iop_CmpEQ32, binop( Iop_And32, binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_C)), mkU32(1) ), mkU32(nnn) ) ); } if (isU32(cc_op, X86G_CC_OP_COPY) && isU32(cond, X86CondZ)) { /* COPY, then Z --> extract Z from dep1, and test (Z == 1). */ return unop( Iop_1Uto32, binop( Iop_CmpNE32, binop( Iop_And32, binop(Iop_Shr32, cc_dep1, mkU8(X86G_CC_SHIFT_Z)), 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, X86G_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, X86G_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, X86G_CC_OP_LOGICL) || isU32(cc_op, X86G_CC_OP_LOGICW) || isU32(cc_op, X86G_CC_OP_LOGICB)) { /* cflag after logic is zero */ return mkU32(0); } if (isU32(cc_op, X86G_CC_OP_DECL) || isU32(cc_op, X86G_CC_OP_INCL)) { /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */ return cc_ndep; } if (isU32(cc_op, X86G_CC_OP_COPY)) { /* cflag after COPY is stored in DEP1. */ return binop( Iop_And32, binop(Iop_Shr32, cc_dep1, mkU8(X86G_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, X86G_CC_OP_COPY)) { /* eflags after COPY are stored in DEP1. */ return binop( Iop_And32, cc_dep1, mkU32(X86G_CC_MASK_O | X86G_CC_MASK_S | X86G_CC_MASK_Z | X86G_CC_MASK_A | X86G_CC_MASK_C | X86G_CC_MASK_P) ); } return NULL; }# undef unop# undef binop# undef mkU32# undef mkU8 return NULL;}/*---------------------------------------------------------------*//*--- Supporting functions for x87 FPU activities. ---*//*---------------------------------------------------------------*/static inline Bool host_is_little_endian ( void ){ UInt x = 0x76543210; UChar* p = (UChar*)(&x); return toBool(*p == 0x10);}/* 80 and 64-bit floating point formats: 80-bit: S 0 0-------0 zero S 0 0X------X denormals S 1-7FFE 1X------X normals (all normals have leading 1) S 7FFF 10------0 infinity S 7FFF 10X-----X snan S 7FFF 11X-----X qnan S is the sign bit. For runs X----X, at least one of the Xs must be nonzero. Exponent is 15 bits, fractional part is 63 bits, and there is an explicitly represented leading 1, and a sign bit, giving 80 in total. 64-bit avoids the confusion of an explicitly represented leading 1 and so is simpler: S 0 0------0 zero S 0 X------X denormals S 1-7FE any normals S 7FF 0------0 infinity S 7FF 0X-----X snan S 7FF 1X-----X qnan Exponent is 11 bits, fractional part is 52 bits, and there is a sign bit, giving 64 in total.*//* Inspect a value and its tag, as per the x87 'FXAM' instruction. *//* CALLED FROM GENERATED CODE: CLEAN HELPER */UInt x86g_calculate_FXAM ( UInt tag, ULong dbl ) { Bool mantissaIsZero; Int bexp; UChar sign; UChar* f64; vassert(host_is_little_endian()); /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -