Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ ec6338ba

History | View | Annotate | Download (37.6 kB)

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

    
32
//#define DEBUG_MMU
33

    
34
static struct x86_def_t *x86_cpu_def;
35
typedef struct x86_def_t x86_def_t;
36
static int cpu_x86_register (CPUX86State *env, const x86_def_t *def);
37

    
38
static void add_flagname_to_bitmaps(char *flagname, uint32_t *features, 
39
                                    uint32_t *ext_features, 
40
                                    uint32_t *ext2_features, 
41
                                    uint32_t *ext3_features)
42
{
43
    int i;
44
    /* feature flags taken from "Intel Processor Identification and the CPUID
45
     * Instruction" and AMD's "CPUID Specification". In cases of disagreement 
46
     * about feature names, the Linux name is used. */
47
    const char *feature_name[] = {
48
        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
49
        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
50
        "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
51
        "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
52
    };
53
    const char *ext_feature_name[] = {
54
       "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
55
       "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
56
       NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
57
       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58
    };
59
    const char *ext2_feature_name[] = {
60
       "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
61
       "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mttr", "pge", "mca", "cmov",
62
       "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
63
       "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
64
    };
65
    const char *ext3_feature_name[] = {
66
       "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
67
       "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
68
       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
69
       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
70
    };
71

    
72
    for ( i = 0 ; i < 32 ; i++ ) 
73
        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
74
            *features |= 1 << i;
75
            return;
76
        }
77
    for ( i = 0 ; i < 32 ; i++ ) 
78
        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
79
            *ext_features |= 1 << i;
80
            return;
81
        }
82
    for ( i = 0 ; i < 32 ; i++ ) 
83
        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
84
            *ext2_features |= 1 << i;
85
            return;
86
        }
87
    for ( i = 0 ; i < 32 ; i++ ) 
88
        if (ext3_features[i] && !strcmp (flagname, ext3_feature_name[i])) {
89
            *ext3_features |= 1 << i;
90
            return;
91
        }
92
    fprintf(stderr, "CPU feature %s not found\n", flagname);
93
}
94

    
95
CPUX86State *cpu_x86_init(void)
96
{
97
    CPUX86State *env;
98
    static int inited;
99

    
100
    env = qemu_mallocz(sizeof(CPUX86State));
101
    if (!env)
102
        return NULL;
103
    cpu_exec_init(env);
104

    
105
    /* init various static tables */
106
    if (!inited) {
107
        inited = 1;
108
        optimize_flags_init();
109
    }
110
    cpu_x86_register(env, x86_cpu_def);
111
    cpu_reset(env);
112
#ifdef USE_KQEMU
113
    kqemu_init(env);
114
#endif
115
    return env;
116
}
117

    
118
struct x86_def_t {
119
    const char *name;
120
    uint32_t vendor1, vendor2, vendor3;
121
    int family;
122
    int model;
123
    int stepping;
124
    uint32_t features, ext_features, ext2_features, ext3_features;
125
    uint32_t xlevel;
126
};
127

    
128
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
129
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
130
          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
131
          CPUID_PAE | CPUID_SEP | CPUID_APIC)
132
static x86_def_t x86_defs[] = {
133
#ifdef TARGET_X86_64
134
    {
135
        .name = "qemu64",
136
        .vendor1 = 0x68747541, /* "Auth" */
137
        .vendor2 = 0x69746e65, /* "enti" */
138
        .vendor3 = 0x444d4163, /* "cAMD" */
139
        .family = 6,
140
        .model = 2,
141
        .stepping = 3,
142
        .features = PPRO_FEATURES | 
143
        /* these features are needed for Win64 and aren't fully implemented */
144
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
145
        /* this feature is needed for Solaris and isn't fully implemented */
146
            CPUID_PSE36,
147
        .ext_features = CPUID_EXT_SSE3,
148
        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
149
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
150
        .ext3_features = CPUID_EXT3_SVM,
151
        .xlevel = 0x80000008,
152
    },
153
#endif
154
    {
155
        .name = "qemu32",
156
        .family = 6,
157
        .model = 3,
158
        .stepping = 3,
159
        .features = PPRO_FEATURES,
160
        .ext_features = CPUID_EXT_SSE3,
161
        .xlevel = 0,
162
    },
163
    {
164
        .name = "486",
165
        .family = 4,
166
        .model = 0,
167
        .stepping = 0,
168
        .features = 0x0000000B,
169
        .xlevel = 0,
170
    },
171
    {
172
        .name = "pentium",
173
        .family = 5,
174
        .model = 4,
175
        .stepping = 3,
176
        .features = 0x008001BF,
177
        .xlevel = 0,
178
    },
179
    {
180
        .name = "pentium2",
181
        .family = 6,
182
        .model = 5,
183
        .stepping = 2,
184
        .features = 0x0183F9FF,
185
        .xlevel = 0,
186
    },
187
    {
188
        .name = "pentium3",
189
        .family = 6,
190
        .model = 7,
191
        .stepping = 3,
192
        .features = 0x0383F9FF,
193
        .xlevel = 0,
194
    },
195
};
196

    
197
int x86_find_cpu_by_name(const unsigned char *cpu_model)
198
{
199
    int ret;
200
    unsigned int i;
201

    
202
    char *s = strdup(cpu_model);
203
    char *featurestr, *name = strtok(s, ",");
204
    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
205
    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
206
    int family = -1, model = -1, stepping = -1;
207

    
208
    ret = -1;
209
    x86_cpu_def = NULL;
210
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
211
        if (strcmp(name, x86_defs[i].name) == 0) {
212
            x86_cpu_def = &x86_defs[i];
213
            ret = 0;
214
            break;
215
        }
216
    }
217
    if (!x86_cpu_def)
218
        goto error;
219

    
220
    featurestr = strtok(NULL, ",");
221

    
222
    while (featurestr) {
223
        char *val;
224
        if (featurestr[0] == '+') {
225
            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
226
        } else if (featurestr[0] == '-') {
227
            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
228
        } else if ((val = strchr(featurestr, '='))) {
229
            *val = 0; val++;
230
            if (!strcmp(featurestr, "family")) {
231
                char *err;
232
                family = strtol(val, &err, 10);
233
                if (!*val || *err || family < 0) {
234
                    fprintf(stderr, "bad numerical value %s\n", val);
235
                    x86_cpu_def = 0;
236
                    goto error;
237
                }
238
                x86_cpu_def->family = family;
239
            } else if (!strcmp(featurestr, "model")) {
240
                char *err;
241
                model = strtol(val, &err, 10);
242
                if (!*val || *err || model < 0 || model > 0xf) {
243
                    fprintf(stderr, "bad numerical value %s\n", val);
244
                    x86_cpu_def = 0;
245
                    goto error;
246
                }
247
                x86_cpu_def->model = model;
248
            } else if (!strcmp(featurestr, "stepping")) {
249
                char *err;
250
                stepping = strtol(val, &err, 10);
251
                if (!*val || *err || stepping < 0 || stepping > 0xf) {
252
                    fprintf(stderr, "bad numerical value %s\n", val);
253
                    x86_cpu_def = 0;
254
                    goto error;
255
                }
256
                x86_cpu_def->stepping = stepping;
257
            } else {
258
                fprintf(stderr, "unregnized feature %s\n", featurestr);
259
                x86_cpu_def = 0;
260
                goto error;
261
            }
262
        } else {
263
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
264
            x86_cpu_def = 0;
265
            goto error;
266
        }
267
        featurestr = strtok(NULL, ",");
268
    }
269
    x86_cpu_def->features |= plus_features;
270
    x86_cpu_def->ext_features |= plus_ext_features;
271
    x86_cpu_def->ext2_features |= plus_ext2_features;
272
    x86_cpu_def->ext3_features |= plus_ext3_features;
273
    x86_cpu_def->features &= ~minus_features;
274
    x86_cpu_def->ext_features &= ~minus_ext_features;
275
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
276
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
277

    
278
error:
279
    free(s);
280
    return ret;
281
}
282

    
283
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
284
{
285
    unsigned int i;
286

    
287
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
288
        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
289
}
290

    
291
int cpu_x86_register (CPUX86State *env, const x86_def_t *def)
292
{
293
    if (def->vendor1) {
294
        env->cpuid_vendor1 = def->vendor1;
295
        env->cpuid_vendor2 = def->vendor2;
296
        env->cpuid_vendor3 = def->vendor3;
297
    } else {
298
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
299
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
300
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
301
    }
302
    env->cpuid_level = 2;
303
    env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
304
    env->cpuid_features = def->features;
305
    env->pat = 0x0007040600070406ULL;
306
    env->cpuid_ext_features = def->ext_features;
307
    env->cpuid_ext2_features = def->ext2_features;
308
    env->cpuid_xlevel = def->xlevel;
309
    env->cpuid_ext3_features = def->ext3_features;
310
    {
311
        const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
312
        int c, len, i;
313
        len = strlen(model_id);
314
        for(i = 0; i < 48; i++) {
315
            if (i >= len)
316
                c = '\0';
317
            else
318
                c = model_id[i];
319
            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
320
        }
321
    }
322
    return 0;
323
}
324

    
325
/* NOTE: must be called outside the CPU execute loop */
326
void cpu_reset(CPUX86State *env)
327
{
328
    int i;
329

    
330
    memset(env, 0, offsetof(CPUX86State, breakpoints));
331

    
332
    tlb_flush(env, 1);
333

    
334
    env->old_exception = -1;
335

    
336
    /* init to reset state */
337

    
338
#ifdef CONFIG_SOFTMMU
339
    env->hflags |= HF_SOFTMMU_MASK;
340
#endif
341
    env->hflags |= HF_GIF_MASK;
342

    
343
    cpu_x86_update_cr0(env, 0x60000010);
344
    env->a20_mask = 0xffffffff;
345
    env->smbase = 0x30000;
346

    
347
    env->idt.limit = 0xffff;
348
    env->gdt.limit = 0xffff;
349
    env->ldt.limit = 0xffff;
350
    env->ldt.flags = DESC_P_MASK;
351
    env->tr.limit = 0xffff;
352
    env->tr.flags = DESC_P_MASK;
353

    
354
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
355
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
356
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
357
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
358
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
359
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
360

    
361
    env->eip = 0xfff0;
362
    env->regs[R_EDX] = env->cpuid_version;
363

    
364
    env->eflags = 0x2;
365

    
366
    /* FPU init */
367
    for(i = 0;i < 8; i++)
368
        env->fptags[i] = 1;
369
    env->fpuc = 0x37f;
370

    
371
    env->mxcsr = 0x1f80;
372
}
373

    
374
void cpu_x86_close(CPUX86State *env)
375
{
376
    free(env);
377
}
378

    
379
/***********************************************************/
380
/* x86 debug */
381

    
382
static const char *cc_op_str[] = {
383
    "DYNAMIC",
384
    "EFLAGS",
385

    
386
    "MULB",
387
    "MULW",
388
    "MULL",
389
    "MULQ",
390

    
391
    "ADDB",
392
    "ADDW",
393
    "ADDL",
394
    "ADDQ",
395

    
396
    "ADCB",
397
    "ADCW",
398
    "ADCL",
399
    "ADCQ",
400

    
401
    "SUBB",
402
    "SUBW",
403
    "SUBL",
404
    "SUBQ",
405

    
406
    "SBBB",
407
    "SBBW",
408
    "SBBL",
409
    "SBBQ",
410

    
411
    "LOGICB",
412
    "LOGICW",
413
    "LOGICL",
414
    "LOGICQ",
415

    
416
    "INCB",
417
    "INCW",
418
    "INCL",
419
    "INCQ",
420

    
421
    "DECB",
422
    "DECW",
423
    "DECL",
424
    "DECQ",
425

    
426
    "SHLB",
427
    "SHLW",
428
    "SHLL",
429
    "SHLQ",
430

    
431
    "SARB",
432
    "SARW",
433
    "SARL",
434
    "SARQ",
435
};
436

    
437
void cpu_dump_state(CPUState *env, FILE *f,
438
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
439
                    int flags)
440
{
441
    int eflags, i, nb;
442
    char cc_op_name[32];
443
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
444

    
445
    eflags = env->eflags;
446
#ifdef TARGET_X86_64
447
    if (env->hflags & HF_CS64_MASK) {
448
        cpu_fprintf(f,
449
                    "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
450
                    "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
451
                    "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
452
                    "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
453
                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
454
                    env->regs[R_EAX],
455
                    env->regs[R_EBX],
456
                    env->regs[R_ECX],
457
                    env->regs[R_EDX],
458
                    env->regs[R_ESI],
459
                    env->regs[R_EDI],
460
                    env->regs[R_EBP],
461
                    env->regs[R_ESP],
462
                    env->regs[8],
463
                    env->regs[9],
464
                    env->regs[10],
465
                    env->regs[11],
466
                    env->regs[12],
467
                    env->regs[13],
468
                    env->regs[14],
469
                    env->regs[15],
470
                    env->eip, eflags,
471
                    eflags & DF_MASK ? 'D' : '-',
472
                    eflags & CC_O ? 'O' : '-',
473
                    eflags & CC_S ? 'S' : '-',
474
                    eflags & CC_Z ? 'Z' : '-',
475
                    eflags & CC_A ? 'A' : '-',
476
                    eflags & CC_P ? 'P' : '-',
477
                    eflags & CC_C ? 'C' : '-',
478
                    env->hflags & HF_CPL_MASK,
479
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
480
                    (env->a20_mask >> 20) & 1,
481
                    (env->hflags >> HF_SMM_SHIFT) & 1,
482
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
483
    } else
484
#endif
485
    {
486
        cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
487
                    "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
488
                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
489
                    (uint32_t)env->regs[R_EAX],
490
                    (uint32_t)env->regs[R_EBX],
491
                    (uint32_t)env->regs[R_ECX],
492
                    (uint32_t)env->regs[R_EDX],
493
                    (uint32_t)env->regs[R_ESI],
494
                    (uint32_t)env->regs[R_EDI],
495
                    (uint32_t)env->regs[R_EBP],
496
                    (uint32_t)env->regs[R_ESP],
497
                    (uint32_t)env->eip, eflags,
498
                    eflags & DF_MASK ? 'D' : '-',
499
                    eflags & CC_O ? 'O' : '-',
500
                    eflags & CC_S ? 'S' : '-',
501
                    eflags & CC_Z ? 'Z' : '-',
502
                    eflags & CC_A ? 'A' : '-',
503
                    eflags & CC_P ? 'P' : '-',
504
                    eflags & CC_C ? 'C' : '-',
505
                    env->hflags & HF_CPL_MASK,
506
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
507
                    (env->a20_mask >> 20) & 1,
508
                    (env->hflags >> HF_SMM_SHIFT) & 1,
509
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
510
    }
511

    
512
#ifdef TARGET_X86_64
513
    if (env->hflags & HF_LMA_MASK) {
514
        for(i = 0; i < 6; i++) {
515
            SegmentCache *sc = &env->segs[i];
516
            cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
517
                        seg_name[i],
518
                        sc->selector,
519
                        sc->base,
520
                        sc->limit,
521
                        sc->flags);
522
        }
523
        cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
524
                    env->ldt.selector,
525
                    env->ldt.base,
526
                    env->ldt.limit,
527
                    env->ldt.flags);
528
        cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
529
                    env->tr.selector,
530
                    env->tr.base,
531
                    env->tr.limit,
532
                    env->tr.flags);
533
        cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
534
                    env->gdt.base, env->gdt.limit);
535
        cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
536
                    env->idt.base, env->idt.limit);
537
        cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
538
                    (uint32_t)env->cr[0],
539
                    env->cr[2],
540
                    env->cr[3],
541
                    (uint32_t)env->cr[4]);
542
    } else
543
#endif
544
    {
545
        for(i = 0; i < 6; i++) {
546
            SegmentCache *sc = &env->segs[i];
547
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
548
                        seg_name[i],
549
                        sc->selector,
550
                        (uint32_t)sc->base,
551
                        sc->limit,
552
                        sc->flags);
553
        }
554
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
555
                    env->ldt.selector,
556
                    (uint32_t)env->ldt.base,
557
                    env->ldt.limit,
558
                    env->ldt.flags);
559
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
560
                    env->tr.selector,
561
                    (uint32_t)env->tr.base,
562
                    env->tr.limit,
563
                    env->tr.flags);
564
        cpu_fprintf(f, "GDT=     %08x %08x\n",
565
                    (uint32_t)env->gdt.base, env->gdt.limit);
566
        cpu_fprintf(f, "IDT=     %08x %08x\n",
567
                    (uint32_t)env->idt.base, env->idt.limit);
568
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
569
                    (uint32_t)env->cr[0],
570
                    (uint32_t)env->cr[2],
571
                    (uint32_t)env->cr[3],
572
                    (uint32_t)env->cr[4]);
573
    }
574
    if (flags & X86_DUMP_CCOP) {
575
        if ((unsigned)env->cc_op < CC_OP_NB)
576
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
577
        else
578
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
579
#ifdef TARGET_X86_64
580
        if (env->hflags & HF_CS64_MASK) {
581
            cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
582
                        env->cc_src, env->cc_dst,
583
                        cc_op_name);
584
        } else
585
#endif
586
        {
587
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
588
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
589
                        cc_op_name);
590
        }
591
    }
592
    if (flags & X86_DUMP_FPU) {
593
        int fptag;
594
        fptag = 0;
595
        for(i = 0; i < 8; i++) {
596
            fptag |= ((!env->fptags[i]) << i);
597
        }
598
        cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
599
                    env->fpuc,
600
                    (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
601
                    env->fpstt,
602
                    fptag,
603
                    env->mxcsr);
604
        for(i=0;i<8;i++) {
605
#if defined(USE_X86LDOUBLE)
606
            union {
607
                long double d;
608
                struct {
609
                    uint64_t lower;
610
                    uint16_t upper;
611
                } l;
612
            } tmp;
613
            tmp.d = env->fpregs[i].d;
614
            cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
615
                        i, tmp.l.lower, tmp.l.upper);
616
#else
617
            cpu_fprintf(f, "FPR%d=%016" PRIx64,
618
                        i, env->fpregs[i].mmx.q);
619
#endif
620
            if ((i & 1) == 1)
621
                cpu_fprintf(f, "\n");
622
            else
623
                cpu_fprintf(f, " ");
624
        }
625
        if (env->hflags & HF_CS64_MASK)
626
            nb = 16;
627
        else
628
            nb = 8;
629
        for(i=0;i<nb;i++) {
630
            cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
631
                        i,
632
                        env->xmm_regs[i].XMM_L(3),
633
                        env->xmm_regs[i].XMM_L(2),
634
                        env->xmm_regs[i].XMM_L(1),
635
                        env->xmm_regs[i].XMM_L(0));
636
            if ((i & 1) == 1)
637
                cpu_fprintf(f, "\n");
638
            else
639
                cpu_fprintf(f, " ");
640
        }
641
    }
642
}
643

    
644
/***********************************************************/
645
/* x86 mmu */
646
/* XXX: add PGE support */
647

    
648
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
649
{
650
    a20_state = (a20_state != 0);
651
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
652
#if defined(DEBUG_MMU)
653
        printf("A20 update: a20=%d\n", a20_state);
654
#endif
655
        /* if the cpu is currently executing code, we must unlink it and
656
           all the potentially executing TB */
657
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
658

    
659
        /* when a20 is changed, all the MMU mappings are invalid, so
660
           we must flush everything */
661
        tlb_flush(env, 1);
662
        env->a20_mask = 0xffefffff | (a20_state << 20);
663
    }
664
}
665

    
666
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
667
{
668
    int pe_state;
669

    
670
#if defined(DEBUG_MMU)
671
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
672
#endif
673
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
674
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
675
        tlb_flush(env, 1);
676
    }
677

    
678
#ifdef TARGET_X86_64
679
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
680
        (env->efer & MSR_EFER_LME)) {
681
        /* enter in long mode */
682
        /* XXX: generate an exception */
683
        if (!(env->cr[4] & CR4_PAE_MASK))
684
            return;
685
        env->efer |= MSR_EFER_LMA;
686
        env->hflags |= HF_LMA_MASK;
687
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
688
               (env->efer & MSR_EFER_LMA)) {
689
        /* exit long mode */
690
        env->efer &= ~MSR_EFER_LMA;
691
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
692
        env->eip &= 0xffffffff;
693
    }
694
#endif
695
    env->cr[0] = new_cr0 | CR0_ET_MASK;
696

    
697
    /* update PE flag in hidden flags */
698
    pe_state = (env->cr[0] & CR0_PE_MASK);
699
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
700
    /* ensure that ADDSEG is always set in real mode */
701
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
702
    /* update FPU flags */
703
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
704
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
705
}
706

    
707
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
708
   the PDPT */
709
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
710
{
711
    env->cr[3] = new_cr3;
712
    if (env->cr[0] & CR0_PG_MASK) {
713
#if defined(DEBUG_MMU)
714
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
715
#endif
716
        tlb_flush(env, 0);
717
    }
718
}
719

    
720
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
721
{
722
#if defined(DEBUG_MMU)
723
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
724
#endif
725
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
726
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
727
        tlb_flush(env, 1);
728
    }
729
    /* SSE handling */
730
    if (!(env->cpuid_features & CPUID_SSE))
731
        new_cr4 &= ~CR4_OSFXSR_MASK;
732
    if (new_cr4 & CR4_OSFXSR_MASK)
733
        env->hflags |= HF_OSFXSR_MASK;
734
    else
735
        env->hflags &= ~HF_OSFXSR_MASK;
736

    
737
    env->cr[4] = new_cr4;
738
}
739

    
740
/* XXX: also flush 4MB pages */
741
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
742
{
743
    tlb_flush_page(env, addr);
744
}
745

    
746
#if defined(CONFIG_USER_ONLY)
747

    
748
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
749
                             int is_write, int mmu_idx, int is_softmmu)
750
{
751
    /* user mode only emulation */
752
    is_write &= 1;
753
    env->cr[2] = addr;
754
    env->error_code = (is_write << PG_ERROR_W_BIT);
755
    env->error_code |= PG_ERROR_U_MASK;
756
    env->exception_index = EXCP0E_PAGE;
757
    return 1;
758
}
759

    
760
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
761
{
762
    return addr;
763
}
764

    
765
#else
766

    
767
#define PHYS_ADDR_MASK 0xfffff000
768

    
769
/* return value:
770
   -1 = cannot handle fault
771
   0  = nothing more to do
772
   1  = generate PF fault
773
   2  = soft MMU activation required for this block
774
*/
775
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
776
                             int is_write1, int mmu_idx, int is_softmmu)
777
{
778
    uint64_t ptep, pte;
779
    uint32_t pdpe_addr, pde_addr, pte_addr;
780
    int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
781
    unsigned long paddr, page_offset;
782
    target_ulong vaddr, virt_addr;
783

    
784
    is_user = mmu_idx == MMU_USER_IDX;
785
#if defined(DEBUG_MMU)
786
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
787
           addr, is_write1, is_user, env->eip);
788
#endif
789
    is_write = is_write1 & 1;
790

    
791
    if (!(env->cr[0] & CR0_PG_MASK)) {
792
        pte = addr;
793
        virt_addr = addr & TARGET_PAGE_MASK;
794
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
795
        page_size = 4096;
796
        goto do_mapping;
797
    }
798

    
799
    if (env->cr[4] & CR4_PAE_MASK) {
800
        uint64_t pde, pdpe;
801

    
802
        /* XXX: we only use 32 bit physical addresses */
803
#ifdef TARGET_X86_64
804
        if (env->hflags & HF_LMA_MASK) {
805
            uint32_t pml4e_addr;
806
            uint64_t pml4e;
807
            int32_t sext;
808

    
809
            /* test virtual address sign extension */
810
            sext = (int64_t)addr >> 47;
811
            if (sext != 0 && sext != -1) {
812
                env->error_code = 0;
813
                env->exception_index = EXCP0D_GPF;
814
                return 1;
815
            }
816

    
817
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
818
                env->a20_mask;
819
            pml4e = ldq_phys(pml4e_addr);
820
            if (!(pml4e & PG_PRESENT_MASK)) {
821
                error_code = 0;
822
                goto do_fault;
823
            }
824
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
825
                error_code = PG_ERROR_RSVD_MASK;
826
                goto do_fault;
827
            }
828
            if (!(pml4e & PG_ACCESSED_MASK)) {
829
                pml4e |= PG_ACCESSED_MASK;
830
                stl_phys_notdirty(pml4e_addr, pml4e);
831
            }
832
            ptep = pml4e ^ PG_NX_MASK;
833
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
834
                env->a20_mask;
835
            pdpe = ldq_phys(pdpe_addr);
836
            if (!(pdpe & PG_PRESENT_MASK)) {
837
                error_code = 0;
838
                goto do_fault;
839
            }
840
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
841
                error_code = PG_ERROR_RSVD_MASK;
842
                goto do_fault;
843
            }
844
            ptep &= pdpe ^ PG_NX_MASK;
845
            if (!(pdpe & PG_ACCESSED_MASK)) {
846
                pdpe |= PG_ACCESSED_MASK;
847
                stl_phys_notdirty(pdpe_addr, pdpe);
848
            }
849
        } else
850
#endif
851
        {
852
            /* XXX: load them when cr3 is loaded ? */
853
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
854
                env->a20_mask;
855
            pdpe = ldq_phys(pdpe_addr);
856
            if (!(pdpe & PG_PRESENT_MASK)) {
857
                error_code = 0;
858
                goto do_fault;
859
            }
860
            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
861
        }
862

    
863
        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
864
            env->a20_mask;
865
        pde = ldq_phys(pde_addr);
866
        if (!(pde & PG_PRESENT_MASK)) {
867
            error_code = 0;
868
            goto do_fault;
869
        }
870
        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
871
            error_code = PG_ERROR_RSVD_MASK;
872
            goto do_fault;
873
        }
874
        ptep &= pde ^ PG_NX_MASK;
875
        if (pde & PG_PSE_MASK) {
876
            /* 2 MB page */
877
            page_size = 2048 * 1024;
878
            ptep ^= PG_NX_MASK;
879
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
880
                goto do_fault_protect;
881
            if (is_user) {
882
                if (!(ptep & PG_USER_MASK))
883
                    goto do_fault_protect;
884
                if (is_write && !(ptep & PG_RW_MASK))
885
                    goto do_fault_protect;
886
            } else {
887
                if ((env->cr[0] & CR0_WP_MASK) &&
888
                    is_write && !(ptep & PG_RW_MASK))
889
                    goto do_fault_protect;
890
            }
891
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
892
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
893
                pde |= PG_ACCESSED_MASK;
894
                if (is_dirty)
895
                    pde |= PG_DIRTY_MASK;
896
                stl_phys_notdirty(pde_addr, pde);
897
            }
898
            /* align to page_size */
899
            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
900
            virt_addr = addr & ~(page_size - 1);
901
        } else {
902
            /* 4 KB page */
903
            if (!(pde & PG_ACCESSED_MASK)) {
904
                pde |= PG_ACCESSED_MASK;
905
                stl_phys_notdirty(pde_addr, pde);
906
            }
907
            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
908
                env->a20_mask;
909
            pte = ldq_phys(pte_addr);
910
            if (!(pte & PG_PRESENT_MASK)) {
911
                error_code = 0;
912
                goto do_fault;
913
            }
914
            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
915
                error_code = PG_ERROR_RSVD_MASK;
916
                goto do_fault;
917
            }
918
            /* combine pde and pte nx, user and rw protections */
919
            ptep &= pte ^ PG_NX_MASK;
920
            ptep ^= PG_NX_MASK;
921
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
922
                goto do_fault_protect;
923
            if (is_user) {
924
                if (!(ptep & PG_USER_MASK))
925
                    goto do_fault_protect;
926
                if (is_write && !(ptep & PG_RW_MASK))
927
                    goto do_fault_protect;
928
            } else {
929
                if ((env->cr[0] & CR0_WP_MASK) &&
930
                    is_write && !(ptep & PG_RW_MASK))
931
                    goto do_fault_protect;
932
            }
933
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
934
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
935
                pte |= PG_ACCESSED_MASK;
936
                if (is_dirty)
937
                    pte |= PG_DIRTY_MASK;
938
                stl_phys_notdirty(pte_addr, pte);
939
            }
940
            page_size = 4096;
941
            virt_addr = addr & ~0xfff;
942
            pte = pte & (PHYS_ADDR_MASK | 0xfff);
943
        }
944
    } else {
945
        uint32_t pde;
946

    
947
        /* page directory entry */
948
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
949
            env->a20_mask;
950
        pde = ldl_phys(pde_addr);
951
        if (!(pde & PG_PRESENT_MASK)) {
952
            error_code = 0;
953
            goto do_fault;
954
        }
955
        /* if PSE bit is set, then we use a 4MB page */
956
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
957
            page_size = 4096 * 1024;
958
            if (is_user) {
959
                if (!(pde & PG_USER_MASK))
960
                    goto do_fault_protect;
961
                if (is_write && !(pde & PG_RW_MASK))
962
                    goto do_fault_protect;
963
            } else {
964
                if ((env->cr[0] & CR0_WP_MASK) &&
965
                    is_write && !(pde & PG_RW_MASK))
966
                    goto do_fault_protect;
967
            }
968
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
969
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
970
                pde |= PG_ACCESSED_MASK;
971
                if (is_dirty)
972
                    pde |= PG_DIRTY_MASK;
973
                stl_phys_notdirty(pde_addr, pde);
974
            }
975

    
976
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
977
            ptep = pte;
978
            virt_addr = addr & ~(page_size - 1);
979
        } else {
980
            if (!(pde & PG_ACCESSED_MASK)) {
981
                pde |= PG_ACCESSED_MASK;
982
                stl_phys_notdirty(pde_addr, pde);
983
            }
984

    
985
            /* page directory entry */
986
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
987
                env->a20_mask;
988
            pte = ldl_phys(pte_addr);
989
            if (!(pte & PG_PRESENT_MASK)) {
990
                error_code = 0;
991
                goto do_fault;
992
            }
993
            /* combine pde and pte user and rw protections */
994
            ptep = pte & pde;
995
            if (is_user) {
996
                if (!(ptep & PG_USER_MASK))
997
                    goto do_fault_protect;
998
                if (is_write && !(ptep & PG_RW_MASK))
999
                    goto do_fault_protect;
1000
            } else {
1001
                if ((env->cr[0] & CR0_WP_MASK) &&
1002
                    is_write && !(ptep & PG_RW_MASK))
1003
                    goto do_fault_protect;
1004
            }
1005
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1006
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1007
                pte |= PG_ACCESSED_MASK;
1008
                if (is_dirty)
1009
                    pte |= PG_DIRTY_MASK;
1010
                stl_phys_notdirty(pte_addr, pte);
1011
            }
1012
            page_size = 4096;
1013
            virt_addr = addr & ~0xfff;
1014
        }
1015
    }
1016
    /* the page can be put in the TLB */
1017
    prot = PAGE_READ;
1018
    if (!(ptep & PG_NX_MASK))
1019
        prot |= PAGE_EXEC;
1020
    if (pte & PG_DIRTY_MASK) {
1021
        /* only set write access if already dirty... otherwise wait
1022
           for dirty access */
1023
        if (is_user) {
1024
            if (ptep & PG_RW_MASK)
1025
                prot |= PAGE_WRITE;
1026
        } else {
1027
            if (!(env->cr[0] & CR0_WP_MASK) ||
1028
                (ptep & PG_RW_MASK))
1029
                prot |= PAGE_WRITE;
1030
        }
1031
    }
1032
 do_mapping:
1033
    pte = pte & env->a20_mask;
1034

    
1035
    /* Even if 4MB pages, we map only one 4KB page in the cache to
1036
       avoid filling it too fast */
1037
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1038
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1039
    vaddr = virt_addr + page_offset;
1040

    
1041
    ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
1042
    return ret;
1043
 do_fault_protect:
1044
    error_code = PG_ERROR_P_MASK;
1045
 do_fault:
1046
    error_code |= (is_write << PG_ERROR_W_BIT);
1047
    if (is_user)
1048
        error_code |= PG_ERROR_U_MASK;
1049
    if (is_write1 == 2 &&
1050
        (env->efer & MSR_EFER_NXE) &&
1051
        (env->cr[4] & CR4_PAE_MASK))
1052
        error_code |= PG_ERROR_I_D_MASK;
1053
    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) {
1054
        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr);
1055
    } else {
1056
        env->cr[2] = addr;
1057
    }
1058
    env->error_code = error_code;
1059
    env->exception_index = EXCP0E_PAGE;
1060
    /* the VMM will handle this */
1061
    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE))
1062
        return 2;
1063
    return 1;
1064
}
1065

    
1066
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1067
{
1068
    uint32_t pde_addr, pte_addr;
1069
    uint32_t pde, pte, paddr, page_offset, page_size;
1070

    
1071
    if (env->cr[4] & CR4_PAE_MASK) {
1072
        uint32_t pdpe_addr, pde_addr, pte_addr;
1073
        uint32_t pdpe;
1074

    
1075
        /* XXX: we only use 32 bit physical addresses */
1076
#ifdef TARGET_X86_64
1077
        if (env->hflags & HF_LMA_MASK) {
1078
            uint32_t pml4e_addr, pml4e;
1079
            int32_t sext;
1080

    
1081
            /* test virtual address sign extension */
1082
            sext = (int64_t)addr >> 47;
1083
            if (sext != 0 && sext != -1)
1084
                return -1;
1085

    
1086
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1087
                env->a20_mask;
1088
            pml4e = ldl_phys(pml4e_addr);
1089
            if (!(pml4e & PG_PRESENT_MASK))
1090
                return -1;
1091

    
1092
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1093
                env->a20_mask;
1094
            pdpe = ldl_phys(pdpe_addr);
1095
            if (!(pdpe & PG_PRESENT_MASK))
1096
                return -1;
1097
        } else
1098
#endif
1099
        {
1100
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1101
                env->a20_mask;
1102
            pdpe = ldl_phys(pdpe_addr);
1103
            if (!(pdpe & PG_PRESENT_MASK))
1104
                return -1;
1105
        }
1106

    
1107
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1108
            env->a20_mask;
1109
        pde = ldl_phys(pde_addr);
1110
        if (!(pde & PG_PRESENT_MASK)) {
1111
            return -1;
1112
        }
1113
        if (pde & PG_PSE_MASK) {
1114
            /* 2 MB page */
1115
            page_size = 2048 * 1024;
1116
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1117
        } else {
1118
            /* 4 KB page */
1119
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1120
                env->a20_mask;
1121
            page_size = 4096;
1122
            pte = ldl_phys(pte_addr);
1123
        }
1124
    } else {
1125
        if (!(env->cr[0] & CR0_PG_MASK)) {
1126
            pte = addr;
1127
            page_size = 4096;
1128
        } else {
1129
            /* page directory entry */
1130
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
1131
            pde = ldl_phys(pde_addr);
1132
            if (!(pde & PG_PRESENT_MASK))
1133
                return -1;
1134
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1135
                pte = pde & ~0x003ff000; /* align to 4MB */
1136
                page_size = 4096 * 1024;
1137
            } else {
1138
                /* page directory entry */
1139
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1140
                pte = ldl_phys(pte_addr);
1141
                if (!(pte & PG_PRESENT_MASK))
1142
                    return -1;
1143
                page_size = 4096;
1144
            }
1145
        }
1146
        pte = pte & env->a20_mask;
1147
    }
1148

    
1149
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1150
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1151
    return paddr;
1152
}
1153
#endif /* !CONFIG_USER_ONLY */