Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ c5d6edc3

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