Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 1247c5f7

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