📄 helper2.c
字号:
/* * i386 helpers (without register variable usage) * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include <signal.h>#include <assert.h>#include "cpu.h"#include "exec-all.h"//#define DEBUG_MMU#ifdef USE_CODE_COPY#include <asm/ldt.h>#include <linux/unistd.h>#include <linux/version.h>_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)#define modify_ldt_ldt_s user_desc#endif#endif /* USE_CODE_COPY */CPUX86State *cpu_x86_init(void){ CPUX86State *env; static int inited; env = qemu_mallocz(sizeof(CPUX86State)); if (!env) return NULL; cpu_exec_init(env); /* init various static tables */ if (!inited) { inited = 1; optimize_flags_init(); }#ifdef USE_CODE_COPY /* testing code for code copy case */ { struct modify_ldt_ldt_s ldt; ldt.entry_number = 1; ldt.base_addr = (unsigned long)env; ldt.limit = (sizeof(CPUState) + 0xfff) >> 12; ldt.seg_32bit = 1; ldt.contents = MODIFY_LDT_CONTENTS_DATA; ldt.read_exec_only = 0; ldt.limit_in_pages = 1; ldt.seg_not_present = 0; ldt.useable = 1; modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7)); }#endif { int family, model, stepping;#ifdef TARGET_X86_64 env->cpuid_vendor1 = 0x68747541; /* "Auth" */ env->cpuid_vendor2 = 0x69746e65; /* "enti" */ env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ family = 6; model = 2; stepping = 3;#else env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */#if 0 /* pentium 75-200 */ family = 5; model = 2; stepping = 11;#else /* pentium pro */ family = 6; model = 3; stepping = 3;#endif#endif env->cpuid_level = 2; env->cpuid_version = (family << 8) | (model << 4) | stepping; env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | CPUID_PAT); env->pat = 0x0007040600070406ULL; env->cpuid_ext_features = CPUID_EXT_SSE3; env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP; env->cpuid_features |= CPUID_APIC; env->cpuid_xlevel = 0; { const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION; int c, len, i; len = strlen(model_id); for(i = 0; i < 48; i++) { if (i >= len) c = '\0'; else c = model_id[i]; env->cpuid_model[i >> 2] |= c << (8 * (i & 3)); } }#ifdef TARGET_X86_64 /* currently not enabled for std i386 because not fully tested */ env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; env->cpuid_xlevel = 0x80000008; /* these features are needed for Win64 and aren't fully implemented */ env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;#endif } cpu_reset(env);#ifdef USE_KQEMU kqemu_init(env);#endif return env;}/* NOTE: must be called outside the CPU execute loop */void cpu_reset(CPUX86State *env){ int i; memset(env, 0, offsetof(CPUX86State, breakpoints)); tlb_flush(env, 1); /* init to reset state */#ifdef CONFIG_SOFTMMU env->hflags |= HF_SOFTMMU_MASK;#endif cpu_x86_update_cr0(env, 0x60000010); env->a20_mask = 0xffffffff; env->idt.limit = 0xffff; env->gdt.limit = 0xffff; env->ldt.limit = 0xffff; env->ldt.flags = DESC_P_MASK; env->tr.limit = 0xffff; env->tr.flags = DESC_P_MASK; cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0); cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0); cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0); cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0); cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0); cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0); env->eip = 0xfff0; env->regs[R_EDX] = 0x600; /* indicate P6 processor */ env->eflags = 0x2; /* FPU init */ for(i = 0;i < 8; i++) env->fptags[i] = 1; env->fpuc = 0x37f; env->mxcsr = 0x1f80;}void cpu_x86_close(CPUX86State *env){ free(env);}/***********************************************************//* x86 debug */static const char *cc_op_str[] = { "DYNAMIC", "EFLAGS", "MULB", "MULW", "MULL", "MULQ", "ADDB", "ADDW", "ADDL", "ADDQ", "ADCB", "ADCW", "ADCL", "ADCQ", "SUBB", "SUBW", "SUBL", "SUBQ", "SBBB", "SBBW", "SBBL", "SBBQ", "LOGICB", "LOGICW", "LOGICL", "LOGICQ", "INCB", "INCW", "INCL", "INCQ", "DECB", "DECW", "DECL", "DECQ", "SHLB", "SHLW", "SHLL", "SHLQ", "SARB", "SARW", "SARL", "SARQ",};void cpu_dump_state(CPUState *env, FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...), int flags){ int eflags, i, nb; char cc_op_name[32]; static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" }; eflags = env->eflags;#ifdef TARGET_X86_64 if (env->hflags & HF_CS64_MASK) { cpu_fprintf(f, "RAX=%016llx RBX=%016llx RCX=%016llx RDX=%016llx\n" "RSI=%016llx RDI=%016llx RBP=%016llx RSP=%016llx\n" "R8 =%016llx R9 =%016llx R10=%016llx R11=%016llx\n" "R12=%016llx R13=%016llx R14=%016llx R15=%016llx\n" "RIP=%016llx RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n", env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], env->regs[8], env->regs[9], env->regs[10], env->regs[11], env->regs[12], env->regs[13], env->regs[14], env->regs[15], env->eip, eflags, eflags & DF_MASK ? 'D' : '-', eflags & CC_O ? 'O' : '-', eflags & CC_S ? 'S' : '-', eflags & CC_Z ? 'Z' : '-', eflags & CC_A ? 'A' : '-', eflags & CC_P ? 'P' : '-', eflags & CC_C ? 'C' : '-', env->hflags & HF_CPL_MASK, (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, (env->a20_mask >> 20) & 1, (env->hflags >> HF_HALTED_SHIFT) & 1); } else #endif { cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n", (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_EBX], (uint32_t)env->regs[R_ECX], (uint32_t)env->regs[R_EDX], (uint32_t)env->regs[R_ESI], (uint32_t)env->regs[R_EDI], (uint32_t)env->regs[R_EBP], (uint32_t)env->regs[R_ESP], (uint32_t)env->eip, eflags, eflags & DF_MASK ? 'D' : '-', eflags & CC_O ? 'O' : '-', eflags & CC_S ? 'S' : '-', eflags & CC_Z ? 'Z' : '-', eflags & CC_A ? 'A' : '-', eflags & CC_P ? 'P' : '-', eflags & CC_C ? 'C' : '-', env->hflags & HF_CPL_MASK, (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, (env->a20_mask >> 20) & 1, (env->hflags >> HF_HALTED_SHIFT) & 1); }#ifdef TARGET_X86_64 if (env->hflags & HF_LMA_MASK) { for(i = 0; i < 6; i++) { SegmentCache *sc = &env->segs[i]; cpu_fprintf(f, "%s =%04x %016llx %08x %08x\n", seg_name[i], sc->selector, sc->base, sc->limit, sc->flags); } cpu_fprintf(f, "LDT=%04x %016llx %08x %08x\n", env->ldt.selector, env->ldt.base, env->ldt.limit, env->ldt.flags); cpu_fprintf(f, "TR =%04x %016llx %08x %08x\n", env->tr.selector, env->tr.base,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -