update
[qemu] / target-i386 / helper2.c
1 /*
2  *  i386 helpers (without register variable usage)
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
27
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "svm.h"
31 #include "qemu-common.h"
32
33 //#define DEBUG_MMU
34
35 static int cpu_x86_register (CPUX86State *env, const char *cpu_model);
36
37 static void add_flagname_to_bitmaps(char *flagname, uint32_t *features, 
38                                     uint32_t *ext_features, 
39                                     uint32_t *ext2_features, 
40                                     uint32_t *ext3_features)
41 {
42     int i;
43     /* feature flags taken from "Intel Processor Identification and the CPUID
44      * Instruction" and AMD's "CPUID Specification". In cases of disagreement 
45      * about feature names, the Linux name is used. */
46     const char *feature_name[] = {
47         "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
48         "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
49         "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
50         "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
51     };
52     const char *ext_feature_name[] = {
53        "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
54        "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
55        NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
56        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
57     };
58     const char *ext2_feature_name[] = {
59        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
60        "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mttr", "pge", "mca", "cmov",
61        "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
62        "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
63     };
64     const char *ext3_feature_name[] = {
65        "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
66        "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
67        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
68        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
69     };
70
71     for ( i = 0 ; i < 32 ; i++ ) 
72         if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
73             *features |= 1 << i;
74             return;
75         }
76     for ( i = 0 ; i < 32 ; i++ ) 
77         if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
78             *ext_features |= 1 << i;
79             return;
80         }
81     for ( i = 0 ; i < 32 ; i++ ) 
82         if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
83             *ext2_features |= 1 << i;
84             return;
85         }
86     for ( i = 0 ; i < 32 ; i++ ) 
87         if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
88             *ext3_features |= 1 << i;
89             return;
90         }
91     fprintf(stderr, "CPU feature %s not found\n", flagname);
92 }
93
94 CPUX86State *cpu_x86_init(const char *cpu_model)
95 {
96     CPUX86State *env;
97     static int inited;
98
99     env = qemu_mallocz(sizeof(CPUX86State));
100     if (!env)
101         return NULL;
102     cpu_exec_init(env);
103     env->cpu_model_str = cpu_model;
104
105     /* init various static tables */
106     if (!inited) {
107         inited = 1;
108         optimize_flags_init();
109     }
110     if (cpu_x86_register(env, cpu_model) < 0) {
111         cpu_x86_close(env);
112         return NULL;
113     }
114     cpu_reset(env);
115 #ifdef USE_KQEMU
116     kqemu_init(env);
117 #endif
118     return env;
119 }
120
121 typedef struct x86_def_t {
122     const char *name;
123     uint32_t level;
124     uint32_t vendor1, vendor2, vendor3;
125     int family;
126     int model;
127     int stepping;
128     uint32_t features, ext_features, ext2_features, ext3_features;
129     uint32_t xlevel;
130 } x86_def_t;
131
132 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
133 #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
134           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX)
135 #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
136           CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
137           CPUID_PSE36 | CPUID_FXSR)
138 #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
139 #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
140           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
141           CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
142           CPUID_PAE | CPUID_SEP | CPUID_APIC)
143 static x86_def_t x86_defs[] = {
144 #ifdef TARGET_X86_64
145     {
146         .name = "qemu64",
147         .level = 2,
148         .vendor1 = 0x68747541, /* "Auth" */
149         .vendor2 = 0x69746e65, /* "enti" */
150         .vendor3 = 0x444d4163, /* "cAMD" */
151         .family = 6,
152         .model = 2,
153         .stepping = 3,
154         .features = PPRO_FEATURES | 
155         /* these features are needed for Win64 and aren't fully implemented */
156             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
157         /* this feature is needed for Solaris and isn't fully implemented */
158             CPUID_PSE36,
159         .ext_features = CPUID_EXT_SSE3,
160         .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
161             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
162             CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
163         .ext3_features = CPUID_EXT3_SVM,
164         .xlevel = 0x8000000A,
165     },
166 #endif
167     {
168         .name = "qemu32",
169         .level = 2,
170         .family = 6,
171         .model = 3,
172         .stepping = 3,
173         .features = PPRO_FEATURES,
174         .ext_features = CPUID_EXT_SSE3,
175         .xlevel = 0,
176     },
177     {
178         .name = "486",
179         .level = 0,
180         .family = 4,
181         .model = 0,
182         .stepping = 0,
183         .features = I486_FEATURES,
184         .xlevel = 0,
185     },
186     {
187         .name = "pentium",
188         .level = 1,
189         .family = 5,
190         .model = 4,
191         .stepping = 3,
192         .features = PENTIUM_FEATURES,
193         .xlevel = 0,
194     },
195     {
196         .name = "pentium2",
197         .level = 2,
198         .family = 6,
199         .model = 5,
200         .stepping = 2,
201         .features = PENTIUM2_FEATURES,
202         .xlevel = 0,
203     },
204     {
205         .name = "pentium3",
206         .level = 2,
207         .family = 6,
208         .model = 7,
209         .stepping = 3,
210         .features = PENTIUM3_FEATURES,
211         .xlevel = 0,
212     },
213     {
214         .name = "athlon",
215         .level = 2,
216         .vendor1 = 0x68747541, /* "Auth" */
217         .vendor2 = 0x69746e65, /* "enti" */
218         .vendor3 = 0x444d4163, /* "cAMD" */
219         .family = 6,
220         .model = 2,
221         .stepping = 3,
222         .features = PPRO_FEATURES | PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
223         .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
224         .xlevel = 0x80000008,
225     },
226 };
227
228 static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
229 {
230     unsigned int i;
231     x86_def_t *def;
232
233     char *s = strdup(cpu_model);
234     char *featurestr, *name = strtok(s, ",");
235     uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
236     uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
237     int family = -1, model = -1, stepping = -1;
238
239     def = NULL;
240     for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
241         if (strcmp(name, x86_defs[i].name) == 0) {
242             def = &x86_defs[i];
243             break;
244         }
245     }
246     if (!def)
247         goto error;
248     memcpy(x86_cpu_def, def, sizeof(*def));
249
250     featurestr = strtok(NULL, ",");
251
252     while (featurestr) {
253         char *val;
254         if (featurestr[0] == '+') {
255             add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
256         } else if (featurestr[0] == '-') {
257             add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
258         } else if ((val = strchr(featurestr, '='))) {
259             *val = 0; val++;
260             if (!strcmp(featurestr, "family")) {
261                 char *err;
262                 family = strtol(val, &err, 10);
263                 if (!*val || *err || family < 0) {
264                     fprintf(stderr, "bad numerical value %s\n", val);
265                     x86_cpu_def = 0;
266                     goto error;
267                 }
268                 x86_cpu_def->family = family;
269             } else if (!strcmp(featurestr, "model")) {
270                 char *err;
271                 model = strtol(val, &err, 10);
272                 if (!*val || *err || model < 0 || model > 0xf) {
273                     fprintf(stderr, "bad numerical value %s\n", val);
274                     x86_cpu_def = 0;
275                     goto error;
276                 }
277                 x86_cpu_def->model = model;
278             } else if (!strcmp(featurestr, "stepping")) {
279                 char *err;
280                 stepping = strtol(val, &err, 10);
281                 if (!*val || *err || stepping < 0 || stepping > 0xf) {
282                     fprintf(stderr, "bad numerical value %s\n", val);
283                     x86_cpu_def = 0;
284                     goto error;
285                 }
286                 x86_cpu_def->stepping = stepping;
287             } else {
288                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
289                 x86_cpu_def = 0;
290                 goto error;
291             }
292         } else {
293             fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
294             x86_cpu_def = 0;
295             goto error;
296         }
297         featurestr = strtok(NULL, ",");
298     }
299     x86_cpu_def->features |= plus_features;
300     x86_cpu_def->ext_features |= plus_ext_features;
301     x86_cpu_def->ext2_features |= plus_ext2_features;
302     x86_cpu_def->ext3_features |= plus_ext3_features;
303     x86_cpu_def->features &= ~minus_features;
304     x86_cpu_def->ext_features &= ~minus_ext_features;
305     x86_cpu_def->ext2_features &= ~minus_ext2_features;
306     x86_cpu_def->ext3_features &= ~minus_ext3_features;
307     free(s);
308     return 0;
309
310 error:
311     free(s);
312     return -1;
313 }
314
315 void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
316 {
317     unsigned int i;
318
319     for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
320         (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
321 }
322
323 static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
324 {
325     x86_def_t def1, *def = &def1;
326
327     if (cpu_x86_find_by_name(def, cpu_model) < 0)
328         return -1;
329     if (def->vendor1) {
330         env->cpuid_vendor1 = def->vendor1;
331         env->cpuid_vendor2 = def->vendor2;
332         env->cpuid_vendor3 = def->vendor3;
333     } else {
334         env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
335         env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
336         env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
337     }
338     env->cpuid_level = def->level;
339     env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
340     env->cpuid_features = def->features;
341     env->pat = 0x0007040600070406ULL;
342     env->cpuid_ext_features = def->ext_features;
343     env->cpuid_ext2_features = def->ext2_features;
344     env->cpuid_xlevel = def->xlevel;
345     env->cpuid_ext3_features = def->ext3_features;
346     {
347         const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
348         int c, len, i;
349         len = strlen(model_id);
350         for(i = 0; i < 48; i++) {
351             if (i >= len)
352                 c = '\0';
353             else
354                 c = model_id[i];
355             env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
356         }
357     }
358     return 0;
359 }
360
361 /* NOTE: must be called outside the CPU execute loop */
362 void cpu_reset(CPUX86State *env)
363 {
364     int i;
365
366     memset(env, 0, offsetof(CPUX86State, breakpoints));
367
368     tlb_flush(env, 1);
369
370     env->old_exception = -1;
371
372     /* init to reset state */
373
374 #ifdef CONFIG_SOFTMMU
375     env->hflags |= HF_SOFTMMU_MASK;
376 #endif
377     env->hflags |= HF_GIF_MASK;
378
379     cpu_x86_update_cr0(env, 0x60000010);
380     env->a20_mask = ~0x0;
381     env->smbase = 0x30000;
382
383     env->idt.limit = 0xffff;
384     env->gdt.limit = 0xffff;
385     env->ldt.limit = 0xffff;
386     env->ldt.flags = DESC_P_MASK;
387     env->tr.limit = 0xffff;
388     env->tr.flags = DESC_P_MASK;
389
390     cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
391     cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
392     cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
393     cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
394     cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
395     cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
396
397     env->eip = 0xfff0;
398     env->regs[R_EDX] = env->cpuid_version;
399
400     env->eflags = 0x2;
401
402     /* FPU init */
403     for(i = 0;i < 8; i++)
404         env->fptags[i] = 1;
405     env->fpuc = 0x37f;
406
407     env->mxcsr = 0x1f80;
408 }
409
410 void cpu_x86_close(CPUX86State *env)
411 {
412     free(env);
413 }
414
415 /***********************************************************/
416 /* x86 debug */
417
418 static const char *cc_op_str[] = {
419     "DYNAMIC",
420     "EFLAGS",
421
422     "MULB",
423     "MULW",
424     "MULL",
425     "MULQ",
426
427     "ADDB",
428     "ADDW",
429     "ADDL",
430     "ADDQ",
431
432     "ADCB",
433     "ADCW",
434     "ADCL",
435     "ADCQ",
436
437     "SUBB",
438     "SUBW",
439     "SUBL",
440     "SUBQ",
441
442     "SBBB",
443     "SBBW",
444     "SBBL",
445     "SBBQ",
446
447     "LOGICB",
448     "LOGICW",
449     "LOGICL",
450     "LOGICQ",
451
452     "INCB",
453     "INCW",
454     "INCL",
455     "INCQ",
456
457     "DECB",
458     "DECW",
459     "DECL",
460     "DECQ",
461
462     "SHLB",
463     "SHLW",
464     "SHLL",
465     "SHLQ",
466
467     "SARB",
468     "SARW",
469     "SARL",
470     "SARQ",
471 };
472
473 void cpu_dump_state(CPUState *env, FILE *f,
474                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
475                     int flags)
476 {
477     int eflags, i, nb;
478     char cc_op_name[32];
479     static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
480
481     eflags = env->eflags;
482 #ifdef TARGET_X86_64
483     if (env->hflags & HF_CS64_MASK) {
484         cpu_fprintf(f,
485                     "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
486                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
487                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
488                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
489                     "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
490                     env->regs[R_EAX],
491                     env->regs[R_EBX],
492                     env->regs[R_ECX],
493                     env->regs[R_EDX],
494                     env->regs[R_ESI],
495                     env->regs[R_EDI],
496                     env->regs[R_EBP],
497                     env->regs[R_ESP],
498                     env->regs[8],
499                     env->regs[9],
500                     env->regs[10],
501                     env->regs[11],
502                     env->regs[12],
503                     env->regs[13],
504                     env->regs[14],
505                     env->regs[15],
506                     env->eip, eflags,
507                     eflags & DF_MASK ? 'D' : '-',
508                     eflags & CC_O ? 'O' : '-',
509                     eflags & CC_S ? 'S' : '-',
510                     eflags & CC_Z ? 'Z' : '-',
511                     eflags & CC_A ? 'A' : '-',
512                     eflags & CC_P ? 'P' : '-',
513                     eflags & CC_C ? 'C' : '-',
514                     env->hflags & HF_CPL_MASK,
515                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
516                     (int)(env->a20_mask >> 20) & 1,
517                     (env->hflags >> HF_SMM_SHIFT) & 1,
518                     (env->hflags >> HF_HALTED_SHIFT) & 1);
519     } else
520 #endif
521     {
522         cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
523                     "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
524                     "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
525                     (uint32_t)env->regs[R_EAX],
526                     (uint32_t)env->regs[R_EBX],
527                     (uint32_t)env->regs[R_ECX],
528                     (uint32_t)env->regs[R_EDX],
529                     (uint32_t)env->regs[R_ESI],
530                     (uint32_t)env->regs[R_EDI],
531                     (uint32_t)env->regs[R_EBP],
532                     (uint32_t)env->regs[R_ESP],
533                     (uint32_t)env->eip, eflags,
534                     eflags & DF_MASK ? 'D' : '-',
535                     eflags & CC_O ? 'O' : '-',
536                     eflags & CC_S ? 'S' : '-',
537                     eflags & CC_Z ? 'Z' : '-',
538                     eflags & CC_A ? 'A' : '-',
539                     eflags & CC_P ? 'P' : '-',
540                     eflags & CC_C ? 'C' : '-',
541                     env->hflags & HF_CPL_MASK,
542                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
543                     (int)(env->a20_mask >> 20) & 1,
544                     (env->hflags >> HF_SMM_SHIFT) & 1,
545                     (env->hflags >> HF_HALTED_SHIFT) & 1);
546     }
547
548 #ifdef TARGET_X86_64
549     if (env->hflags & HF_LMA_MASK) {
550         for(i = 0; i < 6; i++) {
551             SegmentCache *sc = &env->segs[i];
552             cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
553                         seg_name[i],
554                         sc->selector,
555                         sc->base,
556                         sc->limit,
557                         sc->flags);
558         }
559         cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
560                     env->ldt.selector,
561                     env->ldt.base,
562                     env->ldt.limit,
563                     env->ldt.flags);
564         cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
565                     env->tr.selector,
566                     env->tr.base,
567                     env->tr.limit,
568                     env->tr.flags);
569         cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
570                     env->gdt.base, env->gdt.limit);
571         cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
572                     env->idt.base, env->idt.limit);
573         cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
574                     (uint32_t)env->cr[0],
575                     env->cr[2],
576                     env->cr[3],
577                     (uint32_t)env->cr[4]);
578     } else
579 #endif
580     {
581         for(i = 0; i < 6; i++) {
582             SegmentCache *sc = &env->segs[i];
583             cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
584                         seg_name[i],
585                         sc->selector,
586                         (uint32_t)sc->base,
587                         sc->limit,
588                         sc->flags);
589         }
590         cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
591                     env->ldt.selector,
592                     (uint32_t)env->ldt.base,
593                     env->ldt.limit,
594                     env->ldt.flags);
595         cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
596                     env->tr.selector,
597                     (uint32_t)env->tr.base,
598                     env->tr.limit,
599                     env->tr.flags);
600         cpu_fprintf(f, "GDT=     %08x %08x\n",
601                     (uint32_t)env->gdt.base, env->gdt.limit);
602         cpu_fprintf(f, "IDT=     %08x %08x\n",
603                     (uint32_t)env->idt.base, env->idt.limit);
604         cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
605                     (uint32_t)env->cr[0],
606                     (uint32_t)env->cr[2],
607                     (uint32_t)env->cr[3],
608                     (uint32_t)env->cr[4]);
609     }
610     if (flags & X86_DUMP_CCOP) {
611         if ((unsigned)env->cc_op < CC_OP_NB)
612             snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
613         else
614             snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
615 #ifdef TARGET_X86_64
616         if (env->hflags & HF_CS64_MASK) {
617             cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
618                         env->cc_src, env->cc_dst,
619                         cc_op_name);
620         } else
621 #endif
622         {
623             cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
624                         (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
625                         cc_op_name);
626         }
627     }
628     if (flags & X86_DUMP_FPU) {
629         int fptag;
630         fptag = 0;
631         for(i = 0; i < 8; i++) {
632             fptag |= ((!env->fptags[i]) << i);
633         }
634         cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
635                     env->fpuc,
636                     (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
637                     env->fpstt,
638                     fptag,
639                     env->mxcsr);
640         for(i=0;i<8;i++) {
641 #if defined(USE_X86LDOUBLE)
642             union {
643                 long double d;
644                 struct {
645                     uint64_t lower;
646                     uint16_t upper;
647                 } l;
648             } tmp;
649             tmp.d = env->fpregs[i].d;
650             cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
651                         i, tmp.l.lower, tmp.l.upper);
652 #else
653             cpu_fprintf(f, "FPR%d=%016" PRIx64,
654                         i, env->fpregs[i].mmx.q);
655 #endif
656             if ((i & 1) == 1)
657                 cpu_fprintf(f, "\n");
658             else
659                 cpu_fprintf(f, " ");
660         }
661         if (env->hflags & HF_CS64_MASK)
662             nb = 16;
663         else
664             nb = 8;
665         for(i=0;i<nb;i++) {
666             cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
667                         i,
668                         env->xmm_regs[i].XMM_L(3),
669                         env->xmm_regs[i].XMM_L(2),
670                         env->xmm_regs[i].XMM_L(1),
671                         env->xmm_regs[i].XMM_L(0));
672             if ((i & 1) == 1)
673                 cpu_fprintf(f, "\n");
674             else
675                 cpu_fprintf(f, " ");
676         }
677     }
678 }
679
680 /***********************************************************/
681 /* x86 mmu */
682 /* XXX: add PGE support */
683
684 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
685 {
686     a20_state = (a20_state != 0);
687     if (a20_state != ((env->a20_mask >> 20) & 1)) {
688 #if defined(DEBUG_MMU)
689         printf("A20 update: a20=%d\n", a20_state);
690 #endif
691         /* if the cpu is currently executing code, we must unlink it and
692            all the potentially executing TB */
693         cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
694
695         /* when a20 is changed, all the MMU mappings are invalid, so
696            we must flush everything */
697         tlb_flush(env, 1);
698         env->a20_mask = (~0x100000) | (a20_state << 20);
699     }
700 }
701
702 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
703 {
704     int pe_state;
705
706 #if defined(DEBUG_MMU)
707     printf("CR0 update: CR0=0x%08x\n", new_cr0);
708 #endif
709     if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
710         (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
711         tlb_flush(env, 1);
712     }
713
714 #ifdef TARGET_X86_64
715     if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
716         (env->efer & MSR_EFER_LME)) {
717         /* enter in long mode */
718         /* XXX: generate an exception */
719         if (!(env->cr[4] & CR4_PAE_MASK))
720             return;
721         env->efer |= MSR_EFER_LMA;
722         env->hflags |= HF_LMA_MASK;
723     } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
724                (env->efer & MSR_EFER_LMA)) {
725         /* exit long mode */
726         env->efer &= ~MSR_EFER_LMA;
727         env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
728         env->eip &= 0xffffffff;
729     }
730 #endif
731     env->cr[0] = new_cr0 | CR0_ET_MASK;
732
733     /* update PE flag in hidden flags */
734     pe_state = (env->cr[0] & CR0_PE_MASK);
735     env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
736     /* ensure that ADDSEG is always set in real mode */
737     env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
738     /* update FPU flags */
739     env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
740         ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
741 }
742
743 /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
744    the PDPT */
745 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
746 {
747     env->cr[3] = new_cr3;
748     if (env->cr[0] & CR0_PG_MASK) {
749 #if defined(DEBUG_MMU)
750         printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
751 #endif
752         tlb_flush(env, 0);
753     }
754 }
755
756 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
757 {
758 #if defined(DEBUG_MMU)
759     printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
760 #endif
761     if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
762         (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
763         tlb_flush(env, 1);
764     }
765     /* SSE handling */
766     if (!(env->cpuid_features & CPUID_SSE))
767         new_cr4 &= ~CR4_OSFXSR_MASK;
768     if (new_cr4 & CR4_OSFXSR_MASK)
769         env->hflags |= HF_OSFXSR_MASK;
770     else
771         env->hflags &= ~HF_OSFXSR_MASK;
772
773     env->cr[4] = new_cr4;
774 }
775
776 /* XXX: also flush 4MB pages */
777 void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
778 {
779     tlb_flush_page(env, addr);
780 }
781
782 #if defined(CONFIG_USER_ONLY)
783
784 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
785                              int is_write, int mmu_idx, int is_softmmu)
786 {
787     /* user mode only emulation */
788     is_write &= 1;
789     env->cr[2] = addr;
790     env->error_code = (is_write << PG_ERROR_W_BIT);
791     env->error_code |= PG_ERROR_U_MASK;
792     env->exception_index = EXCP0E_PAGE;
793     return 1;
794 }
795
796 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
797 {
798     return addr;
799 }
800
801 #else
802
803 /* XXX: This value should match the one returned by CPUID
804  * and in exec.c */
805 #if defined(USE_KQEMU)
806 #define PHYS_ADDR_MASK 0xfffff000L
807 #else
808 # if defined(TARGET_X86_64)
809 # define PHYS_ADDR_MASK 0xfffffff000L
810 # else
811 # define PHYS_ADDR_MASK 0xffffff000L
812 # endif
813 #endif
814
815 /* return value:
816    -1 = cannot handle fault
817    0  = nothing more to do
818    1  = generate PF fault
819    2  = soft MMU activation required for this block
820 */
821 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
822                              int is_write1, int mmu_idx, int is_softmmu)
823 {
824     uint64_t ptep, pte;
825     target_ulong pde_addr, pte_addr;
826     int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
827     target_phys_addr_t paddr;
828     uint32_t page_offset;
829     target_ulong vaddr, virt_addr;
830
831     is_user = mmu_idx == MMU_USER_IDX;
832 #if defined(DEBUG_MMU)
833     printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
834            addr, is_write1, is_user, env->eip);
835 #endif
836     is_write = is_write1 & 1;
837
838     if (!(env->cr[0] & CR0_PG_MASK)) {
839         pte = addr;
840         virt_addr = addr & TARGET_PAGE_MASK;
841         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
842         page_size = 4096;
843         goto do_mapping;
844     }
845
846     if (env->cr[4] & CR4_PAE_MASK) {
847         uint64_t pde, pdpe;
848         target_ulong pdpe_addr;
849
850 #ifdef TARGET_X86_64
851         if (env->hflags & HF_LMA_MASK) {
852             uint64_t pml4e_addr, pml4e;
853             int32_t sext;
854
855             /* test virtual address sign extension */
856             sext = (int64_t)addr >> 47;
857             if (sext != 0 && sext != -1) {
858                 env->error_code = 0;
859                 env->exception_index = EXCP0D_GPF;
860                 return 1;
861             }
862
863             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
864                 env->a20_mask;
865             pml4e = ldq_phys(pml4e_addr);
866             if (!(pml4e & PG_PRESENT_MASK)) {
867                 error_code = 0;
868                 goto do_fault;
869             }
870             if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
871                 error_code = PG_ERROR_RSVD_MASK;
872                 goto do_fault;
873             }
874             if (!(pml4e & PG_ACCESSED_MASK)) {
875                 pml4e |= PG_ACCESSED_MASK;
876                 stl_phys_notdirty(pml4e_addr, pml4e);
877             }
878             ptep = pml4e ^ PG_NX_MASK;
879             pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
880                 env->a20_mask;
881             pdpe = ldq_phys(pdpe_addr);
882             if (!(pdpe & PG_PRESENT_MASK)) {
883                 error_code = 0;
884                 goto do_fault;
885             }
886             if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
887                 error_code = PG_ERROR_RSVD_MASK;
888                 goto do_fault;
889             }
890             ptep &= pdpe ^ PG_NX_MASK;
891             if (!(pdpe & PG_ACCESSED_MASK)) {
892                 pdpe |= PG_ACCESSED_MASK;
893                 stl_phys_notdirty(pdpe_addr, pdpe);
894             }
895         } else
896 #endif
897         {
898             /* XXX: load them when cr3 is loaded ? */
899             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
900                 env->a20_mask;
901             pdpe = ldq_phys(pdpe_addr);
902             if (!(pdpe & PG_PRESENT_MASK)) {
903                 error_code = 0;
904                 goto do_fault;
905             }
906             ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
907         }
908
909         pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
910             env->a20_mask;
911         pde = ldq_phys(pde_addr);
912         if (!(pde & PG_PRESENT_MASK)) {
913             error_code = 0;
914             goto do_fault;
915         }
916         if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
917             error_code = PG_ERROR_RSVD_MASK;
918             goto do_fault;
919         }
920         ptep &= pde ^ PG_NX_MASK;
921         if (pde & PG_PSE_MASK) {
922             /* 2 MB page */
923             page_size = 2048 * 1024;
924             ptep ^= PG_NX_MASK;
925             if ((ptep & PG_NX_MASK) && is_write1 == 2)
926                 goto do_fault_protect;
927             if (is_user) {
928                 if (!(ptep & PG_USER_MASK))
929                     goto do_fault_protect;
930                 if (is_write && !(ptep & PG_RW_MASK))
931                     goto do_fault_protect;
932             } else {
933                 if ((env->cr[0] & CR0_WP_MASK) &&
934                     is_write && !(ptep & PG_RW_MASK))
935                     goto do_fault_protect;
936             }
937             is_dirty = is_write && !(pde & PG_DIRTY_MASK);
938             if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
939                 pde |= PG_ACCESSED_MASK;
940                 if (is_dirty)
941                     pde |= PG_DIRTY_MASK;
942                 stl_phys_notdirty(pde_addr, pde);
943             }
944             /* align to page_size */
945             pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
946             virt_addr = addr & ~(page_size - 1);
947         } else {
948             /* 4 KB page */
949             if (!(pde & PG_ACCESSED_MASK)) {
950                 pde |= PG_ACCESSED_MASK;
951                 stl_phys_notdirty(pde_addr, pde);
952             }
953             pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
954                 env->a20_mask;
955             pte = ldq_phys(pte_addr);
956             if (!(pte & PG_PRESENT_MASK)) {
957                 error_code = 0;
958                 goto do_fault;
959             }
960             if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
961                 error_code = PG_ERROR_RSVD_MASK;
962                 goto do_fault;
963             }
964             /* combine pde and pte nx, user and rw protections */
965             ptep &= pte ^ PG_NX_MASK;
966             ptep ^= PG_NX_MASK;
967             if ((ptep & PG_NX_MASK) && is_write1 == 2)
968                 goto do_fault_protect;
969             if (is_user) {
970                 if (!(ptep & PG_USER_MASK))
971                     goto do_fault_protect;
972                 if (is_write && !(ptep & PG_RW_MASK))
973                     goto do_fault_protect;
974             } else {
975                 if ((env->cr[0] & CR0_WP_MASK) &&
976                     is_write && !(ptep & PG_RW_MASK))
977                     goto do_fault_protect;
978             }
979             is_dirty = is_write && !(pte & PG_DIRTY_MASK);
980             if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
981                 pte |= PG_ACCESSED_MASK;
982                 if (is_dirty)
983                     pte |= PG_DIRTY_MASK;
984                 stl_phys_notdirty(pte_addr, pte);
985             }
986             page_size = 4096;
987             virt_addr = addr & ~0xfff;
988             pte = pte & (PHYS_ADDR_MASK | 0xfff);
989         }
990     } else {
991         uint32_t pde;
992
993         /* page directory entry */
994         pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
995             env->a20_mask;
996         pde = ldl_phys(pde_addr);
997         if (!(pde & PG_PRESENT_MASK)) {
998             error_code = 0;
999             goto do_fault;
1000         }
1001         /* if PSE bit is set, then we use a 4MB page */
1002         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1003             page_size = 4096 * 1024;
1004             if (is_user) {
1005                 if (!(pde & PG_USER_MASK))
1006                     goto do_fault_protect;
1007                 if (is_write && !(pde & PG_RW_MASK))
1008                     goto do_fault_protect;
1009             } else {
1010                 if ((env->cr[0] & CR0_WP_MASK) &&
1011                     is_write && !(pde & PG_RW_MASK))
1012                     goto do_fault_protect;
1013             }
1014             is_dirty = is_write && !(pde & PG_DIRTY_MASK);
1015             if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
1016                 pde |= PG_ACCESSED_MASK;
1017                 if (is_dirty)
1018                     pde |= PG_DIRTY_MASK;
1019                 stl_phys_notdirty(pde_addr, pde);
1020             }
1021
1022             pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1023             ptep = pte;
1024             virt_addr = addr & ~(page_size - 1);
1025         } else {
1026             if (!(pde & PG_ACCESSED_MASK)) {
1027                 pde |= PG_ACCESSED_MASK;
1028                 stl_phys_notdirty(pde_addr, pde);
1029             }
1030
1031             /* page directory entry */
1032             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
1033                 env->a20_mask;
1034             pte = ldl_phys(pte_addr);
1035             if (!(pte & PG_PRESENT_MASK)) {
1036                 error_code = 0;
1037                 goto do_fault;
1038             }
1039             /* combine pde and pte user and rw protections */
1040             ptep = pte & pde;
1041             if (is_user) {
1042                 if (!(ptep & PG_USER_MASK))
1043                     goto do_fault_protect;
1044                 if (is_write && !(ptep & PG_RW_MASK))
1045                     goto do_fault_protect;
1046             } else {
1047                 if ((env->cr[0] & CR0_WP_MASK) &&
1048                     is_write && !(ptep & PG_RW_MASK))
1049                     goto do_fault_protect;
1050             }
1051             is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1052             if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1053                 pte |= PG_ACCESSED_MASK;
1054                 if (is_dirty)
1055                     pte |= PG_DIRTY_MASK;
1056                 stl_phys_notdirty(pte_addr, pte);
1057             }
1058             page_size = 4096;
1059             virt_addr = addr & ~0xfff;
1060         }
1061     }
1062     /* the page can be put in the TLB */
1063     prot = PAGE_READ;
1064     if (!(ptep & PG_NX_MASK))
1065         prot |= PAGE_EXEC;
1066     if (pte & PG_DIRTY_MASK) {
1067         /* only set write access if already dirty... otherwise wait
1068            for dirty access */
1069         if (is_user) {
1070             if (ptep & PG_RW_MASK)
1071                 prot |= PAGE_WRITE;
1072         } else {
1073             if (!(env->cr[0] & CR0_WP_MASK) ||
1074                 (ptep & PG_RW_MASK))
1075                 prot |= PAGE_WRITE;
1076         }
1077     }
1078  do_mapping:
1079     pte = pte & env->a20_mask;
1080
1081     /* Even if 4MB pages, we map only one 4KB page in the cache to
1082        avoid filling it too fast */
1083     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1084     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1085     vaddr = virt_addr + page_offset;
1086
1087     ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
1088     return ret;
1089  do_fault_protect:
1090     error_code = PG_ERROR_P_MASK;
1091  do_fault:
1092     error_code |= (is_write << PG_ERROR_W_BIT);
1093     if (is_user)
1094         error_code |= PG_ERROR_U_MASK;
1095     if (is_write1 == 2 &&
1096         (env->efer & MSR_EFER_NXE) &&
1097         (env->cr[4] & CR4_PAE_MASK))
1098         error_code |= PG_ERROR_I_D_MASK;
1099     if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) {
1100         stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr);
1101     } else {
1102         env->cr[2] = addr;
1103     }
1104     env->error_code = error_code;
1105     env->exception_index = EXCP0E_PAGE;
1106     /* the VMM will handle this */
1107     if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE))
1108         return 2;
1109     return 1;
1110 }
1111
1112 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1113 {
1114     target_ulong pde_addr, pte_addr;
1115     uint64_t pte;
1116     target_phys_addr_t paddr;
1117     uint32_t page_offset;
1118     int page_size;
1119
1120     if (env->cr[4] & CR4_PAE_MASK) {
1121         target_ulong pdpe_addr;
1122         uint64_t pde, pdpe;
1123
1124 #ifdef TARGET_X86_64
1125         if (env->hflags & HF_LMA_MASK) {
1126             uint64_t pml4e_addr, pml4e;
1127             int32_t sext;
1128
1129             /* test virtual address sign extension */
1130             sext = (int64_t)addr >> 47;
1131             if (sext != 0 && sext != -1)
1132                 return -1;
1133
1134             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1135                 env->a20_mask;
1136             pml4e = ldq_phys(pml4e_addr);
1137             if (!(pml4e & PG_PRESENT_MASK))
1138                 return -1;
1139
1140             pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1141                 env->a20_mask;
1142             pdpe = ldq_phys(pdpe_addr);
1143             if (!(pdpe & PG_PRESENT_MASK))
1144                 return -1;
1145         } else
1146 #endif
1147         {
1148             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1149                 env->a20_mask;
1150             pdpe = ldq_phys(pdpe_addr);
1151             if (!(pdpe & PG_PRESENT_MASK))
1152                 return -1;
1153         }
1154
1155         pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1156             env->a20_mask;
1157         pde = ldq_phys(pde_addr);
1158         if (!(pde & PG_PRESENT_MASK)) {
1159             return -1;
1160         }
1161         if (pde & PG_PSE_MASK) {
1162             /* 2 MB page */
1163             page_size = 2048 * 1024;
1164             pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1165         } else {
1166             /* 4 KB page */
1167             pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1168                 env->a20_mask;
1169             page_size = 4096;
1170             pte = ldq_phys(pte_addr);
1171         }
1172     } else {
1173         uint32_t pde;
1174
1175         if (!(env->cr[0] & CR0_PG_MASK)) {
1176             pte = addr;
1177             page_size = 4096;
1178         } else {
1179             /* page directory entry */
1180             pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
1181             pde = ldl_phys(pde_addr);
1182             if (!(pde & PG_PRESENT_MASK))
1183                 return -1;
1184             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1185                 pte = pde & ~0x003ff000; /* align to 4MB */
1186                 page_size = 4096 * 1024;
1187             } else {
1188                 /* page directory entry */
1189                 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1190                 pte = ldl_phys(pte_addr);
1191                 if (!(pte & PG_PRESENT_MASK))
1192                     return -1;
1193                 page_size = 4096;
1194             }
1195         }
1196         pte = pte & env->a20_mask;
1197     }
1198
1199     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1200     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1201     return paddr;
1202 }
1203 #endif /* !CONFIG_USER_ONLY */