📄 ghelpers.c
字号:
LOGIC sets SF and ZF according to the result and makes OF be zero. L computes SF ^ OF, but OF is zero, so this reduces to SF -- which will be 1 iff the result is < signed 0. Hence ... */ return unop(Iop_1Uto64, binop(Iop_CmpLT64S, cc_dep1, mkU64(0))); } /*---------------- LOGICL ----------------*/ if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) { /* long and/or/xor, then Z --> test dst==0 */ return unop(Iop_1Uto64, binop(Iop_CmpEQ64, binop(Iop_Shl64,cc_dep1,mkU8(32)), mkU64(0))); } if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondNZ)) { /* long and/or/xor, then NZ --> test dst!=0 */ return unop(Iop_1Uto64, binop(Iop_CmpNE64, binop(Iop_Shl64,cc_dep1,mkU8(32)), mkU64(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 (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondLE)) { /* 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 (SF ^ OF) | ZF, but OF is zero, so this reduces to SF | ZF -- which will be 1 iff the result is <=signed 0. Hence ... */ return unop(Iop_1Uto64, binop(Iop_CmpLE64S, binop(Iop_Shl64,cc_dep1,mkU8(32)), mkU64(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 (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondZ)) { /* byte and/or/xor, then Z --> test dst==0 */ return unop(Iop_1Uto64, binop(Iop_CmpEQ64, binop(Iop_And64,cc_dep1,mkU64(255)), mkU64(0))); } if (isU64(cc_op, AMD64G_CC_OP_LOGICB) && isU64(cond, AMD64CondS)) { /* this is an idiom gcc sometimes uses to find out if the top bit of a byte register is set: eg testb %al,%al; js .. Since it just depends on the top bit of the byte, extract that bit and explicitly get rid of all the rest. This helps memcheck avoid false positives in the case where any of the other bits in the byte are undefined. */ /* byte and/or/xor, then S --> (UInt)result[7] */ return binop(Iop_And64, binop(Iop_Shr64,cc_dep1,mkU8(7)), mkU64(1)); } /*---------------- INCB ----------------*/ if (isU64(cc_op, AMD64G_CC_OP_INCB) && isU64(cond, AMD64CondLE)) { /* 8-bit inc, then LE --> test result <=s 0 */ return unop(Iop_1Uto64, binop(Iop_CmpLE64S, binop(Iop_Shl64,cc_dep1,mkU8(56)), mkU64(0))); } /*---------------- DECL ----------------*/ if (isU64(cc_op, AMD64G_CC_OP_DECL) && isU64(cond, AMD64CondZ)) { /* dec L, then Z --> test dst == 0 */ return unop(Iop_1Uto64, binop(Iop_CmpEQ64, binop(Iop_Shl64,cc_dep1,mkU8(32)), mkU64(0))); } /*---------------- DECW ----------------*/ if (isU64(cc_op, AMD64G_CC_OP_DECW) && isU64(cond, AMD64CondNZ)) { /* 16-bit dec, then NZ --> test dst != 0 */ return unop(Iop_1Uto64, binop(Iop_CmpNE64, binop(Iop_Shl64,cc_dep1,mkU8(48)), mkU64(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 amd64 FP compares: "comisd ... ; jbe" for example. */ if (isU64(cc_op, AMD64G_CC_OP_COPY) && (isU64(cond, AMD64CondBE) || isU64(cond, AMD64CondNBE))) { /* 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). */ ULong nnn = isU64(cond, AMD64CondBE) ? 1 : 0; return unop( Iop_1Uto64, binop( Iop_CmpEQ64, binop( Iop_And64, binop( Iop_Or64, binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z)) ), mkU64(1) ), mkU64(nnn) ) ); } if (isU64(cc_op, AMD64G_CC_OP_COPY) && isU64(cond, AMD64CondB)) { /* COPY, then B --> extract C dep1, and test (C == 1). */ return unop( Iop_1Uto64, binop( Iop_CmpNE64, binop( Iop_And64, binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)), mkU64(1) ), mkU64(0) ) ); } return NULL; } /* --------- specialising "amd64g_calculate_rflags_c" --------- */ if (vex_streq(function_name, "amd64g_calculate_rflags_c")) { /* specialise calls to above "calculate_rflags_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 (isU64(cc_op, AMD64G_CC_OP_SUBQ)) { /* C after sub denotes unsigned less than */ return unop(Iop_1Uto64, binop(Iop_CmpLT64U, cc_dep1, cc_dep2)); } if (isU64(cc_op, AMD64G_CC_OP_SUBL)) { /* C after sub denotes unsigned less than */ return unop(Iop_1Uto64, binop(Iop_CmpLT64U, binop(Iop_Shl64,cc_dep1,mkU8(32)), binop(Iop_Shl64,cc_dep2,mkU8(32)))); } if (isU64(cc_op, AMD64G_CC_OP_SUBB)) { /* C after sub denotes unsigned less than */ return unop(Iop_1Uto64, binop(Iop_CmpLT64U, binop(Iop_And64,cc_dep1,mkU64(0xFF)), binop(Iop_And64,cc_dep2,mkU64(0xFF)))); } if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) || isU64(cc_op, AMD64G_CC_OP_LOGICL) || isU64(cc_op, AMD64G_CC_OP_LOGICW) || isU64(cc_op, AMD64G_CC_OP_LOGICB)) { /* cflag after logic is zero */ return mkU64(0); } if (isU64(cc_op, AMD64G_CC_OP_DECL) || isU64(cc_op, AMD64G_CC_OP_INCL) || isU64(cc_op, AMD64G_CC_OP_DECQ) || isU64(cc_op, AMD64G_CC_OP_INCQ)) { /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */ return cc_ndep; }//.. if (isU64(cc_op, AMD64G_CC_OP_COPY)) {//.. /* cflag after COPY is stored in DEP1. *///.. return//.. binop(//.. Iop_And64,//.. binop(Iop_Shr64, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),//.. mkU64(1)//.. );//.. }//.. # if 0//.. if (cc_op->tag == Iex_Const) {//.. vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");//.. }//.. # endif return NULL; }//.. /* --------- specialising "x86g_calculate_rflags_all" --------- *///.. //.. if (vex_streq(function_name, "x86g_calculate_rflags_all")) {//.. /* specialise calls to above "calculate_rflags_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 mkU64# 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);}/* Inspect a value and its tag, as per the x87 'FXAM' instruction. *//* CALLED FROM GENERATED CODE: CLEAN HELPER */ULong amd64g_calculate_FXAM ( ULong tag, ULong dbl ) { Bool mantissaIsZero; Int bexp; UChar sign; UChar* f64; vassert(host_is_little_endian()); /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */ f64 = (UChar*)(&dbl); sign = toUChar( (f64[7] >> 7) & 1 ); /* First off, if the tag indicates the register was empty, return 1,0,sign,1 */ if (tag == 0) { /* vex_printf("Empty\n"); */ return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0; } bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F); bexp &= 0x7FF; mantissaIsZero = toBool( (f64[6] & 0x0F) == 0 && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0 ); /* If both exponent and mantissa are zero, the value is zero. Return 1,0,sign,0. */ if (bexp == 0 && mantissaIsZero) { /* vex_printf("Zero\n"); */ return AMD64G_FC_MASK_C3 | 0 | (sign << AMD64G_FC_SHIFT_C1) | 0; } /* If exponent is zero but mantissa isn't, it's a denormal. Return 1,1,sign,0. */ if (bexp == 0 && !mantissaIsZero) { /* vex_printf("Denormal\n"); */ return AMD64G_FC_MASK_C3 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0; } /* If the exponent is 7FF and the mantissa is zero, this is an infinity. Return 0,1,sign,1. */ if (bexp == 0x7FF && mantissaIsZero) { /* vex_printf("Inf\n"); */ return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0; } /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN. Return 0,0,sign,1. */ if (bexp == 0x7FF && !mantissaIsZero) { /* vex_printf("NaN\n"); */ return 0 | 0 | (sign << AMD64G_FC_SHIFT_C1) | AMD64G_FC_MASK_C0; } /* Uh, ok, we give up. It must be a normal finite number. Return 0,1,sign,0. */ /* vex_printf("normal\n"); */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -