diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index aa7374186..e89b52e62 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -76,6 +76,7 @@ enum { CPUID_MCA = (1 << 14), /* Machine Check Architecture */ CPUID_CMOV = (1 << 15), /* Conditional move instructions */ CPUID_PAT = (1 << 16), /* Page Attribute Table */ + CPUID_PSE36 = (1 << 17), /* 36-bit Page Size Extension */ CPUID_MMX = (1 << 23), /* MMX technology */ CPUID_FXSR = (1 << 24) /* FXSAVE and FXRSTOR instructions */ }; @@ -1743,8 +1744,10 @@ cpu_set(void) if (cpu_s->cpu_type >= CPU_PENTIUM2) cpu_features |= CPU_FEATURE_MMX; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PAE | CR4_PCE | CR4_PGE; - if (cpu_s->cpu_type == CPU_PENTIUM2D) + if (cpu_s->cpu_type == CPU_PENTIUM2D) { cpu_CR4_mask |= CR4_OSFXSR; + cpu_features |= CPU_FEATURE_PSE36; + } #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_p6); @@ -2489,7 +2492,7 @@ cpu_CPUID(void) } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; + EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV | CPUID_PSE36; } else if (EAX == 2) { EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries Instruction TLB: 4 MB pages, fully associative, 2 entries diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index d96d7951d..d1bc71ebc 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -530,6 +530,7 @@ extern int hasfpu; #define CPU_FEATURE_3DNOW (1 << 6) #define CPU_FEATURE_SYSCALL (1 << 7) #define CPU_FEATURE_3DNOWE (1 << 8) +#define CPU_FEATURE_PSE36 (1 << 9) extern uint32_t cpu_features; diff --git a/src/mem/mem.c b/src/mem/mem.c index b9a7fb764..c29616ed1 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -320,6 +320,7 @@ mmutranslatereal_normal(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ + uint64_t ret = temp & ~0x3fffff; if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; @@ -336,7 +337,10 @@ mmutranslatereal_normal(uint32_t addr, int rw) mmu_perm = temp & 4; rammap(addr2) |= (rw ? 0x60 : 0x20); - return (temp & ~0x3fffff) + (addr & 0x3fffff); + if (cpu_features & CPU_FEATURE_PSE36) + ret |= (uint64_t) (temp & 0x1e000) << 32; + + return ret + (addr & 0x3fffff); } temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); @@ -488,10 +492,14 @@ mmutranslate_noabrt_normal(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ + uint64_t ret = temp & ~0x3fffff; if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; - return (temp & ~0x3fffff) + (addr & 0x3fffff); + if (cpu_features & CPU_FEATURE_PSE36) + ret |= (uint64_t) (temp & 0x1e000) << 32; + + return ret + (addr & 0x3fffff); } temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc));