Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 3b21e03e

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