📄 ghelpers.c
字号:
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 ); */ 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 X86G_FC_MASK_C3 | 0 | (sign << X86G_FC_SHIFT_C1) | X86G_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 X86G_FC_MASK_C3 | 0 | (sign << X86G_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 X86G_FC_MASK_C3 | X86G_FC_MASK_C2 | (sign << X86G_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 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1) | X86G_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 << X86G_FC_SHIFT_C1) | X86G_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 | X86G_FC_MASK_C2 | (sign << X86G_FC_SHIFT_C1) | 0;}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (reads guest memory) */ULong x86g_dirtyhelper_loadF80le ( UInt 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 x86g_dirtyhelper_storeF80le ( UInt addrU, ULong f64 ){ convert_f64le_to_f80le( (UChar*)&f64, (UChar*)ULong_to_Ptr(addrU) );}/*----------------------------------------------*//*--- The exported fns .. ---*//*----------------------------------------------*//* Layout of the real x87 state. *//* 13 June 05: Fpu_State and auxiliary constants was moved to g_generic_x87.h *//* 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 x86g_check_fldcw ( UInt fpucw ){ /* Decide on a rounding mode. fpucw[11:10] holds it. */ /* NOTE, encoded exactly as per enum IRRoundingMode. */ UInt 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. */UInt x86g_create_fpucw ( UInt fpround ){ fpround &= 3; return 0x037F | (fpround << 10);}/* 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 x86g_check_ldmxcsr ( UInt mxcsr ){ /* Decide on a rounding mode. mxcsr[14:13] holds it. */ /* NOTE, encoded exactly as per enum IRRoundingMode. */ UInt 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);}/* CLEAN HELPER *//* Given sseround as an IRRoundingMode value, create a suitable SSE native format MXCSR value. */UInt x86g_create_mxcsr ( UInt sseround ){ sseround &= 3; return 0x1F80 | (sseround << 13);}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (writes guest state) *//* Initialise the x87 FPU state as per 'finit'. */void x86g_dirtyhelper_FINIT ( VexGuestX86State* 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 = (UInt)Irrm_NEAREST; gst->guest_FC3210 = 0;}/* This is used to implement both 'frstor' and 'fldenv'. The latter appears to differ from the former only in that the 8 FP registers themselves are not transferred into the guest state. */staticVexEmWarn do_put_x87 ( Bool moveRegs, /*IN*/UChar* x87_state, /*OUT*/VexGuestX86State* vex_state ){ Int stno, preg; UInt tag; ULong* vexRegs = (ULong*)(&vex_state->guest_FPREG[0]); 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]; UInt c3210 = x87->env[FP_ENV_STAT] & 0x4700; VexEmWarn ew; UInt fpround; ULong pair; /* Copy registers and tags */ for (stno = 0; stno < 8; stno++) { preg = (stno + ftop) & 7; tag = (tagw >> (2*preg)) & 3; if (tag == 3) { /* register is empty */ /* hmm, if it's empty, does it still get written? Probably safer to say it does. If we don't, memcheck could get out of sync, in that it thinks all FP registers are defined by this helper, but in reality some have not been updated. */ if (moveRegs) vexRegs[preg] = 0; /* IEEE754 64-bit zero */ vexTags[preg] = 0; } else { /* register is non-empty */ if (moveRegs) convert_f80le_to_f64le( &x87->reg[10*stno], (UChar*)&vexRegs[preg] ); vexTags[preg] = 1; } } /* stack pointer */ vex_state->guest_FTOP = ftop;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -