helper.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,185 行 · 第 1/5 页
C
2,185 行
}void helper_aaa(void){ int icarry; int al, ah, af; int eflags; eflags = cc_table[CC_OP].compute_all(); af = eflags & CC_A; al = EAX & 0xff; ah = (EAX >> 8) & 0xff; icarry = (al > 0xf9); if (((al & 0x0f) > 9 ) || af) { al = (al + 6) & 0x0f; ah = (ah + 1 + icarry) & 0xff; eflags |= CC_C | CC_A; } else { eflags &= ~(CC_C | CC_A); al &= 0x0f; } EAX = (EAX & ~0xffff) | al | (ah << 8); CC_SRC = eflags; FORCE_RET();}void helper_aas(void){ int icarry; int al, ah, af; int eflags; eflags = cc_table[CC_OP].compute_all(); af = eflags & CC_A; al = EAX & 0xff; ah = (EAX >> 8) & 0xff; icarry = (al < 6); if (((al & 0x0f) > 9 ) || af) { al = (al - 6) & 0x0f; ah = (ah - 1 - icarry) & 0xff; eflags |= CC_C | CC_A; } else { eflags &= ~(CC_C | CC_A); al &= 0x0f; } EAX = (EAX & ~0xffff) | al | (ah << 8); CC_SRC = eflags; FORCE_RET();}void helper_daa(void){ int al, af, cf; int eflags; eflags = cc_table[CC_OP].compute_all(); cf = eflags & CC_C; af = eflags & CC_A; al = EAX & 0xff; eflags = 0; if (((al & 0x0f) > 9 ) || af) { al = (al + 6) & 0xff; eflags |= CC_A; } if ((al > 0x9f) || cf) { al = (al + 0x60) & 0xff; eflags |= CC_C; } EAX = (EAX & ~0xff) | al; /* well, speed is not an issue here, so we compute the flags by hand */ eflags |= (al == 0) << 6; /* zf */ eflags |= parity_table[al]; /* pf */ eflags |= (al & 0x80); /* sf */ CC_SRC = eflags; FORCE_RET();}void helper_das(void){ int al, al1, af, cf; int eflags; eflags = cc_table[CC_OP].compute_all(); cf = eflags & CC_C; af = eflags & CC_A; al = EAX & 0xff; eflags = 0; al1 = al; if (((al & 0x0f) > 9 ) || af) { eflags |= CC_A; if (al < 6 || cf) eflags |= CC_C; al = (al - 6) & 0xff; } if ((al1 > 0x99) || cf) { al = (al - 0x60) & 0xff; eflags |= CC_C; } EAX = (EAX & ~0xff) | al; /* well, speed is not an issue here, so we compute the flags by hand */ eflags |= (al == 0) << 6; /* zf */ eflags |= parity_table[al]; /* pf */ eflags |= (al & 0x80); /* sf */ CC_SRC = eflags; FORCE_RET();}void helper_cmpxchg8b(void){ uint64_t d; int eflags; eflags = cc_table[CC_OP].compute_all(); d = ldq(A0); if (d == (((uint64_t)EDX << 32) | EAX)) { stq(A0, ((uint64_t)ECX << 32) | EBX); eflags |= CC_Z; } else { EDX = d >> 32; EAX = d; eflags &= ~CC_Z; } CC_SRC = eflags;}void helper_single_step(void){ env->dr[6] |= 0x4000; raise_exception(EXCP01_SSTP);}void helper_cpuid(void){ uint32_t index; index = (uint32_t)EAX; /* test if maximum index reached */ if (index & 0x80000000) { if (index > env->cpuid_xlevel) index = env->cpuid_level; } else { if (index > env->cpuid_level) index = env->cpuid_level; } switch(index) { case 0: EAX = env->cpuid_level; EBX = env->cpuid_vendor1; EDX = env->cpuid_vendor2; ECX = env->cpuid_vendor3; break; case 1: EAX = env->cpuid_version; EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ ECX = env->cpuid_ext_features; EDX = env->cpuid_features; break; case 2: /* cache info: needed for Pentium Pro compatibility */ EAX = 1; EBX = 0; ECX = 0; EDX = 0x2c307d; break; case 0x80000000: EAX = env->cpuid_xlevel; EBX = env->cpuid_vendor1; EDX = env->cpuid_vendor2; ECX = env->cpuid_vendor3; break; case 0x80000001: EAX = env->cpuid_features; EBX = 0; ECX = env->cpuid_ext3_features; EDX = env->cpuid_ext2_features; break; case 0x80000002: case 0x80000003: case 0x80000004: EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0]; EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1]; ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2]; EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3]; break; case 0x80000005: /* cache info (L1 cache) */ EAX = 0x01ff01ff; EBX = 0x01ff01ff; ECX = 0x40020140; EDX = 0x40020140; break; case 0x80000006: /* cache info (L2 cache) */ EAX = 0; EBX = 0x42004200; ECX = 0x02008140; EDX = 0; break; case 0x80000008: /* virtual & phys address size in low 2 bytes. *//* XXX: This value must match the one used in the MMU code. */ #if defined(TARGET_X86_64)# if defined(USE_KQEMU) EAX = 0x00003020; /* 48 bits virtual, 32 bits physical */# else/* XXX: The physical address space is limited to 42 bits in exec.c. */ EAX = 0x00003028; /* 48 bits virtual, 40 bits physical */# endif#else# if defined(USE_KQEMU) EAX = 0x00000020; /* 32 bits physical */# else EAX = 0x00000024; /* 36 bits physical */# endif#endif EBX = 0; ECX = 0; EDX = 0; break; case 0x8000000A: EAX = 0x00000001; EBX = 0; ECX = 0; EDX = 0; break; default: /* reserved values: zero */ EAX = 0; EBX = 0; ECX = 0; EDX = 0; break; }}void helper_enter_level(int level, int data32){ target_ulong ssp; uint32_t esp_mask, esp, ebp; esp_mask = get_sp_mask(env->segs[R_SS].flags); ssp = env->segs[R_SS].base; ebp = EBP; esp = ESP; if (data32) { /* 32 bit */ esp -= 4; while (--level) { esp -= 4; ebp -= 4; stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask))); } esp -= 4; stl(ssp + (esp & esp_mask), T1); } else { /* 16 bit */ esp -= 2; while (--level) { esp -= 2; ebp -= 2; stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask))); } esp -= 2; stw(ssp + (esp & esp_mask), T1); }}#ifdef TARGET_X86_64void helper_enter64_level(int level, int data64){ target_ulong esp, ebp; ebp = EBP; esp = ESP; if (data64) { /* 64 bit */ esp -= 8; while (--level) { esp -= 8; ebp -= 8; stq(esp, ldq(ebp)); } esp -= 8; stq(esp, T1); } else { /* 16 bit */ esp -= 2; while (--level) { esp -= 2; ebp -= 2; stw(esp, lduw(ebp)); } esp -= 2; stw(esp, T1); }}#endifvoid helper_lldt(int selector){ SegmentCache *dt; uint32_t e1, e2; int index, entry_limit; target_ulong ptr; selector &= 0xffff; if ((selector & 0xfffc) == 0) { /* XXX: NULL selector case: invalid LDT */ env->ldt.base = 0; env->ldt.limit = 0; } else { if (selector & 0x4) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); dt = &env->gdt; index = selector & ~7;#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) entry_limit = 15; else#endif entry_limit = 7; if ((index + entry_limit) > dt->limit) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); ptr = dt->base + index; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); if (!(e2 & DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { uint32_t e3; e3 = ldl_kernel(ptr + 8); load_seg_cache_raw_dt(&env->ldt, e1, e2); env->ldt.base |= (target_ulong)e3 << 32; } else#endif { load_seg_cache_raw_dt(&env->ldt, e1, e2); } } env->ldt.selector = selector;}void helper_ltr(int selector){ SegmentCache *dt; uint32_t e1, e2; int index, type, entry_limit; target_ulong ptr; selector &= 0xffff; if ((selector & 0xfffc) == 0) { /* NULL selector case: invalid TR */ env->tr.base = 0; env->tr.limit = 0; env->tr.flags = 0; } else { if (selector & 0x4) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); dt = &env->gdt; index = selector & ~7;#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) entry_limit = 15; else#endif entry_limit = 7; if ((index + entry_limit) > dt->limit) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); ptr = dt->base + index; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); type = (e2 >> DESC_TYPE_SHIFT) & 0xf; if ((e2 & DESC_S_MASK) || (type != 1 && type != 9)) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); if (!(e2 & DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { uint32_t e3, e4; e3 = ldl_kernel(ptr + 8); e4 = ldl_kernel(ptr + 12); if ((e4 >> DESC_TYPE_SHIFT) & 0xf) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); load_seg_cache_raw_dt(&env->tr, e1, e2); env->tr.base |= (target_ulong)e3 << 32; } else#endif { load_seg_cache_raw_dt(&env->tr, e1, e2); } e2 |= DESC_TSS_BUSY_MASK; stl_kernel(ptr + 4, e2); } env->tr.selector = selector;}/* only works if protected mode and not VM86. seg_reg must be != R_CS */void helper_load_seg(int seg_reg, int selector){ uint32_t e1, e2; int cpl, dpl, rpl; SegmentCache *dt; int index; target_ulong ptr; selector &= 0xffff; cpl = env->hflags & HF_CPL_MASK; if ((selector & 0xfffc) == 0) { /* null selector case */ if (seg_reg == R_SS#ifdef TARGET_X86_64 && (!(env->hflags & HF_CS64_MASK) || cpl == 3)#endif ) raise_exception_err(EXCP0D_GPF, 0); cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0); } else { if (selector & 0x4) dt = &env->ldt; else dt = &env->gdt; index = selector & ~7; if ((index + 7) > dt->limit) raise_exception_err(EXCP0D_GPF, selector & 0xfffc); ptr = dt->base + index; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?