Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 5516d670

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