📄 ghelpers.c
字号:
/* 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_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"); */ return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0;}// MAYBE NOT TRUE: /* CALLED FROM GENERATED CODE */// MAYBE NOT TRUE: /* DIRTY HELPER (writes guest state) *//* Initialise the x87 FPU state as per 'finit'. */staticvoid amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst ){ Int i; gst->guest_FTOP = 0; for (i = 0; i < 8; i++) { gst->guest_FPTAG[i] = 0; /* empty */ gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */ } gst->guest_FPROUND = (ULong)Irrm_NEAREST; gst->guest_FC3210 = 0;}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (reads guest memory) */ULong amd64g_loadF80le ( ULong addrU ){ ULong f64; convert_f80le_to_f64le ( (UChar*)ULong_to_Ptr(addrU), (UChar*)&f64 ); return f64;}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (writes guest memory) */void amd64g_storeF80le ( ULong addrU, ULong f64 ){ convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );}/* CALLED FROM GENERATED CODE *//* CLEAN HELPER *//* mxcsr[15:0] contains a SSE native format MXCSR value. Extract from it the required SSEROUND value and any resulting emulation warning, and return (warn << 32) | sseround value.*/ULong amd64g_check_ldmxcsr ( ULong mxcsr ){ /* Decide on a rounding mode. mxcsr[14:13] holds it. */ /* NOTE, encoded exactly as per enum IRRoundingMode. */ ULong rmode = (mxcsr >> 13) & 3; /* Detect any required emulation warnings. */ VexEmWarn ew = EmWarn_NONE; if ((mxcsr & 0x1F80) != 0x1F80) { /* unmasked exceptions! */ ew = EmWarn_X86_sseExns; } else if (mxcsr & (1<<15)) { /* FZ is set */ ew = EmWarn_X86_fz; } else if (mxcsr & (1<<6)) { /* DAZ is set */ ew = EmWarn_X86_daz; } return (((ULong)ew) << 32) | ((ULong)rmode);}/* CALLED FROM GENERATED CODE *//* CLEAN HELPER *//* Given sseround as an IRRoundingMode value, create a suitable SSE native format MXCSR value. */ULong amd64g_create_mxcsr ( ULong sseround ){ sseround &= 3; return 0x1F80 | (sseround << 13);}/* CLEAN HELPER *//* fpucw[15:0] contains a x87 native format FPU control word. Extract from it the required FPROUND value and any resulting emulation warning, and return (warn << 32) | fpround value.*/ULong amd64g_check_fldcw ( ULong fpucw ){ /* Decide on a rounding mode. fpucw[11:10] holds it. */ /* NOTE, encoded exactly as per enum IRRoundingMode. */ ULong rmode = (fpucw >> 10) & 3; /* Detect any required emulation warnings. */ VexEmWarn ew = EmWarn_NONE; if ((fpucw & 0x3F) != 0x3F) { /* unmasked exceptions! */ ew = EmWarn_X86_x87exns; } else if (((fpucw >> 8) & 3) != 3) { /* unsupported precision */ ew = EmWarn_X86_x87precision; } return (((ULong)ew) << 32) | ((ULong)rmode);}/* CLEAN HELPER *//* Given fpround as an IRRoundingMode value, create a suitable x87 native format FPU control word. */ULong amd64g_create_fpucw ( ULong fpround ){ fpround &= 3; return 0x037F | (fpround << 10);}/* This is used to implement 'fldenv'. Reads 28 bytes at x87_state[0 .. 27]. *//* CALLED FROM GENERATED CODE *//* DIRTY HELPER */VexEmWarn amd64g_dirtyhelper_FLDENV ( /*OUT*/VexGuestAMD64State* vex_state, /*IN*/HWord x87_state){ Int stno, preg; UInt tag; UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); Fpu_State* x87 = (Fpu_State*)x87_state; UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7; UInt tagw = x87->env[FP_ENV_TAG]; UInt fpucw = x87->env[FP_ENV_CTRL]; ULong c3210 = x87->env[FP_ENV_STAT] & 0x4700; VexEmWarn ew; ULong fpround; ULong pair; /* Copy tags */ for (stno = 0; stno < 8; stno++) { preg = (stno + ftop) & 7; tag = (tagw >> (2*preg)) & 3; if (tag == 3) { /* register is empty */ vexTags[preg] = 0; } else { /* register is non-empty */ vexTags[preg] = 1; } } /* stack pointer */ vex_state->guest_FTOP = ftop; /* status word */ vex_state->guest_FC3210 = c3210; /* handle the control word, setting FPROUND and detecting any emulation warnings. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -