Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ d0bdf2a2

History | View | Annotate | Download (32.6 kB)

1 2c0262af bellard
/*
2 2c0262af bellard
 *  i386 helpers (without register variable usage)
3 2c0262af bellard
 * 
4 2c0262af bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 2c0262af bellard
 *
6 2c0262af bellard
 * This library is free software; you can redistribute it and/or
7 2c0262af bellard
 * modify it under the terms of the GNU Lesser General Public
8 2c0262af bellard
 * License as published by the Free Software Foundation; either
9 2c0262af bellard
 * version 2 of the License, or (at your option) any later version.
10 2c0262af bellard
 *
11 2c0262af bellard
 * This library is distributed in the hope that it will be useful,
12 2c0262af bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 2c0262af bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 2c0262af bellard
 * Lesser General Public License for more details.
15 2c0262af bellard
 *
16 2c0262af bellard
 * You should have received a copy of the GNU Lesser General Public
17 2c0262af bellard
 * License along with this library; if not, write to the Free Software
18 2c0262af bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 2c0262af bellard
 */
20 2c0262af bellard
#include <stdarg.h>
21 2c0262af bellard
#include <stdlib.h>
22 2c0262af bellard
#include <stdio.h>
23 2c0262af bellard
#include <string.h>
24 2c0262af bellard
#include <inttypes.h>
25 2c0262af bellard
#include <signal.h>
26 2c0262af bellard
#include <assert.h>
27 2c0262af bellard
28 2c0262af bellard
#include "cpu.h"
29 2c0262af bellard
#include "exec-all.h"
30 2c0262af bellard
31 2c0262af bellard
//#define DEBUG_MMU
32 2c0262af bellard
33 0e4b179d bellard
#ifdef USE_CODE_COPY
34 0e4b179d bellard
#include <asm/ldt.h>
35 0e4b179d bellard
#include <linux/unistd.h>
36 73bdea19 bellard
#include <linux/version.h>
37 0e4b179d bellard
38 83fcb515 bellard
int modify_ldt(int func, void *ptr, unsigned long bytecount)
39 83fcb515 bellard
{
40 83fcb515 bellard
        return syscall(__NR_modify_ldt, func, ptr, bytecount);
41 83fcb515 bellard
}
42 73bdea19 bellard
43 73bdea19 bellard
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
44 73bdea19 bellard
#define modify_ldt_ldt_s user_desc
45 0e4b179d bellard
#endif
46 73bdea19 bellard
#endif /* USE_CODE_COPY */
47 0e4b179d bellard
48 2c0262af bellard
CPUX86State *cpu_x86_init(void)
49 2c0262af bellard
{
50 2c0262af bellard
    CPUX86State *env;
51 2c0262af bellard
    static int inited;
52 2c0262af bellard
53 173d6cfe bellard
    env = qemu_mallocz(sizeof(CPUX86State));
54 2c0262af bellard
    if (!env)
55 2c0262af bellard
        return NULL;
56 173d6cfe bellard
    cpu_exec_init(env);
57 173d6cfe bellard
58 ffddfee3 bellard
    /* init various static tables */
59 ffddfee3 bellard
    if (!inited) {
60 ffddfee3 bellard
        inited = 1;
61 ffddfee3 bellard
        optimize_flags_init();
62 ffddfee3 bellard
    }
63 ffddfee3 bellard
#ifdef USE_CODE_COPY
64 ffddfee3 bellard
    /* testing code for code copy case */
65 ffddfee3 bellard
    {
66 ffddfee3 bellard
        struct modify_ldt_ldt_s ldt;
67 2c0262af bellard
68 ffddfee3 bellard
        ldt.entry_number = 1;
69 ffddfee3 bellard
        ldt.base_addr = (unsigned long)env;
70 ffddfee3 bellard
        ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
71 ffddfee3 bellard
        ldt.seg_32bit = 1;
72 ffddfee3 bellard
        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
73 ffddfee3 bellard
        ldt.read_exec_only = 0;
74 ffddfee3 bellard
        ldt.limit_in_pages = 1;
75 ffddfee3 bellard
        ldt.seg_not_present = 0;
76 ffddfee3 bellard
        ldt.useable = 1;
77 ffddfee3 bellard
        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
78 ffddfee3 bellard
        
79 ffddfee3 bellard
        asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
80 ffddfee3 bellard
    }
81 ffddfee3 bellard
#endif
82 14ce26e7 bellard
    {
83 14ce26e7 bellard
        int family, model, stepping;
84 14ce26e7 bellard
#ifdef TARGET_X86_64
85 14ce26e7 bellard
        env->cpuid_vendor1 = 0x68747541; /* "Auth" */
86 14ce26e7 bellard
        env->cpuid_vendor2 = 0x69746e65; /* "enti" */
87 14ce26e7 bellard
        env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
88 14ce26e7 bellard
        family = 6;
89 14ce26e7 bellard
        model = 2;
90 14ce26e7 bellard
        stepping = 3;
91 14ce26e7 bellard
#else
92 14ce26e7 bellard
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
93 14ce26e7 bellard
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
94 14ce26e7 bellard
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
95 14ce26e7 bellard
#if 0
96 14ce26e7 bellard
        /* pentium 75-200 */
97 14ce26e7 bellard
        family = 5;
98 14ce26e7 bellard
        model = 2;
99 14ce26e7 bellard
        stepping = 11;
100 14ce26e7 bellard
#else
101 14ce26e7 bellard
        /* pentium pro */
102 14ce26e7 bellard
        family = 6;
103 bf079a1e bellard
        model = 3;
104 14ce26e7 bellard
        stepping = 3;
105 14ce26e7 bellard
#endif
106 14ce26e7 bellard
#endif
107 a6f37988 bellard
        env->cpuid_level = 2;
108 14ce26e7 bellard
        env->cpuid_version = (family << 8) | (model << 4) | stepping;
109 14ce26e7 bellard
        env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
110 14ce26e7 bellard
                               CPUID_TSC | CPUID_MSR | CPUID_MCE |
111 8f091a59 bellard
                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
112 8f091a59 bellard
                               CPUID_PAT);
113 8f091a59 bellard
        env->pat = 0x0007040600070406ULL;
114 465e9838 bellard
        env->cpuid_ext_features = CPUID_EXT_SSE3;
115 bf079a1e bellard
        env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
116 96b74a02 bellard
        env->cpuid_features |= CPUID_APIC;
117 a6f37988 bellard
        env->cpuid_xlevel = 0;
118 a6f37988 bellard
        {
119 a6f37988 bellard
            const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
120 a6f37988 bellard
            int c, len, i;
121 a6f37988 bellard
            len = strlen(model_id);
122 a6f37988 bellard
            for(i = 0; i < 48; i++) {
123 a6f37988 bellard
                if (i >= len)
124 a6f37988 bellard
                    c = '\0';
125 a6f37988 bellard
                else
126 a6f37988 bellard
                    c = model_id[i];
127 a6f37988 bellard
                env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
128 a6f37988 bellard
            }
129 a6f37988 bellard
        }
130 14ce26e7 bellard
#ifdef TARGET_X86_64
131 14ce26e7 bellard
        /* currently not enabled for std i386 because not fully tested */
132 a6f37988 bellard
        env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
133 4b4f782c bellard
        env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
134 a6f37988 bellard
        env->cpuid_xlevel = 0x80000008;
135 8f091a59 bellard
136 8f091a59 bellard
        /* these features are needed for Win64 and aren't fully implemented */
137 8f091a59 bellard
        env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
138 69c3bcb4 bellard
        /* this feature is needed for Solaris and isn't fully implemented */
139 69c3bcb4 bellard
        env->cpuid_features |= CPUID_PSE36;
140 14ce26e7 bellard
#endif
141 14ce26e7 bellard
    }
142 ffddfee3 bellard
    cpu_reset(env);
143 bf079a1e bellard
#ifdef USE_KQEMU
144 bf079a1e bellard
    kqemu_init(env);
145 bf079a1e bellard
#endif
146 ffddfee3 bellard
    return env;
147 ffddfee3 bellard
}
148 ffddfee3 bellard
149 ffddfee3 bellard
/* NOTE: must be called outside the CPU execute loop */
150 ffddfee3 bellard
void cpu_reset(CPUX86State *env)
151 ffddfee3 bellard
{
152 ffddfee3 bellard
    int i;
153 ffddfee3 bellard
154 ffddfee3 bellard
    memset(env, 0, offsetof(CPUX86State, breakpoints));
155 1ac157da bellard
156 1ac157da bellard
    tlb_flush(env, 1);
157 ffddfee3 bellard
158 ffddfee3 bellard
    /* init to reset state */
159 ffddfee3 bellard
160 2c0262af bellard
#ifdef CONFIG_SOFTMMU
161 2c0262af bellard
    env->hflags |= HF_SOFTMMU_MASK;
162 2c0262af bellard
#endif
163 1ac157da bellard
164 1ac157da bellard
    cpu_x86_update_cr0(env, 0x60000010);
165 1ac157da bellard
    env->a20_mask = 0xffffffff;
166 3b21e03e bellard
    env->smbase = 0x30000;
167 3b21e03e bellard
168 1ac157da bellard
    env->idt.limit = 0xffff;
169 1ac157da bellard
    env->gdt.limit = 0xffff;
170 1ac157da bellard
    env->ldt.limit = 0xffff;
171 1ac157da bellard
    env->ldt.flags = DESC_P_MASK;
172 1ac157da bellard
    env->tr.limit = 0xffff;
173 1ac157da bellard
    env->tr.flags = DESC_P_MASK;
174 1ac157da bellard
    
175 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0); 
176 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
177 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
178 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
179 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
180 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
181 1ac157da bellard
    
182 1ac157da bellard
    env->eip = 0xfff0;
183 1ac157da bellard
    env->regs[R_EDX] = 0x600; /* indicate P6 processor */
184 1ac157da bellard
    
185 1ac157da bellard
    env->eflags = 0x2;
186 1ac157da bellard
    
187 1ac157da bellard
    /* FPU init */
188 1ac157da bellard
    for(i = 0;i < 8; i++)
189 1ac157da bellard
        env->fptags[i] = 1;
190 1ac157da bellard
    env->fpuc = 0x37f;
191 664e0f19 bellard
192 664e0f19 bellard
    env->mxcsr = 0x1f80;
193 2c0262af bellard
}
194 2c0262af bellard
195 2c0262af bellard
void cpu_x86_close(CPUX86State *env)
196 2c0262af bellard
{
197 2c0262af bellard
    free(env);
198 2c0262af bellard
}
199 2c0262af bellard
200 2c0262af bellard
/***********************************************************/
201 2c0262af bellard
/* x86 debug */
202 2c0262af bellard
203 2c0262af bellard
static const char *cc_op_str[] = {
204 2c0262af bellard
    "DYNAMIC",
205 2c0262af bellard
    "EFLAGS",
206 14ce26e7 bellard
207 b7f0f463 bellard
    "MULB",
208 b7f0f463 bellard
    "MULW",
209 b7f0f463 bellard
    "MULL",
210 14ce26e7 bellard
    "MULQ",
211 14ce26e7 bellard
212 2c0262af bellard
    "ADDB",
213 2c0262af bellard
    "ADDW",
214 2c0262af bellard
    "ADDL",
215 14ce26e7 bellard
    "ADDQ",
216 14ce26e7 bellard
217 2c0262af bellard
    "ADCB",
218 2c0262af bellard
    "ADCW",
219 2c0262af bellard
    "ADCL",
220 14ce26e7 bellard
    "ADCQ",
221 14ce26e7 bellard
222 2c0262af bellard
    "SUBB",
223 2c0262af bellard
    "SUBW",
224 2c0262af bellard
    "SUBL",
225 14ce26e7 bellard
    "SUBQ",
226 14ce26e7 bellard
227 2c0262af bellard
    "SBBB",
228 2c0262af bellard
    "SBBW",
229 2c0262af bellard
    "SBBL",
230 14ce26e7 bellard
    "SBBQ",
231 14ce26e7 bellard
232 2c0262af bellard
    "LOGICB",
233 2c0262af bellard
    "LOGICW",
234 2c0262af bellard
    "LOGICL",
235 14ce26e7 bellard
    "LOGICQ",
236 14ce26e7 bellard
237 2c0262af bellard
    "INCB",
238 2c0262af bellard
    "INCW",
239 2c0262af bellard
    "INCL",
240 14ce26e7 bellard
    "INCQ",
241 14ce26e7 bellard
242 2c0262af bellard
    "DECB",
243 2c0262af bellard
    "DECW",
244 2c0262af bellard
    "DECL",
245 14ce26e7 bellard
    "DECQ",
246 14ce26e7 bellard
247 2c0262af bellard
    "SHLB",
248 2c0262af bellard
    "SHLW",
249 2c0262af bellard
    "SHLL",
250 14ce26e7 bellard
    "SHLQ",
251 14ce26e7 bellard
252 2c0262af bellard
    "SARB",
253 2c0262af bellard
    "SARW",
254 2c0262af bellard
    "SARL",
255 14ce26e7 bellard
    "SARQ",
256 2c0262af bellard
};
257 2c0262af bellard
258 7fe48483 bellard
void cpu_dump_state(CPUState *env, FILE *f, 
259 7fe48483 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
260 7fe48483 bellard
                    int flags)
261 2c0262af bellard
{
262 2157fa06 bellard
    int eflags, i, nb;
263 2c0262af bellard
    char cc_op_name[32];
264 246d897f bellard
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
265 2c0262af bellard
266 2c0262af bellard
    eflags = env->eflags;
267 14ce26e7 bellard
#ifdef TARGET_X86_64
268 14ce26e7 bellard
    if (env->hflags & HF_CS64_MASK) {
269 14ce26e7 bellard
        cpu_fprintf(f, 
270 26a76461 bellard
                    "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
271 26a76461 bellard
                    "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
272 26a76461 bellard
                    "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
273 26a76461 bellard
                    "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
274 3b21e03e bellard
                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
275 14ce26e7 bellard
                    env->regs[R_EAX], 
276 14ce26e7 bellard
                    env->regs[R_EBX], 
277 14ce26e7 bellard
                    env->regs[R_ECX], 
278 14ce26e7 bellard
                    env->regs[R_EDX], 
279 14ce26e7 bellard
                    env->regs[R_ESI], 
280 14ce26e7 bellard
                    env->regs[R_EDI], 
281 14ce26e7 bellard
                    env->regs[R_EBP], 
282 14ce26e7 bellard
                    env->regs[R_ESP], 
283 14ce26e7 bellard
                    env->regs[8], 
284 14ce26e7 bellard
                    env->regs[9], 
285 14ce26e7 bellard
                    env->regs[10], 
286 14ce26e7 bellard
                    env->regs[11], 
287 14ce26e7 bellard
                    env->regs[12], 
288 14ce26e7 bellard
                    env->regs[13], 
289 14ce26e7 bellard
                    env->regs[14], 
290 14ce26e7 bellard
                    env->regs[15], 
291 14ce26e7 bellard
                    env->eip, eflags,
292 14ce26e7 bellard
                    eflags & DF_MASK ? 'D' : '-',
293 14ce26e7 bellard
                    eflags & CC_O ? 'O' : '-',
294 14ce26e7 bellard
                    eflags & CC_S ? 'S' : '-',
295 14ce26e7 bellard
                    eflags & CC_Z ? 'Z' : '-',
296 14ce26e7 bellard
                    eflags & CC_A ? 'A' : '-',
297 14ce26e7 bellard
                    eflags & CC_P ? 'P' : '-',
298 14ce26e7 bellard
                    eflags & CC_C ? 'C' : '-',
299 14ce26e7 bellard
                    env->hflags & HF_CPL_MASK, 
300 14ce26e7 bellard
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
301 d2ac63e0 bellard
                    (env->a20_mask >> 20) & 1,
302 3b21e03e bellard
                    (env->hflags >> HF_SMM_SHIFT) & 1,
303 d2ac63e0 bellard
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
304 14ce26e7 bellard
    } else 
305 14ce26e7 bellard
#endif
306 14ce26e7 bellard
    {
307 14ce26e7 bellard
        cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
308 14ce26e7 bellard
                    "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
309 3b21e03e bellard
                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
310 14ce26e7 bellard
                    (uint32_t)env->regs[R_EAX], 
311 14ce26e7 bellard
                    (uint32_t)env->regs[R_EBX], 
312 14ce26e7 bellard
                    (uint32_t)env->regs[R_ECX], 
313 14ce26e7 bellard
                    (uint32_t)env->regs[R_EDX], 
314 14ce26e7 bellard
                    (uint32_t)env->regs[R_ESI], 
315 14ce26e7 bellard
                    (uint32_t)env->regs[R_EDI], 
316 14ce26e7 bellard
                    (uint32_t)env->regs[R_EBP], 
317 14ce26e7 bellard
                    (uint32_t)env->regs[R_ESP], 
318 14ce26e7 bellard
                    (uint32_t)env->eip, eflags,
319 14ce26e7 bellard
                    eflags & DF_MASK ? 'D' : '-',
320 14ce26e7 bellard
                    eflags & CC_O ? 'O' : '-',
321 14ce26e7 bellard
                    eflags & CC_S ? 'S' : '-',
322 14ce26e7 bellard
                    eflags & CC_Z ? 'Z' : '-',
323 14ce26e7 bellard
                    eflags & CC_A ? 'A' : '-',
324 14ce26e7 bellard
                    eflags & CC_P ? 'P' : '-',
325 14ce26e7 bellard
                    eflags & CC_C ? 'C' : '-',
326 14ce26e7 bellard
                    env->hflags & HF_CPL_MASK, 
327 14ce26e7 bellard
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
328 d2ac63e0 bellard
                    (env->a20_mask >> 20) & 1,
329 3b21e03e bellard
                    (env->hflags >> HF_SMM_SHIFT) & 1,
330 d2ac63e0 bellard
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
331 14ce26e7 bellard
    }
332 14ce26e7 bellard
333 14ce26e7 bellard
#ifdef TARGET_X86_64
334 14ce26e7 bellard
    if (env->hflags & HF_LMA_MASK) {
335 14ce26e7 bellard
        for(i = 0; i < 6; i++) {
336 14ce26e7 bellard
            SegmentCache *sc = &env->segs[i];
337 26a76461 bellard
            cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
338 14ce26e7 bellard
                        seg_name[i],
339 14ce26e7 bellard
                        sc->selector,
340 14ce26e7 bellard
                        sc->base,
341 14ce26e7 bellard
                        sc->limit,
342 14ce26e7 bellard
                        sc->flags);
343 14ce26e7 bellard
        }
344 26a76461 bellard
        cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
345 14ce26e7 bellard
                    env->ldt.selector,
346 14ce26e7 bellard
                    env->ldt.base,
347 14ce26e7 bellard
                    env->ldt.limit,
348 14ce26e7 bellard
                    env->ldt.flags);
349 26a76461 bellard
        cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
350 14ce26e7 bellard
                    env->tr.selector,
351 14ce26e7 bellard
                    env->tr.base,
352 14ce26e7 bellard
                    env->tr.limit,
353 14ce26e7 bellard
                    env->tr.flags);
354 26a76461 bellard
        cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
355 14ce26e7 bellard
                    env->gdt.base, env->gdt.limit);
356 26a76461 bellard
        cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
357 14ce26e7 bellard
                    env->idt.base, env->idt.limit);
358 26a76461 bellard
        cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
359 14ce26e7 bellard
                    (uint32_t)env->cr[0], 
360 14ce26e7 bellard
                    env->cr[2], 
361 14ce26e7 bellard
                    env->cr[3], 
362 14ce26e7 bellard
                    (uint32_t)env->cr[4]);
363 14ce26e7 bellard
    } else
364 14ce26e7 bellard
#endif
365 14ce26e7 bellard
    {
366 14ce26e7 bellard
        for(i = 0; i < 6; i++) {
367 14ce26e7 bellard
            SegmentCache *sc = &env->segs[i];
368 14ce26e7 bellard
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
369 14ce26e7 bellard
                        seg_name[i],
370 14ce26e7 bellard
                        sc->selector,
371 14ce26e7 bellard
                        (uint32_t)sc->base,
372 14ce26e7 bellard
                        sc->limit,
373 14ce26e7 bellard
                        sc->flags);
374 14ce26e7 bellard
        }
375 14ce26e7 bellard
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
376 14ce26e7 bellard
                    env->ldt.selector,
377 14ce26e7 bellard
                    (uint32_t)env->ldt.base,
378 14ce26e7 bellard
                    env->ldt.limit,
379 14ce26e7 bellard
                    env->ldt.flags);
380 14ce26e7 bellard
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
381 14ce26e7 bellard
                    env->tr.selector,
382 14ce26e7 bellard
                    (uint32_t)env->tr.base,
383 14ce26e7 bellard
                    env->tr.limit,
384 14ce26e7 bellard
                    env->tr.flags);
385 14ce26e7 bellard
        cpu_fprintf(f, "GDT=     %08x %08x\n",
386 14ce26e7 bellard
                    (uint32_t)env->gdt.base, env->gdt.limit);
387 14ce26e7 bellard
        cpu_fprintf(f, "IDT=     %08x %08x\n",
388 14ce26e7 bellard
                    (uint32_t)env->idt.base, env->idt.limit);
389 14ce26e7 bellard
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
390 14ce26e7 bellard
                    (uint32_t)env->cr[0], 
391 14ce26e7 bellard
                    (uint32_t)env->cr[2], 
392 14ce26e7 bellard
                    (uint32_t)env->cr[3], 
393 14ce26e7 bellard
                    (uint32_t)env->cr[4]);
394 246d897f bellard
    }
395 2c0262af bellard
    if (flags & X86_DUMP_CCOP) {
396 2c0262af bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
397 eba2af63 bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
398 2c0262af bellard
        else
399 2c0262af bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
400 14ce26e7 bellard
#ifdef TARGET_X86_64
401 14ce26e7 bellard
        if (env->hflags & HF_CS64_MASK) {
402 26a76461 bellard
            cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
403 14ce26e7 bellard
                        env->cc_src, env->cc_dst, 
404 14ce26e7 bellard
                        cc_op_name);
405 14ce26e7 bellard
        } else 
406 14ce26e7 bellard
#endif
407 14ce26e7 bellard
        {
408 14ce26e7 bellard
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
409 14ce26e7 bellard
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst, 
410 14ce26e7 bellard
                        cc_op_name);
411 14ce26e7 bellard
        }
412 2c0262af bellard
    }
413 2c0262af bellard
    if (flags & X86_DUMP_FPU) {
414 2157fa06 bellard
        int fptag;
415 2157fa06 bellard
        fptag = 0;
416 2157fa06 bellard
        for(i = 0; i < 8; i++) {
417 2157fa06 bellard
            fptag |= ((!env->fptags[i]) << i);
418 2157fa06 bellard
        }
419 2157fa06 bellard
        cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
420 2157fa06 bellard
                    env->fpuc,
421 2157fa06 bellard
                    (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
422 2157fa06 bellard
                    env->fpstt,
423 2157fa06 bellard
                    fptag,
424 2157fa06 bellard
                    env->mxcsr);
425 2157fa06 bellard
        for(i=0;i<8;i++) {
426 2157fa06 bellard
#if defined(USE_X86LDOUBLE)
427 2157fa06 bellard
            union {
428 2157fa06 bellard
                long double d;
429 2157fa06 bellard
                struct {
430 2157fa06 bellard
                    uint64_t lower;
431 2157fa06 bellard
                    uint16_t upper;
432 2157fa06 bellard
                } l;
433 2157fa06 bellard
            } tmp;
434 2157fa06 bellard
            tmp.d = env->fpregs[i].d;
435 26a76461 bellard
            cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
436 2157fa06 bellard
                        i, tmp.l.lower, tmp.l.upper);
437 2157fa06 bellard
#else
438 26a76461 bellard
            cpu_fprintf(f, "FPR%d=%016" PRIx64,
439 2157fa06 bellard
                        i, env->fpregs[i].mmx.q);
440 2157fa06 bellard
#endif
441 2157fa06 bellard
            if ((i & 1) == 1)
442 2157fa06 bellard
                cpu_fprintf(f, "\n");
443 2157fa06 bellard
            else
444 2157fa06 bellard
                cpu_fprintf(f, " ");
445 2157fa06 bellard
        }
446 2157fa06 bellard
        if (env->hflags & HF_CS64_MASK) 
447 2157fa06 bellard
            nb = 16;
448 2157fa06 bellard
        else
449 2157fa06 bellard
            nb = 8;
450 2157fa06 bellard
        for(i=0;i<nb;i++) {
451 2157fa06 bellard
            cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
452 2157fa06 bellard
                        i, 
453 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(3),
454 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(2),
455 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(1),
456 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(0));
457 2157fa06 bellard
            if ((i & 1) == 1)
458 2157fa06 bellard
                cpu_fprintf(f, "\n");
459 2157fa06 bellard
            else
460 2157fa06 bellard
                cpu_fprintf(f, " ");
461 2157fa06 bellard
        }
462 2c0262af bellard
    }
463 2c0262af bellard
}
464 2c0262af bellard
465 2c0262af bellard
/***********************************************************/
466 2c0262af bellard
/* x86 mmu */
467 2c0262af bellard
/* XXX: add PGE support */
468 2c0262af bellard
469 461c0471 bellard
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
470 461c0471 bellard
{
471 461c0471 bellard
    a20_state = (a20_state != 0);
472 1ac157da bellard
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
473 b7f0f463 bellard
#if defined(DEBUG_MMU)
474 b7f0f463 bellard
        printf("A20 update: a20=%d\n", a20_state);
475 b7f0f463 bellard
#endif
476 6bb70571 bellard
        /* if the cpu is currently executing code, we must unlink it and
477 6bb70571 bellard
           all the potentially executing TB */
478 0e4b179d bellard
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
479 6bb70571 bellard
480 461c0471 bellard
        /* when a20 is changed, all the MMU mappings are invalid, so
481 461c0471 bellard
           we must flush everything */
482 1ac157da bellard
        tlb_flush(env, 1);
483 1ac157da bellard
        env->a20_mask = 0xffefffff | (a20_state << 20);
484 461c0471 bellard
    }
485 461c0471 bellard
}
486 461c0471 bellard
487 1ac157da bellard
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
488 2c0262af bellard
{
489 1ac157da bellard
    int pe_state;
490 2c0262af bellard
491 b7f0f463 bellard
#if defined(DEBUG_MMU)
492 1ac157da bellard
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
493 2c0262af bellard
#endif
494 1ac157da bellard
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
495 1ac157da bellard
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
496 1ac157da bellard
        tlb_flush(env, 1);
497 2c0262af bellard
    }
498 14ce26e7 bellard
499 14ce26e7 bellard
#ifdef TARGET_X86_64
500 14ce26e7 bellard
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
501 14ce26e7 bellard
        (env->efer & MSR_EFER_LME)) {
502 14ce26e7 bellard
        /* enter in long mode */
503 14ce26e7 bellard
        /* XXX: generate an exception */
504 14ce26e7 bellard
        if (!(env->cr[4] & CR4_PAE_MASK))
505 14ce26e7 bellard
            return;
506 14ce26e7 bellard
        env->efer |= MSR_EFER_LMA;
507 14ce26e7 bellard
        env->hflags |= HF_LMA_MASK;
508 14ce26e7 bellard
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
509 14ce26e7 bellard
               (env->efer & MSR_EFER_LMA)) {
510 14ce26e7 bellard
        /* exit long mode */
511 14ce26e7 bellard
        env->efer &= ~MSR_EFER_LMA;
512 14ce26e7 bellard
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
513 14ce26e7 bellard
        env->eip &= 0xffffffff;
514 14ce26e7 bellard
    }
515 14ce26e7 bellard
#endif
516 28c3ee3f bellard
    env->cr[0] = new_cr0 | CR0_ET_MASK;
517 1ac157da bellard
    
518 436d8b89 bellard
    /* update PE flag in hidden flags */
519 436d8b89 bellard
    pe_state = (env->cr[0] & CR0_PE_MASK);
520 436d8b89 bellard
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
521 436d8b89 bellard
    /* ensure that ADDSEG is always set in real mode */
522 436d8b89 bellard
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
523 9588b95a bellard
    /* update FPU flags */
524 9588b95a bellard
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
525 9588b95a bellard
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
526 2c0262af bellard
}
527 2c0262af bellard
528 bf079a1e bellard
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
529 bf079a1e bellard
   the PDPT */
530 14ce26e7 bellard
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
531 2c0262af bellard
{
532 1ac157da bellard
    env->cr[3] = new_cr3;
533 2c0262af bellard
    if (env->cr[0] & CR0_PG_MASK) {
534 2c0262af bellard
#if defined(DEBUG_MMU)
535 14ce26e7 bellard
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
536 2c0262af bellard
#endif
537 1ac157da bellard
        tlb_flush(env, 0);
538 2c0262af bellard
    }
539 2c0262af bellard
}
540 2c0262af bellard
541 1ac157da bellard
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
542 2c0262af bellard
{
543 1ac157da bellard
#if defined(DEBUG_MMU)
544 14ce26e7 bellard
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
545 1ac157da bellard
#endif
546 1ac157da bellard
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
547 1ac157da bellard
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
548 1ac157da bellard
        tlb_flush(env, 1);
549 1ac157da bellard
    }
550 664e0f19 bellard
    /* SSE handling */
551 664e0f19 bellard
    if (!(env->cpuid_features & CPUID_SSE))
552 664e0f19 bellard
        new_cr4 &= ~CR4_OSFXSR_MASK;
553 664e0f19 bellard
    if (new_cr4 & CR4_OSFXSR_MASK)
554 664e0f19 bellard
        env->hflags |= HF_OSFXSR_MASK;
555 664e0f19 bellard
    else
556 664e0f19 bellard
        env->hflags &= ~HF_OSFXSR_MASK;
557 664e0f19 bellard
558 1ac157da bellard
    env->cr[4] = new_cr4;
559 2c0262af bellard
}
560 2c0262af bellard
561 2c0262af bellard
/* XXX: also flush 4MB pages */
562 8f091a59 bellard
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
563 2c0262af bellard
{
564 2c0262af bellard
    tlb_flush_page(env, addr);
565 2c0262af bellard
}
566 2c0262af bellard
567 8df1cd07 bellard
#if defined(CONFIG_USER_ONLY) 
568 14ce26e7 bellard
569 8df1cd07 bellard
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
570 8df1cd07 bellard
                             int is_write, int is_user, int is_softmmu)
571 14ce26e7 bellard
{
572 8df1cd07 bellard
    /* user mode only emulation */
573 8df1cd07 bellard
    is_write &= 1;
574 8df1cd07 bellard
    env->cr[2] = addr;
575 8df1cd07 bellard
    env->error_code = (is_write << PG_ERROR_W_BIT);
576 8df1cd07 bellard
    env->error_code |= PG_ERROR_U_MASK;
577 54ca9095 bellard
    env->exception_index = EXCP0E_PAGE;
578 8df1cd07 bellard
    return 1;
579 14ce26e7 bellard
}
580 14ce26e7 bellard
581 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
582 14ce26e7 bellard
{
583 8df1cd07 bellard
    return addr;
584 14ce26e7 bellard
}
585 14ce26e7 bellard
586 8df1cd07 bellard
#else
587 8df1cd07 bellard
588 4b4f782c bellard
#define PHYS_ADDR_MASK 0xfffff000
589 4b4f782c bellard
590 2c0262af bellard
/* return value:
591 2c0262af bellard
   -1 = cannot handle fault 
592 2c0262af bellard
   0  = nothing more to do 
593 2c0262af bellard
   1  = generate PF fault
594 2c0262af bellard
   2  = soft MMU activation required for this block
595 2c0262af bellard
*/
596 14ce26e7 bellard
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
597 4b4f782c bellard
                             int is_write1, int is_user, int is_softmmu)
598 2c0262af bellard
{
599 4b4f782c bellard
    uint64_t ptep, pte;
600 14ce26e7 bellard
    uint32_t pdpe_addr, pde_addr, pte_addr;
601 4b4f782c bellard
    int error_code, is_dirty, prot, page_size, ret, is_write;
602 14ce26e7 bellard
    unsigned long paddr, page_offset;
603 14ce26e7 bellard
    target_ulong vaddr, virt_addr;
604 2c0262af bellard
    
605 436d8b89 bellard
#if defined(DEBUG_MMU)
606 14ce26e7 bellard
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", 
607 4b4f782c bellard
           addr, is_write1, is_user, env->eip);
608 2c0262af bellard
#endif
609 4b4f782c bellard
    is_write = is_write1 & 1;
610 b769d8fe bellard
    
611 2c0262af bellard
    if (!(env->cr[0] & CR0_PG_MASK)) {
612 2c0262af bellard
        pte = addr;
613 461c0471 bellard
        virt_addr = addr & TARGET_PAGE_MASK;
614 4b4f782c bellard
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
615 2c0262af bellard
        page_size = 4096;
616 2c0262af bellard
        goto do_mapping;
617 2c0262af bellard
    }
618 2c0262af bellard
619 14ce26e7 bellard
    if (env->cr[4] & CR4_PAE_MASK) {
620 4b4f782c bellard
        uint64_t pde, pdpe;
621 4b4f782c bellard
622 14ce26e7 bellard
        /* XXX: we only use 32 bit physical addresses */
623 14ce26e7 bellard
#ifdef TARGET_X86_64
624 14ce26e7 bellard
        if (env->hflags & HF_LMA_MASK) {
625 4b4f782c bellard
            uint32_t pml4e_addr;
626 4b4f782c bellard
            uint64_t pml4e;
627 14ce26e7 bellard
            int32_t sext;
628 14ce26e7 bellard
629 14ce26e7 bellard
            /* test virtual address sign extension */
630 14ce26e7 bellard
            sext = (int64_t)addr >> 47;
631 14ce26e7 bellard
            if (sext != 0 && sext != -1) {
632 54ca9095 bellard
                env->error_code = 0;
633 54ca9095 bellard
                env->exception_index = EXCP0D_GPF;
634 54ca9095 bellard
                return 1;
635 14ce26e7 bellard
            }
636 14ce26e7 bellard
            
637 14ce26e7 bellard
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 
638 14ce26e7 bellard
                env->a20_mask;
639 4b4f782c bellard
            pml4e = ldq_phys(pml4e_addr);
640 14ce26e7 bellard
            if (!(pml4e & PG_PRESENT_MASK)) {
641 14ce26e7 bellard
                error_code = 0;
642 14ce26e7 bellard
                goto do_fault;
643 14ce26e7 bellard
            }
644 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
645 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
646 4b4f782c bellard
                goto do_fault;
647 4b4f782c bellard
            }
648 14ce26e7 bellard
            if (!(pml4e & PG_ACCESSED_MASK)) {
649 14ce26e7 bellard
                pml4e |= PG_ACCESSED_MASK;
650 8df1cd07 bellard
                stl_phys_notdirty(pml4e_addr, pml4e);
651 14ce26e7 bellard
            }
652 4b4f782c bellard
            ptep = pml4e ^ PG_NX_MASK;
653 4b4f782c bellard
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) & 
654 14ce26e7 bellard
                env->a20_mask;
655 4b4f782c bellard
            pdpe = ldq_phys(pdpe_addr);
656 14ce26e7 bellard
            if (!(pdpe & PG_PRESENT_MASK)) {
657 14ce26e7 bellard
                error_code = 0;
658 14ce26e7 bellard
                goto do_fault;
659 14ce26e7 bellard
            }
660 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
661 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
662 4b4f782c bellard
                goto do_fault;
663 4b4f782c bellard
            }
664 4b4f782c bellard
            ptep &= pdpe ^ PG_NX_MASK;
665 14ce26e7 bellard
            if (!(pdpe & PG_ACCESSED_MASK)) {
666 14ce26e7 bellard
                pdpe |= PG_ACCESSED_MASK;
667 8df1cd07 bellard
                stl_phys_notdirty(pdpe_addr, pdpe);
668 14ce26e7 bellard
            }
669 4b4f782c bellard
        } else
670 14ce26e7 bellard
#endif
671 14ce26e7 bellard
        {
672 4b4f782c bellard
            /* XXX: load them when cr3 is loaded ? */
673 af661ad1 ths
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & 
674 14ce26e7 bellard
                env->a20_mask;
675 4b4f782c bellard
            pdpe = ldq_phys(pdpe_addr);
676 14ce26e7 bellard
            if (!(pdpe & PG_PRESENT_MASK)) {
677 14ce26e7 bellard
                error_code = 0;
678 14ce26e7 bellard
                goto do_fault;
679 14ce26e7 bellard
            }
680 4b4f782c bellard
            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
681 10f0e412 bellard
        }
682 14ce26e7 bellard
683 4b4f782c bellard
        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
684 14ce26e7 bellard
            env->a20_mask;
685 4b4f782c bellard
        pde = ldq_phys(pde_addr);
686 14ce26e7 bellard
        if (!(pde & PG_PRESENT_MASK)) {
687 14ce26e7 bellard
            error_code = 0;
688 14ce26e7 bellard
            goto do_fault;
689 2c0262af bellard
        }
690 4b4f782c bellard
        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
691 4b4f782c bellard
            error_code = PG_ERROR_RSVD_MASK;
692 4b4f782c bellard
            goto do_fault;
693 4b4f782c bellard
        }
694 4b4f782c bellard
        ptep &= pde ^ PG_NX_MASK;
695 14ce26e7 bellard
        if (pde & PG_PSE_MASK) {
696 14ce26e7 bellard
            /* 2 MB page */
697 14ce26e7 bellard
            page_size = 2048 * 1024;
698 4b4f782c bellard
            ptep ^= PG_NX_MASK;
699 4b4f782c bellard
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
700 4b4f782c bellard
                goto do_fault_protect;
701 4b4f782c bellard
            if (is_user) {
702 4b4f782c bellard
                if (!(ptep & PG_USER_MASK))
703 4b4f782c bellard
                    goto do_fault_protect;
704 4b4f782c bellard
                if (is_write && !(ptep & PG_RW_MASK))
705 4b4f782c bellard
                    goto do_fault_protect;
706 4b4f782c bellard
            } else {
707 4b4f782c bellard
                if ((env->cr[0] & CR0_WP_MASK) && 
708 4b4f782c bellard
                    is_write && !(ptep & PG_RW_MASK)) 
709 4b4f782c bellard
                    goto do_fault_protect;
710 4b4f782c bellard
            }
711 4b4f782c bellard
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
712 4b4f782c bellard
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
713 4b4f782c bellard
                pde |= PG_ACCESSED_MASK;
714 4b4f782c bellard
                if (is_dirty)
715 4b4f782c bellard
                    pde |= PG_DIRTY_MASK;
716 4b4f782c bellard
                stl_phys_notdirty(pde_addr, pde);
717 4b4f782c bellard
            }
718 4b4f782c bellard
            /* align to page_size */
719 4b4f782c bellard
            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff); 
720 4b4f782c bellard
            virt_addr = addr & ~(page_size - 1);
721 14ce26e7 bellard
        } else {
722 14ce26e7 bellard
            /* 4 KB page */
723 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK)) {
724 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
725 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
726 14ce26e7 bellard
            }
727 4b4f782c bellard
            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
728 14ce26e7 bellard
                env->a20_mask;
729 4b4f782c bellard
            pte = ldq_phys(pte_addr);
730 4b4f782c bellard
            if (!(pte & PG_PRESENT_MASK)) {
731 4b4f782c bellard
                error_code = 0;
732 4b4f782c bellard
                goto do_fault;
733 4b4f782c bellard
            }
734 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
735 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
736 4b4f782c bellard
                goto do_fault;
737 4b4f782c bellard
            }
738 4b4f782c bellard
            /* combine pde and pte nx, user and rw protections */
739 4b4f782c bellard
            ptep &= pte ^ PG_NX_MASK;
740 4b4f782c bellard
            ptep ^= PG_NX_MASK;
741 4b4f782c bellard
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
742 4b4f782c bellard
                goto do_fault_protect; 
743 4b4f782c bellard
            if (is_user) {
744 4b4f782c bellard
                if (!(ptep & PG_USER_MASK))
745 4b4f782c bellard
                    goto do_fault_protect;
746 4b4f782c bellard
                if (is_write && !(ptep & PG_RW_MASK))
747 4b4f782c bellard
                    goto do_fault_protect;
748 4b4f782c bellard
            } else {
749 4b4f782c bellard
                if ((env->cr[0] & CR0_WP_MASK) &&
750 4b4f782c bellard
                    is_write && !(ptep & PG_RW_MASK)) 
751 4b4f782c bellard
                    goto do_fault_protect;
752 4b4f782c bellard
            }
753 4b4f782c bellard
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
754 4b4f782c bellard
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
755 4b4f782c bellard
                pte |= PG_ACCESSED_MASK;
756 4b4f782c bellard
                if (is_dirty)
757 4b4f782c bellard
                    pte |= PG_DIRTY_MASK;
758 4b4f782c bellard
                stl_phys_notdirty(pte_addr, pte);
759 4b4f782c bellard
            }
760 4b4f782c bellard
            page_size = 4096;
761 4b4f782c bellard
            virt_addr = addr & ~0xfff;
762 4b4f782c bellard
            pte = pte & (PHYS_ADDR_MASK | 0xfff);
763 2c0262af bellard
        }
764 14ce26e7 bellard
    } else {
765 4b4f782c bellard
        uint32_t pde;
766 4b4f782c bellard
767 2c0262af bellard
        /* page directory entry */
768 af661ad1 ths
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & 
769 14ce26e7 bellard
            env->a20_mask;
770 8df1cd07 bellard
        pde = ldl_phys(pde_addr);
771 14ce26e7 bellard
        if (!(pde & PG_PRESENT_MASK)) {
772 2c0262af bellard
            error_code = 0;
773 2c0262af bellard
            goto do_fault;
774 2c0262af bellard
        }
775 14ce26e7 bellard
        /* if PSE bit is set, then we use a 4MB page */
776 14ce26e7 bellard
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
777 14ce26e7 bellard
            page_size = 4096 * 1024;
778 14ce26e7 bellard
            if (is_user) {
779 14ce26e7 bellard
                if (!(pde & PG_USER_MASK))
780 14ce26e7 bellard
                    goto do_fault_protect;
781 14ce26e7 bellard
                if (is_write && !(pde & PG_RW_MASK))
782 14ce26e7 bellard
                    goto do_fault_protect;
783 14ce26e7 bellard
            } else {
784 14ce26e7 bellard
                if ((env->cr[0] & CR0_WP_MASK) && 
785 14ce26e7 bellard
                    is_write && !(pde & PG_RW_MASK)) 
786 14ce26e7 bellard
                    goto do_fault_protect;
787 14ce26e7 bellard
            }
788 14ce26e7 bellard
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
789 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
790 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
791 14ce26e7 bellard
                if (is_dirty)
792 14ce26e7 bellard
                    pde |= PG_DIRTY_MASK;
793 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
794 14ce26e7 bellard
            }
795 14ce26e7 bellard
        
796 14ce26e7 bellard
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
797 14ce26e7 bellard
            ptep = pte;
798 14ce26e7 bellard
            virt_addr = addr & ~(page_size - 1);
799 2c0262af bellard
        } else {
800 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK)) {
801 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
802 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
803 14ce26e7 bellard
            }
804 14ce26e7 bellard
805 14ce26e7 bellard
            /* page directory entry */
806 14ce26e7 bellard
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & 
807 14ce26e7 bellard
                env->a20_mask;
808 8df1cd07 bellard
            pte = ldl_phys(pte_addr);
809 14ce26e7 bellard
            if (!(pte & PG_PRESENT_MASK)) {
810 14ce26e7 bellard
                error_code = 0;
811 14ce26e7 bellard
                goto do_fault;
812 14ce26e7 bellard
            }
813 14ce26e7 bellard
            /* combine pde and pte user and rw protections */
814 14ce26e7 bellard
            ptep = pte & pde;
815 14ce26e7 bellard
            if (is_user) {
816 14ce26e7 bellard
                if (!(ptep & PG_USER_MASK))
817 14ce26e7 bellard
                    goto do_fault_protect;
818 14ce26e7 bellard
                if (is_write && !(ptep & PG_RW_MASK))
819 14ce26e7 bellard
                    goto do_fault_protect;
820 14ce26e7 bellard
            } else {
821 14ce26e7 bellard
                if ((env->cr[0] & CR0_WP_MASK) &&
822 14ce26e7 bellard
                    is_write && !(ptep & PG_RW_MASK)) 
823 14ce26e7 bellard
                    goto do_fault_protect;
824 14ce26e7 bellard
            }
825 14ce26e7 bellard
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
826 14ce26e7 bellard
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
827 14ce26e7 bellard
                pte |= PG_ACCESSED_MASK;
828 14ce26e7 bellard
                if (is_dirty)
829 14ce26e7 bellard
                    pte |= PG_DIRTY_MASK;
830 8df1cd07 bellard
                stl_phys_notdirty(pte_addr, pte);
831 14ce26e7 bellard
            }
832 14ce26e7 bellard
            page_size = 4096;
833 14ce26e7 bellard
            virt_addr = addr & ~0xfff;
834 2c0262af bellard
        }
835 4b4f782c bellard
    }
836 4b4f782c bellard
    /* the page can be put in the TLB */
837 4b4f782c bellard
    prot = PAGE_READ;
838 4b4f782c bellard
    if (!(ptep & PG_NX_MASK))
839 4b4f782c bellard
        prot |= PAGE_EXEC;
840 4b4f782c bellard
    if (pte & PG_DIRTY_MASK) {
841 4b4f782c bellard
        /* only set write access if already dirty... otherwise wait
842 4b4f782c bellard
           for dirty access */
843 4b4f782c bellard
        if (is_user) {
844 4b4f782c bellard
            if (ptep & PG_RW_MASK)
845 4b4f782c bellard
                prot |= PAGE_WRITE;
846 4b4f782c bellard
        } else {
847 4b4f782c bellard
            if (!(env->cr[0] & CR0_WP_MASK) ||
848 4b4f782c bellard
                (ptep & PG_RW_MASK))
849 4b4f782c bellard
                prot |= PAGE_WRITE;
850 c8135d9a bellard
        }
851 2c0262af bellard
    }
852 2c0262af bellard
 do_mapping:
853 1ac157da bellard
    pte = pte & env->a20_mask;
854 2c0262af bellard
855 436d8b89 bellard
    /* Even if 4MB pages, we map only one 4KB page in the cache to
856 436d8b89 bellard
       avoid filling it too fast */
857 436d8b89 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
858 436d8b89 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
859 436d8b89 bellard
    vaddr = virt_addr + page_offset;
860 436d8b89 bellard
    
861 4b4f782c bellard
    ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
862 2c0262af bellard
    return ret;
863 2c0262af bellard
 do_fault_protect:
864 2c0262af bellard
    error_code = PG_ERROR_P_MASK;
865 2c0262af bellard
 do_fault:
866 2c0262af bellard
    env->cr[2] = addr;
867 4b4f782c bellard
    error_code |= (is_write << PG_ERROR_W_BIT);
868 2c0262af bellard
    if (is_user)
869 4b4f782c bellard
        error_code |= PG_ERROR_U_MASK;
870 4b4f782c bellard
    if (is_write1 == 2 && 
871 4b4f782c bellard
        (env->efer & MSR_EFER_NXE) && 
872 4b4f782c bellard
        (env->cr[4] & CR4_PAE_MASK))
873 4b4f782c bellard
        error_code |= PG_ERROR_I_D_MASK;
874 4b4f782c bellard
    env->error_code = error_code;
875 54ca9095 bellard
    env->exception_index = EXCP0E_PAGE;
876 2c0262af bellard
    return 1;
877 2c0262af bellard
}
878 10f0e412 bellard
879 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
880 10f0e412 bellard
{
881 f51589da bellard
    uint32_t pde_addr, pte_addr;
882 10f0e412 bellard
    uint32_t pde, pte, paddr, page_offset, page_size;
883 10f0e412 bellard
884 f51589da bellard
    if (env->cr[4] & CR4_PAE_MASK) {
885 f51589da bellard
        uint32_t pdpe_addr, pde_addr, pte_addr;
886 f51589da bellard
        uint32_t pdpe;
887 f51589da bellard
888 f51589da bellard
        /* XXX: we only use 32 bit physical addresses */
889 f51589da bellard
#ifdef TARGET_X86_64
890 f51589da bellard
        if (env->hflags & HF_LMA_MASK) {
891 f51589da bellard
            uint32_t pml4e_addr, pml4e;
892 f51589da bellard
            int32_t sext;
893 f51589da bellard
894 f51589da bellard
            /* test virtual address sign extension */
895 f51589da bellard
            sext = (int64_t)addr >> 47;
896 f51589da bellard
            if (sext != 0 && sext != -1)
897 f51589da bellard
                return -1;
898 f51589da bellard
            
899 f51589da bellard
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 
900 f51589da bellard
                env->a20_mask;
901 8df1cd07 bellard
            pml4e = ldl_phys(pml4e_addr);
902 f51589da bellard
            if (!(pml4e & PG_PRESENT_MASK))
903 f51589da bellard
                return -1;
904 f51589da bellard
            
905 f51589da bellard
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 
906 f51589da bellard
                env->a20_mask;
907 8df1cd07 bellard
            pdpe = ldl_phys(pdpe_addr);
908 f51589da bellard
            if (!(pdpe & PG_PRESENT_MASK))
909 f51589da bellard
                return -1;
910 f51589da bellard
        } else 
911 f51589da bellard
#endif
912 f51589da bellard
        {
913 af661ad1 ths
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & 
914 f51589da bellard
                env->a20_mask;
915 8df1cd07 bellard
            pdpe = ldl_phys(pdpe_addr);
916 f51589da bellard
            if (!(pdpe & PG_PRESENT_MASK))
917 f51589da bellard
                return -1;
918 f51589da bellard
        }
919 f51589da bellard
920 f51589da bellard
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
921 f51589da bellard
            env->a20_mask;
922 8df1cd07 bellard
        pde = ldl_phys(pde_addr);
923 f51589da bellard
        if (!(pde & PG_PRESENT_MASK)) {
924 10f0e412 bellard
            return -1;
925 f51589da bellard
        }
926 f51589da bellard
        if (pde & PG_PSE_MASK) {
927 f51589da bellard
            /* 2 MB page */
928 f51589da bellard
            page_size = 2048 * 1024;
929 f51589da bellard
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
930 f51589da bellard
        } else {
931 f51589da bellard
            /* 4 KB page */
932 f51589da bellard
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
933 f51589da bellard
                env->a20_mask;
934 f51589da bellard
            page_size = 4096;
935 8df1cd07 bellard
            pte = ldl_phys(pte_addr);
936 f51589da bellard
        }
937 f51589da bellard
    } else {
938 f51589da bellard
        if (!(env->cr[0] & CR0_PG_MASK)) {
939 f51589da bellard
            pte = addr;
940 f51589da bellard
            page_size = 4096;
941 10f0e412 bellard
        } else {
942 10f0e412 bellard
            /* page directory entry */
943 af661ad1 ths
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
944 8df1cd07 bellard
            pde = ldl_phys(pde_addr);
945 f51589da bellard
            if (!(pde & PG_PRESENT_MASK)) 
946 10f0e412 bellard
                return -1;
947 f51589da bellard
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
948 f51589da bellard
                pte = pde & ~0x003ff000; /* align to 4MB */
949 f51589da bellard
                page_size = 4096 * 1024;
950 f51589da bellard
            } else {
951 f51589da bellard
                /* page directory entry */
952 f51589da bellard
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
953 8df1cd07 bellard
                pte = ldl_phys(pte_addr);
954 f51589da bellard
                if (!(pte & PG_PRESENT_MASK))
955 f51589da bellard
                    return -1;
956 f51589da bellard
                page_size = 4096;
957 f51589da bellard
            }
958 10f0e412 bellard
        }
959 f51589da bellard
        pte = pte & env->a20_mask;
960 10f0e412 bellard
    }
961 f51589da bellard
962 10f0e412 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
963 10f0e412 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
964 10f0e412 bellard
    return paddr;
965 10f0e412 bellard
}
966 8df1cd07 bellard
#endif /* !CONFIG_USER_ONLY */
967 9588b95a bellard
968 9588b95a bellard
#if defined(USE_CODE_COPY)
969 9588b95a bellard
struct fpstate {
970 9588b95a bellard
    uint16_t fpuc;
971 9588b95a bellard
    uint16_t dummy1;
972 9588b95a bellard
    uint16_t fpus;
973 9588b95a bellard
    uint16_t dummy2;
974 9588b95a bellard
    uint16_t fptag;
975 9588b95a bellard
    uint16_t dummy3;
976 9588b95a bellard
977 9588b95a bellard
    uint32_t fpip;
978 9588b95a bellard
    uint32_t fpcs;
979 9588b95a bellard
    uint32_t fpoo;
980 9588b95a bellard
    uint32_t fpos;
981 9588b95a bellard
    uint8_t fpregs1[8 * 10];
982 9588b95a bellard
};
983 9588b95a bellard
984 9588b95a bellard
void restore_native_fp_state(CPUState *env)
985 9588b95a bellard
{
986 9588b95a bellard
    int fptag, i, j;
987 9588b95a bellard
    struct fpstate fp1, *fp = &fp1;
988 9588b95a bellard
    
989 9588b95a bellard
    fp->fpuc = env->fpuc;
990 9588b95a bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
991 9588b95a bellard
    fptag = 0;
992 9588b95a bellard
    for (i=7; i>=0; i--) {
993 9588b95a bellard
        fptag <<= 2;
994 9588b95a bellard
        if (env->fptags[i]) {
995 9588b95a bellard
            fptag |= 3;
996 9588b95a bellard
        } else {
997 9588b95a bellard
            /* the FPU automatically computes it */
998 9588b95a bellard
        }
999 9588b95a bellard
    }
1000 9588b95a bellard
    fp->fptag = fptag;
1001 9588b95a bellard
    j = env->fpstt;
1002 9588b95a bellard
    for(i = 0;i < 8; i++) {
1003 664e0f19 bellard
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
1004 9588b95a bellard
        j = (j + 1) & 7;
1005 9588b95a bellard
    }
1006 9588b95a bellard
    asm volatile ("frstor %0" : "=m" (*fp));
1007 9588b95a bellard
    env->native_fp_regs = 1;
1008 9588b95a bellard
}
1009 9588b95a bellard
 
1010 9588b95a bellard
void save_native_fp_state(CPUState *env)
1011 9588b95a bellard
{
1012 9588b95a bellard
    int fptag, i, j;
1013 9588b95a bellard
    uint16_t fpuc;
1014 9588b95a bellard
    struct fpstate fp1, *fp = &fp1;
1015 9588b95a bellard
1016 9588b95a bellard
    asm volatile ("fsave %0" : : "m" (*fp));
1017 9588b95a bellard
    env->fpuc = fp->fpuc;
1018 9588b95a bellard
    env->fpstt = (fp->fpus >> 11) & 7;
1019 9588b95a bellard
    env->fpus = fp->fpus & ~0x3800;
1020 9588b95a bellard
    fptag = fp->fptag;
1021 9588b95a bellard
    for(i = 0;i < 8; i++) {
1022 9588b95a bellard
        env->fptags[i] = ((fptag & 3) == 3);
1023 9588b95a bellard
        fptag >>= 2;
1024 9588b95a bellard
    }
1025 9588b95a bellard
    j = env->fpstt;
1026 9588b95a bellard
    for(i = 0;i < 8; i++) {
1027 664e0f19 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
1028 9588b95a bellard
        j = (j + 1) & 7;
1029 9588b95a bellard
    }
1030 9588b95a bellard
    /* we must restore the default rounding state */
1031 9588b95a bellard
    /* XXX: we do not restore the exception state */
1032 9588b95a bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
1033 9588b95a bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
1034 9588b95a bellard
    env->native_fp_regs = 0;
1035 9588b95a bellard
}
1036 9588b95a bellard
#endif