📄 ghelpers.c
字号:
/* status word */ vex_state->guest_FC3210 = c3210; /* handle the control word, setting FPROUND and detecting any emulation warnings. */ pair = x86g_check_fldcw ( (UInt)fpucw ); fpround = (UInt)pair; ew = (VexEmWarn)(pair >> 32); vex_state->guest_FPROUND = fpround & 3; /* emulation warnings --> caller */ return ew;}/* Create an x87 FPU state from the guest state, as close as we can approximate it. */staticvoid do_get_x87 ( /*IN*/VexGuestX86State* vex_state, /*OUT*/UChar* x87_state ){ Int i, stno, preg; UInt tagw; 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 = vex_state->guest_FTOP; UInt c3210 = vex_state->guest_FC3210; for (i = 0; i < 14; i++) x87->env[i] = 0; x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF; x87->env[FP_ENV_STAT] = toUShort(((ftop & 7) << 11) | (c3210 & 0x4700)); x87->env[FP_ENV_CTRL] = toUShort(x86g_create_fpucw( vex_state->guest_FPROUND )); /* Dump the register stack in ST order. */ tagw = 0; for (stno = 0; stno < 8; stno++) { preg = (stno + ftop) & 7; if (vexTags[preg] == 0) { /* register is empty */ tagw |= (3 << (2*preg)); convert_f64le_to_f80le( (UChar*)&vexRegs[preg], &x87->reg[10*stno] ); } else { /* register is full. */ tagw |= (0 << (2*preg)); convert_f64le_to_f80le( (UChar*)&vexRegs[preg], &x87->reg[10*stno] ); } } x87->env[FP_ENV_TAG] = toUShort(tagw);}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (reads guest state, writes guest mem) */void x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr ){ /* Somewhat roundabout, but at least it's simple. */ Fpu_State tmp; UShort* addrS = (UShort*)addr; UChar* addrC = (UChar*)addr; U128* xmm = (U128*)(addr + 160); UInt mxcsr; UShort fp_tags; UInt summary_tags; Int r, stno; UShort *srcS, *dstS; do_get_x87( gst, (UChar*)&tmp ); mxcsr = x86g_create_mxcsr( gst->guest_SSEROUND ); /* Now build the proper fxsave image from the x87 image we just made. */ addrS[0] = tmp.env[FP_ENV_CTRL]; /* FCW: fpu control word */ addrS[1] = tmp.env[FP_ENV_STAT]; /* FCW: fpu status word */ /* set addrS[2] in an endian-independent way */ summary_tags = 0; fp_tags = tmp.env[FP_ENV_TAG]; for (r = 0; r < 8; r++) { if ( ((fp_tags >> (2*r)) & 3) != 3 ) summary_tags |= (1 << r); } addrC[4] = toUChar(summary_tags); /* FTW: tag summary byte */ addrC[5] = 0; /* pad */ addrS[3] = 0; /* FOP: fpu opcode (bogus) */ addrS[4] = 0; addrS[5] = 0; /* FPU IP (bogus) */ addrS[6] = 0; /* FPU IP's segment selector (bogus) (although we could conceivably dump %CS here) */ addrS[7] = 0; /* Intel reserved */ addrS[8] = 0; /* FPU DP (operand pointer) (bogus) */ addrS[9] = 0; /* FPU DP (operand pointer) (bogus) */ addrS[10] = 0; /* segment selector for above operand pointer; %DS perhaps? */ addrS[11] = 0; /* Intel reserved */ addrS[12] = toUShort(mxcsr); /* MXCSR */ addrS[13] = toUShort(mxcsr >> 16); addrS[14] = 0xFFFF; /* MXCSR mask (lo16); who knows what for */ addrS[15] = 0xFFFF; /* MXCSR mask (hi16); who knows what for */ /* Copy in the FP registers, in ST order. */ for (stno = 0; stno < 8; stno++) { srcS = (UShort*)(&tmp.reg[10*stno]); dstS = (UShort*)(&addrS[16 + 8*stno]); dstS[0] = srcS[0]; dstS[1] = srcS[1]; dstS[2] = srcS[2]; dstS[3] = srcS[3]; dstS[4] = srcS[4]; dstS[5] = 0; dstS[6] = 0; dstS[7] = 0; } /* That's the first 160 bytes of the image done. Now only %xmm0 .. %xmm7 remain to be copied. If the host is big-endian, these need to be byte-swapped. */ vassert(host_is_little_endian());# define COPY_U128(_dst,_src) \ do { _dst[0] = _src[0]; _dst[1] = _src[1]; \ _dst[2] = _src[2]; _dst[3] = _src[3]; } \ while (0) COPY_U128( xmm[0], gst->guest_XMM0 ); COPY_U128( xmm[1], gst->guest_XMM1 ); COPY_U128( xmm[2], gst->guest_XMM2 ); COPY_U128( xmm[3], gst->guest_XMM3 ); COPY_U128( xmm[4], gst->guest_XMM4 ); COPY_U128( xmm[5], gst->guest_XMM5 ); COPY_U128( xmm[6], gst->guest_XMM6 ); COPY_U128( xmm[7], gst->guest_XMM7 );# undef COPY_U128}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (reads guest state, writes guest mem) */void x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr ){ do_get_x87( gst, (UChar*)addr );}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (writes guest state, reads guest mem) */VexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr ){ return do_put_x87( True/*regs too*/, (UChar*)addr, gst );}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (reads guest state, writes guest mem) */void x86g_dirtyhelper_FSTENV ( VexGuestX86State* gst, HWord addr ){ /* Somewhat roundabout, but at least it's simple. */ Int i; UShort* addrP = (UShort*)addr; Fpu_State tmp; do_get_x87( gst, (UChar*)&tmp ); for (i = 0; i < 14; i++) addrP[i] = tmp.env[i];}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (writes guest state, reads guest mem) */VexEmWarn x86g_dirtyhelper_FLDENV ( VexGuestX86State* gst, HWord addr ){ return do_put_x87( False/*don't move regs*/, (UChar*)addr, gst);}/*---------------------------------------------------------------*//*--- Misc integer helpers, including rotates and CPUID. ---*//*---------------------------------------------------------------*//* 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.*/ULong x86g_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 >> X86G_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 >> X86G_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 >> X86G_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 &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O); eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O); return (((ULong)eflags_in) << 32) | ((ULong)arg);}/* CALLED FROM GENERATED CODE: CLEAN HELPER *//* Calculate both flags and value result for rotate left through the carry bit. Result in low 32 bits, new flags (OSZACP) in high 32 bits.*/ULong x86g_calculate_RCL ( 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 >> X86G_CC_SHIFT_C) & 1; while (tempCOUNT > 0) { tempcf = (arg >> 31) & 1; arg = (arg << 1) | (cf & 1); cf = tempcf; tempCOUNT--; } of = ((arg >> 31) ^ cf) & 1; break; case 2: while (tempCOUNT >= 17) tempCOUNT -= 17; cf = (eflags_in >> X86G_CC_SHIFT_C) & 1; while (tempCOUNT > 0) { tempcf = (arg >> 15) & 1; arg = 0xFFFF & ((arg << 1) | (cf & 1)); cf = tempcf; tempCOUNT--; } of = ((arg >> 15) ^ cf) & 1; break; case 1: while (tempCOUNT >= 9) tempCOUNT -= 9; cf = (eflags_in >> X86G_CC_SHIFT_C) & 1; while (tempCOUNT > 0) { tempcf = (arg >> 7) & 1; arg = 0xFF & ((arg << 1) | (cf & 1)); cf = tempcf; tempCOUNT--; } of = ((arg >> 7) ^ cf) & 1; break; default: vpanic("calculate_RCL: invalid size"); } cf &= 1; of &= 1; eflags_in &= ~(X86G_CC_MASK_C | X86G_CC_MASK_O); eflags_in |= (cf << X86G_CC_SHIFT_C) | (of << X86G_CC_SHIFT_O); return (((ULong)eflags_in) << 32) | ((ULong)arg);}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (non-referentially-transparent) *//* Horrible hack. On non-x86 platforms, return 1. */ULong x86g_dirtyhelper_RDTSC ( void ){# if defined(__i386__) ULong res; __asm__ __volatile__("rdtsc" : "=A" (res)); return res;# else return 1ULL;# endif}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (modifies guest state) *//* Claim to be a P55C (Intel Pentium/MMX) */void x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* st ){ switch (st->guest_EAX) { case 0: st->guest_EAX = 0x1; st->guest_EBX = 0x756e6547; st->guest_ECX = 0x6c65746e; st->guest_EDX = 0x49656e69; break; default: st->guest_EAX = 0x543; st->guest_EBX = 0x0; st->guest_ECX = 0x0; st->guest_EDX = 0x8001bf; break; }}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (modifies guest state) *//* Claim to be the following SSE1-capable CPU: vendor_id : GenuineIntel cpu family : 6 model : 11 model name : Intel(R) Pentium(R) III CPU family 1133MHz stepping : 1 cpu MHz : 1131.013 cache size : 512 KB*/void x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* st ){ switch (st->guest_EAX) { case 0: st->guest_EAX = 0x00000002; st->guest_EBX = 0x756e6547; st->guest_ECX = 0x6c65746e; st->guest_EDX = 0x49656e69; break; case 1: st->guest_EAX = 0x000006b1; st->guest_EBX = 0x00000004; st->guest_ECX = 0x00000000; st->guest_EDX = 0x0383fbff; break; default: st->guest_EAX = 0x03020101; st->guest_EBX = 0x00000000; st->guest_ECX = 0x00000000; st->guest_EDX = 0x0c040883; break; }}/* Claim to be the following SSE2-capable CPU: vendor_id : GenuineIntel cpu family : 15 model : 2 model name : Intel(R) Pentium(R) 4 CPU 2.40GHz stepping : 7 cpu MHz
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -