📄 ghelpers.c
字号:
return 0 | AMD64G_FC_MASK_C2 | (sign << AMD64G_FC_SHIFT_C1) | 0;}/* DIRTY HELPER (writes guest state) *//* Initialise the x87 FPU state as per 'finit'. */void 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_dirtyhelper_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_dirtyhelper_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. */ pair = amd64g_check_fldcw ( (ULong)fpucw ); fpround = pair & 0xFFFFFFFFULL; ew = (VexEmWarn)(pair >> 32); vex_state->guest_FPROUND = fpround & 3; /* emulation warnings --> caller */ return ew;}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER *//* Create an x87 FPU env from the guest state, as close as we can approximate it. Writes 28 bytes at x87_state[0..27]. */void amd64g_dirtyhelper_FSTENV ( /*IN*/VexGuestAMD64State* vex_state, /*OUT*/HWord x87_state ){ Int i, stno, preg; UInt tagw; UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]); Fpu_State* x87 = (Fpu_State*)x87_state; UInt ftop = vex_state->guest_FTOP; ULong 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(toUInt( ((ftop & 7) << 11) | (c3210 & 0x4700) )); x87->env[FP_ENV_CTRL] = toUShort(toUInt( amd64g_create_fpucw( vex_state->guest_FPROUND ) )); /* Compute the x87 tag word. */ tagw = 0; for (stno = 0; stno < 8; stno++) { preg = (stno + ftop) & 7; if (vexTags[preg] == 0) { /* register is empty */ tagw |= (3 << (2*preg)); } else { /* register is full. */ tagw |= (0 << (2*preg)); } } x87->env[FP_ENV_TAG] = toUShort(tagw); /* We don't dump the x87 registers, tho. */}/*---------------------------------------------------------------*//*--- Misc integer helpers, including rotates and CPUID. ---*//*---------------------------------------------------------------*//* Claim to be the following CPU: vendor_id : AuthenticAMD cpu family : 15 model : 12 model name : AMD Athlon(tm) 64 Processor 3200+ stepping : 0 cpu MHz : 2202.917 cache size : 512 KB fpu : yes fpu_exception : yes cpuid level : 1 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 pni syscall nx mmxext lm 3dnowext 3dnow bogomips : 4308.99 TLB size : 1088 4K pages clflush size : 64 cache_alignment : 64 address sizes : 40 bits physical, 48 bits virtual power management: ts fid vid ttp*/void amd64g_dirtyhelper_CPUID ( VexGuestAMD64State* st ){# define SET_ABCD(_a,_b,_c,_d) \ do { st->guest_RAX = (ULong)(_a); \ st->guest_RBX = (ULong)(_b); \ st->guest_RCX = (ULong)(_c); \ st->guest_RDX = (ULong)(_d); \ } while (0) switch (0xFFFFFFFF & st->guest_RAX) { case 0x0: SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65); break; case 0x1: SET_ABCD(0x00000fc0, 0x00000800, 0x00000000, 0x078bfbff); break; case 0x80000000: SET_ABCD(0x80000018, 0x68747541, 0x444d4163, 0x69746e65); break; case 0x80000001: SET_ABCD(0x00000fc0, 0x0000010a, 0x00000000, 0xe1d3fbff); break; case 0x80000002: SET_ABCD(0x20444d41, 0x6c687441, 0x74286e6f, 0x3620296d); break; case 0x80000003: SET_ABCD(0x72502034, 0x7365636f, 0x20726f73, 0x30303233); break; case 0x80000004: SET_ABCD(0x0000002b, 0x00000000, 0x00000000, 0x00000000); break; case 0x80000005: SET_ABCD(0xff08ff08, 0xff20ff20, 0x40020140, 0x40020140); break; case 0x80000006: SET_ABCD(0x00000000, 0x42004200, 0x02008140, 0x00000000); break; case 0x80000007: SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x0000000f); break; case 0x80000008: SET_ABCD(0x00003028, 0x00000000, 0x00000000, 0x00000000); break; default: SET_ABCD(0x00000000, 0x00000000, 0x00000000, 0x00000000); break; }# undef SET_ABCD}ULong amd64g_calculate_RCR ( ULong arg, ULong rot_amt, ULong rflags_in, Long szIN ){ Bool wantRflags = toBool(szIN < 0); ULong sz = wantRflags ? (-szIN) : szIN; ULong tempCOUNT = rot_amt & (sz == 8 ? 0x3F : 0x1F); ULong cf=0, of=0, tempcf; switch (sz) { case 8: cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; of = ((arg >> 63) ^ cf) & 1; while (tempCOUNT > 0) { tempcf = arg & 1; arg = (arg >> 1) | (cf << 63); cf = tempcf; tempCOUNT--; } break; case 4: while (tempCOUNT >= 33) tempCOUNT -= 33; cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; of = ((arg >> 31) ^ cf) & 1; while (tempCOUNT > 0) { tempcf = arg & 1; arg = ((arg >> 1) & 0x7FFFFFFFULL) | (cf << 31); cf = tempcf; tempCOUNT--; } break; case 2: while (tempCOUNT >= 17) tempCOUNT -= 17; cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; of = ((arg >> 15) ^ cf) & 1; while (tempCOUNT > 0) { tempcf = arg & 1; arg = ((arg >> 1) & 0x7FFFULL) | (cf << 15); cf = tempcf; tempCOUNT--; } break; case 1: while (tempCOUNT >= 9) tempCOUNT -= 9; cf = (rflags_in >> AMD64G_CC_SHIFT_C) & 1; of = ((arg >> 7) ^ cf) & 1; while (tempCOUNT > 0) { tempcf = arg & 1; arg = ((arg >> 1) & 0x7FULL) | (cf << 7); cf = tempcf; tempCOUNT--; } break; default: vpanic("calculate_RCR(amd64g): invalid size"); } cf &= 1; of &= 1; rflags_in &= ~(AMD64G_CC_MASK_C | AMD64G_CC_MASK_O); rflags_in |= (cf << AMD64G_CC_SHIFT_C) | (of << AMD64G_CC_SHIFT_O); /* caller can ask to have back either the resulting flags or resulting value, but not both */ return wantRflags ? rflags_in : arg;}/* CALLED FROM GENERATED CODE *//* DIRTY HELPER (non-referentially-transparent) *//* Horrible hack. On non-amd64 platforms, return 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -