Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 977d5710

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