Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ c326e0af

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