diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c
index 4b4037207..f9ca3408d 100644
--- a/src/cpu/386_common.c
+++ b/src/cpu/386_common.c
@@ -128,9 +128,9 @@ uint32_t addr64a_2[8];
static pc_timer_t *cpu_fast_off_timer = NULL;
static double cpu_fast_off_period = 0.0;
-#define AMD_SYSCALL_EIP (msr.star & 0xFFFFFFFF)
-#define AMD_SYSCALL_SB ((msr.star >> 32) & 0xFFFF)
-#define AMD_SYSRET_SB ((msr.star >> 48) & 0xFFFF)
+#define AMD_SYSCALL_EIP (msr.amd_star & 0xFFFFFFFF)
+#define AMD_SYSCALL_SB ((msr.amd_star >> 32) & 0xFFFF)
+#define AMD_SYSRET_SB ((msr.amd_star >> 48) & 0xFFFF)
/* These #define's and enum have been borrowed from Bochs. */
/* SMM feature masks */
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index e05ec0d9c..4398df36c 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -55,27 +55,31 @@
#define CCR3_NMI_EN (1 << 1)
enum {
- CPUID_FPU = (1 << 0),
- CPUID_VME = (1 << 1),
- CPUID_PSE = (1 << 3),
- CPUID_TSC = (1 << 4),
- CPUID_MSR = (1 << 5),
- CPUID_PAE = (1 << 6),
- CPUID_MCE = (1 << 7),
- CPUID_CMPXCHG8B = (1 << 8),
- CPUID_AMDSEP = (1 << 10),
- CPUID_SEP = (1 << 11),
- CPUID_MTRR = (1 << 12),
- CPUID_PGE = (1 << 13),
- CPUID_MCA = (1 << 14),
- CPUID_CMOV = (1 << 15),
- CPUID_MMX = (1 << 23),
- CPUID_FXSR = (1 << 24)
+ CPUID_FPU = (1 << 0), /* On-chip Floating Point Unit */
+ CPUID_VME = (1 << 1), /* Virtual 8086 mode extensions */
+ CPUID_DE = (1 << 2), /* Debugging extensions */
+ CPUID_PSE = (1 << 3), /* Page Size Extension */
+ CPUID_TSC = (1 << 4), /* Time Stamp Counter */
+ CPUID_MSR = (1 << 5), /* Model-specific registers */
+ CPUID_PAE = (1 << 6), /* Physical Address Extension */
+ CPUID_MCE = (1 << 7), /* Machine Check Exception */
+ CPUID_CMPXCHG8B = (1 << 8), /* CMPXCHG8B instruction */
+ CPUID_APIC = (1 << 9), /* On-chip APIC */
+ CPUID_AMDPGE = (1 << 9), /* Global Page Enable (AMD K5 Model 0 only) */
+ CPUID_AMDSEP = (1 << 10), /* SYSCALL and SYSRET instructions (AMD K6 only) */
+ CPUID_SEP = (1 << 11), /* SYSENTER and SYSEXIT instructions (SYSCALL and SYSRET if EAX=80000001h) */
+ CPUID_MTRR = (1 << 12), /* Memory type range registers */
+ CPUID_PGE = (1 << 13), /* Page Global Enable */
+ CPUID_MCA = (1 << 14), /* Machine Check Architecture */
+ CPUID_CMOV = (1 << 15), /* Conditional move instructions */
+ CPUID_PAT = (1 << 16), /* Page Attribute Table */
+ CPUID_MMX = (1 << 23), /* MMX technology */
+ CPUID_FXSR = (1 << 24) /* FXSAVE and FXRSTOR instructions */
};
-/*Addition flags returned by CPUID function 0x80000001*/
-#define CPUID_3DNOW (1UL << 31UL)
-#define CPUID_3DNOWE (1UL << 30UL)
+/* Additional flags returned by CPUID function 0x80000001 */
+#define CPUID_3DNOWE (1UL << 30UL) /* Extended 3DNow! instructions */
+#define CPUID_3DNOW (1UL << 31UL) /* 3DNow! instructions */
/* Make sure this is as low as possible. */
cpu_state_t cpu_state;
@@ -244,8 +248,7 @@ uint32_t cache_index = 0;
uint8_t _cache[2048];
uint64_t cpu_CR4_mask;
-uint64_t tsc = 0;
-uint64_t pmc[2] = { 0, 0 };
+uint64_t tsc = 0;
double cpu_dmulti;
double cpu_busspeed;
@@ -1605,11 +1608,16 @@ cpu_set(void)
cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE);
if (cpu_s->cpu_type <= CPU_K6)
cpu_CR4_mask |= CR4_PCE;
- }
+ else if (cpu_s->cpu_type >= CPU_K6_2C)
+ cpu_CR4_mask |= CR4_PGE;
+ } else
+ cpu_CR4_mask |= CR4_PGE;
#else
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE;
if (cpu_s->cpu_type == CPU_K6)
cpu_CR4_mask |= CR4_PCE;
+ else if (cpu_s->cpu_type >= CPU_K6_2C)
+ cpu_CR4_mask |= CR4_PGE;
#endif
#ifdef USE_DYNAREC
@@ -1906,7 +1914,7 @@ cpu_CPUID(void)
case CPU_i486SX_SLENH:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -1920,7 +1928,7 @@ cpu_CPUID(void)
case CPU_i486DX_SLENH:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -1936,21 +1944,21 @@ cpu_CPUID(void)
case CPU_ENH_Am486DX:
if (!EAX) {
- EAX = 1;
- EBX = 0x68747541;
+ EAX = 0x00000001;
+ EBX = 0x68747541;/* AuthenticAMD */
ECX = 0x444D4163;
EDX = 0x69746E65;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU; /*FPU*/
+ EDX = CPUID_FPU;
} else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_WINCHIP:
if (!EAX) {
- EAX = 1;
+ EAX = 0x00000001;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
@@ -1961,7 +1969,7 @@ cpu_CPUID(void)
EDX = 0x48727561;
}
} else if (EAX == 1) {
- EAX = 0x540;
+ EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID);
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
@@ -1975,7 +1983,7 @@ cpu_CPUID(void)
case CPU_WINCHIP2:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
@@ -1987,7 +1995,7 @@ cpu_CPUID(void)
}
break;
case 1:
- EAX = CPUID;
+ EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID);
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
@@ -2032,13 +2040,15 @@ cpu_CPUID(void)
case CPU_PENTIUM:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
+ if (cpu_s->cpu_type != CPU_P24T)
+ EDX |= CPUID_MCE;
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2047,106 +2057,69 @@ cpu_CPUID(void)
case CPU_K5:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x68747541;
+ EBX = 0x68747541; /* AuthenticAMD */
EDX = 0x69746E65;
ECX = 0x444D4163;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE;
} else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_5K86:
- if (!EAX) {
- EAX = 0x00000001;
- EBX = 0x68747541;
- EDX = 0x69746E65;
- ECX = 0x444D4163;
- } else if (EAX == 1) {
- EAX = CPUID;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
- } else if (EAX == 0x80000000) {
- EAX = 0x80000005;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000001) {
- EAX = CPUID;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
- } else if (EAX == 0x80000002) {
- EAX = 0x2D444D41;
- EBX = 0x7428354B;
- ECX = 0x5020296D;
- EDX = 0x65636F72;
- } else if (EAX == 0x80000003) {
- EAX = 0x726F7373;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000004)
- EAX = EBX = ECX = EDX = 0;
- else if (EAX == 0x80000005) {
- EAX = 0;
- EBX = 0x04800000;
- ECX = 0x08040120;
- EDX = 0x10040120;
- } else
- EAX = EBX = ECX = EDX = 0;
+ switch (EAX) {
+ case 0:
+ EAX = 0x00000001;
+ EBX = 0x68747541; /* AuthenticAMD */
+ EDX = 0x69746E65;
+ ECX = 0x444D4163;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000001:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
+ break;
+ case 0x80000002: /* Processor name string */
+ EAX = 0x2D444D41; /* AMD-K5(tm) Proce */
+ EBX = 0x7428354B;
+ ECX = 0x5020296D;
+ EDX = 0x65636F72;
+ break;
+ case 0x80000003: /* Processor name string */
+ EAX = 0x726F7373; /* ssor */
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000005: /* Cache information */
+ EAX = 0;
+ EBX = 0x04800000; /* TLBs */
+ ECX = 0x08040120; /* L1 data cache */
+ EDX = 0x10040120; /* L1 instruction cache */
+ break;
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
break;
#endif
case CPU_K6:
- if (!EAX) {
- EAX = 0x00000001;
- EBX = 0x68747541;
- EDX = 0x69746E65;
- ECX = 0x444D4163;
- } else if (EAX == 1) {
- EAX = CPUID;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
- } else if (EAX == 0x80000000) {
- EAX = 0x80000005;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000001) {
- EAX = CPUID + 0x100;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX;
- } else if (EAX == 0x80000002) {
- EAX = 0x2D444D41;
- EBX = 0x6D74364B;
- ECX = 0x202F7720;
- EDX = 0x746C756D;
- } else if (EAX == 0x80000003) {
- EAX = 0x64656D69;
- EBX = 0x65206169;
- ECX = 0x6E657478;
- EDX = 0x6E6F6973;
- } else if (EAX == 0x80000004) {
- EAX = 0x73;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000005) {
- EAX = 0;
- EBX = 0x02800140;
- ECX = 0x20020220;
- EDX = 0x20020220;
- } else if (EAX == 0x8FFFFFFF) {
- EAX = 0x4778654E;
- EBX = 0x72656E65;
- ECX = 0x6F697461;
- EDX = 0x444D416E;
- } else
- EAX = EBX = ECX = EDX = 0;
- break;
-
- case CPU_K6_2:
- case CPU_K6_2C:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
EBX = 0x68747541; /* AuthenticAMD */
- ECX = 0x444d4163;
- EDX = 0x69746e65;
+ EDX = 0x69746E65;
+ ECX = 0x444D4163;
break;
case 1:
EAX = CPUID;
@@ -2160,7 +2133,68 @@ cpu_CPUID(void)
case 0x80000001:
EAX = CPUID + 0x100;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX;
+ break;
+ case 0x80000002: /* Processor name string */
+ EAX = 0x2D444D41; /* AMD-K6tm w/ mult */
+ EBX = 0x6D74364B;
+ ECX = 0x202F7720;
+ EDX = 0x746C756D;
+ break;
+ case 0x80000003: /* Processor name string */
+ EAX = 0x64656D69; /* imedia extension */
+ EBX = 0x65206169;
+ ECX = 0x6E657478;
+ EDX = 0x6E6F6973;
+ break;
+ case 0x80000004: /* Processor name string */
+ EAX = 0x73; /* s */
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000005: /* Cache information */
+ EAX = 0;
+ EBX = 0x02800140; /* TLBs */
+ ECX = 0x20020220; /* L1 data cache */
+ EDX = 0x20020220; /* L1 instruction cache */
+ break;
+ case 0x8FFFFFFF: /* Easter egg */
+ EAX = 0x4778654E; /* NexGenerationAMD */
+ EBX = 0x72656E65;
+ ECX = 0x6F697461;
+ EDX = 0x444D416E;
+ break;
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
+
+ case CPU_K6_2:
+ case CPU_K6_2C:
+ switch (EAX) {
+ case 0:
+ EAX = 0x00000001;
+ EBX = 0x68747541; /* AuthenticAMD */
+ ECX = 0x444d4163;
+ EDX = 0x69746e65;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ if (cpu_s->cpu_type == CPU_K6_2C)
+ EDX |= CPUID_PGE;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000001:
+ EAX = CPUID + 0x100;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_3DNOW;
+ if (cpu_s->cpu_type == CPU_K6_2C)
+ EDX |= CPUID_PGE;
break;
case 0x80000002: /* Processor name string */
EAX = 0x2d444d41; /* AMD-K6(tm) 3D pr */
@@ -2174,11 +2208,11 @@ cpu_CPUID(void)
ECX = 0x00000000;
EDX = 0x00000000;
break;
- case 0x80000005: /*Cache information*/
+ case 0x80000005: /* Cache information */
EAX = 0;
- EBX = 0x02800140; /*TLBs*/
- ECX = 0x20020220; /*L1 data cache*/
- EDX = 0x20020220; /*L1 instruction cache*/
+ EBX = 0x02800140; /* TLBs */
+ ECX = 0x20020220; /* L1 data cache */
+ EDX = 0x20020220; /* L1 instruction cache */
break;
default:
EAX = EBX = ECX = EDX = 0;
@@ -2189,7 +2223,7 @@ cpu_CPUID(void)
case CPU_K6_3:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
EBX = 0x68747541; /* AuthenticAMD */
ECX = 0x444d4163;
EDX = 0x69746e65;
@@ -2197,7 +2231,7 @@ cpu_CPUID(void)
case 1:
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000006;
@@ -2206,7 +2240,7 @@ cpu_CPUID(void)
case 0x80000001:
EAX = CPUID + 0x100;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_PGE | CPUID_MMX | CPUID_3DNOW;
break;
case 0x80000002: /* Processor name string */
EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */
@@ -2223,8 +2257,8 @@ cpu_CPUID(void)
case 0x80000005: /* Cache information */
EAX = 0;
EBX = 0x02800140; /* TLBs */
- ECX = 0x20020220; /*L1 data cache*/
- EDX = 0x20020220; /*L1 instruction cache*/
+ ECX = 0x20020220; /* L1 data cache */
+ EDX = 0x20020220; /* L1 instruction cache */
break;
case 0x80000006: /* L2 Cache information */
EAX = EBX = EDX = 0;
@@ -2240,7 +2274,7 @@ cpu_CPUID(void)
case CPU_K6_3P:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
EBX = 0x68747541; /* AuthenticAMD */
ECX = 0x444d4163;
EDX = 0x69746e65;
@@ -2248,7 +2282,7 @@ cpu_CPUID(void)
case 1:
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000007;
@@ -2257,7 +2291,7 @@ cpu_CPUID(void)
case 0x80000001:
EAX = CPUID + 0x100;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW | CPUID_3DNOWE;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_PGE | CPUID_3DNOW | CPUID_3DNOWE;
break;
case 0x80000002: /* Processor name string */
EAX = 0x2d444d41; /* AMD-K6(tm)-III P */
@@ -2297,7 +2331,7 @@ cpu_CPUID(void)
case CPU_PENTIUMMMX:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -2312,7 +2346,7 @@ cpu_CPUID(void)
case CPU_Cx6x86:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
@@ -2326,7 +2360,7 @@ cpu_CPUID(void)
case CPU_Cx6x86L:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
@@ -2340,7 +2374,7 @@ cpu_CPUID(void)
case CPU_CxGX1:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
@@ -2354,7 +2388,7 @@ cpu_CPUID(void)
case CPU_Cx6x86MX:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
@@ -2369,7 +2403,7 @@ cpu_CPUID(void)
case CPU_PENTIUMPRO:
if (!EAX) {
EAX = 0x00000002;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -2377,20 +2411,14 @@ cpu_CPUID(void)
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV;
} else if (EAX == 2) {
- /* if (!strcmp(machine_get_internal_name(), "ap61")) {
- EAX = 0x00000001;
- EDX = 0x00000000;
- } else */ {
- EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
- Instruction TLB: 4 MB pages, fully associative, 2 entries
- Data TLB: 4 KB pages, 4-way set associative, 64 entries */
- EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size
- 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size
- Data TLB: 4 MB pages, 4-way set associative, 8 entries
- 1st-level instruction cache:8 KB, 4-way set associative, 32-byte line size */
- }
-
+ EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
+ Instruction TLB: 4 MB pages, fully associative, 2 entries
+ Data TLB: 4 KB pages, 4-way set associative, 64 entries */
EBX = ECX = 0;
+ EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size
+ 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size
+ Data TLB: 4 MB pages, 4-way set associative, 8 entries
+ 1st-level instruction cache: 8 KB, 4-way set associative, 32-byte line size */
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2398,7 +2426,7 @@ cpu_CPUID(void)
case CPU_PENTIUM2:
if (!EAX) {
EAX = 0x00000002;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -2421,7 +2449,7 @@ cpu_CPUID(void)
case CPU_PENTIUM2D:
if (!EAX) {
EAX = 0x00000002;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -2452,7 +2480,7 @@ cpu_CPUID(void)
case CPU_CYRIX3S:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
@@ -2464,7 +2492,7 @@ cpu_CPUID(void)
}
break;
case 1:
- EAX = CPUID;
+ EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID);
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR;
if (cpu_has_feature(CPU_FEATURE_CX8))
@@ -2510,9 +2538,12 @@ cpu_ven_reset(void)
switch (cpu_s->cpu_type) {
case CPU_WINCHIP:
case CPU_WINCHIP2:
- msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- if (cpu_s->cpu_type == CPU_WINCHIP2)
- msr.fcr |= (1 << 18) | (1 << 20);
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
+ msr.mcr_ctrl = 0xf8000000;
+ if (cpu_s->cpu_type == CPU_WINCHIP2) {
+ msr.fcr |= (1 << 18) | (1 << 20);
+ msr.mcr_ctrl |= (1 << 17);
+ }
break;
case CPU_K6_2P:
@@ -2552,18 +2583,28 @@ cpu_RDMSR(void)
case CPU_IBM486BL:
EAX = EDX = 0;
switch (ECX) {
+ /* Processor Operation Register */
case 0x1000:
EAX = msr.ibm_por & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff);
break;
+ /* Cache Region Control Register */
case 0x1001:
- EAX = msr.ibm_crcr & 0xffffffffff;
+ EAX = msr.ibm_crcr & 0xffffffff;
+ EDX = (msr.ibm_crcr >> 32) & 0x0000ffff;
break;
+ /* Processor Operation Register */
case 0x1002:
if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi)
EAX = msr.ibm_por2 & 0x3f000000;
break;
+
+ /* Processor Control Register */
+ case 0x1004:
+ if (cpu_s->cpu_type > CPU_IBM486SLC)
+ EAX = msr.ibm_pcr & 0x00d6001a;
+ break;
}
break;
@@ -2571,42 +2612,74 @@ cpu_RDMSR(void)
case CPU_WINCHIP2:
EAX = EDX = 0;
switch (ECX) {
+ /* Pentium Processor Parity Reversal Register */
case 0x02:
EAX = msr.tr1;
break;
+ /* Pentium Processor New Feature Control */
case 0x0e:
EAX = msr.tr12;
break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* Performance Monitor - Control and Event Select */
case 0x11:
EAX = msr.cesr;
break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ EAX = msr.pmc[0] & 0xffffffff;
+ EDX = msr.pmc[0] >> 32;
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ EAX = msr.pmc[1] & 0xffffffff;
+ EDX = msr.pmc[1] >> 32;
+ break;
+ /* Feature Control Register */
case 0x107:
EAX = msr.fcr;
break;
+ /* Feature Control Register 2 */
case 0x108:
EAX = msr.fcr2 & 0xffffffff;
EDX = msr.fcr2 >> 32;
break;
+ /* Feature Control Register 4 */
case 0x10a:
EAX = cpu_multi & 3;
break;
+ /* Memory Configuration Register Control */
+ case 0x120:
+ EAX = msr.mcr_ctrl;
+ break;
+ /* Unknown */
+ case 0x131:
+ case 0x142 ... 0x145:
+ case 0x147:
+ case 0x150:
+ case 0x151:
+ break;
}
break;
case CPU_CYRIX3S:
EAX = EDX = 0;
switch (ECX) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* EBL_CR_POWERON - Processor Hard Power-On Configuration */
case 0x2a:
EAX = 0xc4000000;
EDX = 0;
@@ -2633,29 +2706,41 @@ cpu_RDMSR(void)
if (cpu_busspeed >= 84000000)
EAX |= (1 << 19);
break;
+ /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */
+ case 0xc1:
+ EAX = tsc & 0xffffffff;
+ EDX = (tsc >> 32) & 0xff;
+ break;
+ /* PERFCTR1 - Performance Counter Register 1 */
+ case 0xc2:
+ EAX = msr.perfctr[1] & 0xffffffff;
+ EDX = msr.perfctr[1] >> 32;
+ break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
+ case 0x11e:
+ EAX = 0x800000; /* L2 cache disabled */
+ break;
+ /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */
+ case 0x186:
+ EAX = 0x470079;
+ break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
+ case 0x187:
+ EAX = msr.evntsel[1] & 0xffffffff;
+ EDX = msr.evntsel[1] >> 32;
+ break;
+ /* Feature Control Register */
case 0x1107:
EAX = msr.fcr;
break;
+ /* Feature Control Register 2 */
case 0x1108:
EAX = msr.fcr2 & 0xffffffff;
EDX = msr.fcr2 >> 32;
break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1) {
EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff;
EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32;
@@ -2664,29 +2749,27 @@ cpu_RDMSR(void)
EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32;
}
break;
+ /* MTRRfix64K_00000 */
case 0x250:
EAX = msr.mtrr_fix64k_8000 & 0xffffffff;
EDX = msr.mtrr_fix64k_8000 >> 32;
break;
+ /* MTRRfix16K_80000 */
case 0x258:
EAX = msr.mtrr_fix16k_8000 & 0xffffffff;
EDX = msr.mtrr_fix16k_8000 >> 32;
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
EAX = msr.mtrr_fix16k_a000 & 0xffffffff;
EDX = msr.mtrr_fix16k_a000 >> 32;
break;
- case 0x268:
- case 0x269:
- case 0x26a:
- case 0x26b:
- case 0x26c:
- case 0x26d:
- case 0x26e:
- case 0x26f:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff;
EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32;
break;
+ /* MTRRdefType */
case 0x2ff:
EAX = msr.mtrr_deftype & 0xffffffff;
EDX = msr.mtrr_deftype >> 32;
@@ -2704,37 +2787,75 @@ cpu_RDMSR(void)
case CPU_K6_3:
case CPU_K6_2P:
case CPU_K6_3P:
- EAX = EDX = 0;
+ EAX = 0;
+ /* EDX is left unchanged when reading this MSR! */
+ if (ECX != 0x82)
+ EDX = 0;
switch (ECX) {
+ /* Machine Check Address Register */
case 0x00000000:
- case 0x00000001:
+ EAX = msr.mcar & 0xffffffff;
+ EDX = msr.mcar >> 32;
break;
+ /* Machine Check Type Register */
+ case 0x00000001:
+ EAX = msr.mctr & 0xffffffff;
+ EDX = msr.mctr >> 32;
+ break;
+ /* Test Register 12 */
case 0x0000000e:
EAX = msr.tr12;
break;
+ /* Time Stamp Counter */
case 0x00000010:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
- case 0x00000083:
- EAX = msr.ecx83 & 0xffffffff;
- EDX = msr.ecx83 >> 32;
+ /* Array Access Register */
+ case 0x00000082:
+ if (cpu_s->cpu_type > CPU_5K86)
+ goto amd_k_invalid_rdmsr;
+ EAX = msr.amd_aar & 0xffffffff;
+ /* EDX is left unchanged! */
break;
+ /* Hardware Configuration Register */
+ case 0x00000083:
+ EAX = msr.amd_hwcr & 0xffffffff;
+ EDX = msr.amd_hwcr >> 32;
+ break;
+ /* Write Allocate Top-of-Memory and Control Register */
+ case 0x00000085:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_rdmsr;
+ EAX = msr.amd_watmcr & 0xffffffff;
+ EDX = msr.amd_watmcr >> 32;
+ break;
+ /* Write Allocate Programmable Memory Range Register */
+ case 0x00000086:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_rdmsr;
+ EAX = msr.amd_wapmrr & 0xffffffff;
+ EDX = msr.amd_wapmrr >> 32;
+ break;
+ /* Extended Feature Enable Register */
case 0xc0000080:
EAX = msr.amd_efer & 0xffffffff;
EDX = msr.amd_efer >> 32;
break;
+ /* SYSCALL Target Address Register */
case 0xc0000081:
if (cpu_s->cpu_type < CPU_K6_2)
goto amd_k_invalid_rdmsr;
- EAX = msr.star & 0xffffffff;
- EDX = msr.star >> 32;
+ EAX = msr.amd_star & 0xffffffff;
+ EDX = msr.amd_star >> 32;
break;
+ /* Write-Handling Control Register */
case 0xc0000082:
EAX = msr.amd_whcr & 0xffffffff;
EDX = msr.amd_whcr >> 32;
break;
+ /* UC/WC Cacheability Control Register */
case 0xc0000085:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_rdmsr;
@@ -2742,6 +2863,7 @@ cpu_RDMSR(void)
EAX = msr.amd_uwccr & 0xffffffff;
EDX = msr.amd_uwccr >> 32;
break;
+ /* Enhanced Power Management Register */
case 0xc0000086:
if (cpu_s->cpu_type < CPU_K6_2P)
goto amd_k_invalid_rdmsr;
@@ -2749,6 +2871,7 @@ cpu_RDMSR(void)
EAX = msr.amd_epmr & 0xffffffff;
EDX = msr.amd_epmr >> 32;
break;
+ /* Processor State Observability Register */
case 0xc0000087:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_rdmsr;
@@ -2756,6 +2879,7 @@ cpu_RDMSR(void)
EAX = msr.amd_psor & 0xffffffff;
EDX = msr.amd_psor >> 32;
break;
+ /* Page Flush/Invalidate Register */
case 0xc0000088:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_rdmsr;
@@ -2763,6 +2887,7 @@ cpu_RDMSR(void)
EAX = msr.amd_pfir & 0xffffffff;
EDX = msr.amd_pfir >> 32;
break;
+ /* Level-2 Cache Array Access Register */
case 0xc0000089:
if (cpu_s->cpu_type < CPU_K6_3)
goto amd_k_invalid_rdmsr;
@@ -2780,25 +2905,205 @@ amd_k_invalid_rdmsr:
case CPU_P24T:
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
+ EAX = EDX = 0;
+ /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per:
+ Ralf Brown, Pentium Model-Specific Registers and What They Reveal.
+ https://www.cs.cmu.edu/~ralf/papers/highmsr.html
+ But leave the bit 31 intact to be able to handle both low and high
+ MSRs in a single switch block. */
+ switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) {
+ /* Machine Check Exception Address */
+ case 0x00000000:
+ case 0x80000000:
+ EAX = msr.mcar & 0xffffffff;
+ EDX = msr.mcar >> 32;
+ break;
+ /* Machine Check Exception Type */
+ case 0x00000001:
+ case 0x80000001:
+ EAX = msr.mctr & 0xffffffff;
+ EDX = msr.mctr >> 32;
+ msr.mctr &= ~0x1; /* clear the machine check pending bit */
+ break;
+ /* TR1 - Parity Reversal Test Register */
+ case 0x00000002:
+ case 0x80000002:
+ EAX = msr.tr1;
+ break;
+ /* TR2 - Instruction Cache End Bit */
+ case 0x00000004:
+ case 0x80000004:
+ if (cpu_s->cpu_type == CPU_PENTIUMMMX)
+ goto pentium_invalid_rdmsr;
+ EAX = msr.tr2;
+ break;
+ /* TR3 - Cache Test Data */
+ case 0x00000005:
+ case 0x80000005:
+ EAX = msr.tr3;
+ break;
+ /* TR4 - Cache Test Tag */
+ case 0x00000006:
+ case 0x80000006:
+ EAX = msr.tr4;
+ break;
+ /* TR5 - Cache Test Control */
+ case 0x00000007:
+ case 0x80000007:
+ EAX = msr.tr5;
+ break;
+ /* TR6 - TLB Test Command */
+ case 0x00000008:
+ case 0x80000008:
+ EAX = msr.tr6;
+ break;
+ /* TR7 - TLB Test Data */
+ case 0x00000009:
+ case 0x80000009:
+ EAX = msr.tr7;
+ break;
+ /* TR9 - Branch Target Buffer Tag */
+ case 0x0000000b:
+ case 0x8000000b:
+ EAX = msr.tr9;
+ break;
+ /* TR10 - Branch Target Buffer Target */
+ case 0x0000000c:
+ case 0x8000000c:
+ EAX = msr.tr10;
+ break;
+ /* TR11 - Branch Target Buffer Control */
+ case 0x0000000d:
+ case 0x8000000d:
+ EAX = msr.tr11;
+ break;
+ /* TR12 - New Feature Control */
+ case 0x0000000e:
+ case 0x8000000e:
+ EAX = msr.tr12;
+ break;
+ /* Time Stamp Counter */
+ case 0x00000010:
+ case 0x80000010:
+ EAX = tsc & 0xffffffff;
+ EDX = tsc >> 32;
+ break;
+ /* Performance Monitor - Control and Event Select */
+ case 0x00000011:
+ case 0x80000011:
+ EAX = msr.cesr;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x00000012:
+ case 0x80000012:
+ EAX = msr.pmc[0] & 0xffffffff;
+ EDX = msr.pmc[0] >> 32;
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x00000013:
+ case 0x80000013:
+ EAX = msr.pmc[1] & 0xffffffff;
+ EDX = msr.pmc[1] >> 32;
+ break;
+ /* Unknown */
+ case 0x00000014:
+ case 0x80000014:
+ if ((CPUID & 0xfff) <= 0x520)
+ goto pentium_invalid_rdmsr;
+ break;
+ /* Unknown, possibly paging-related; initial value is 0004h,
+ becomes 0008h once paging is enabled */
+ case 0x80000018:
+ EAX = ((cr0 & (1 << 31)) ? 0x00000008 : 0x00000004);
+ break;
+ /* Floating point - last prefetched opcode
+ bits 10-8: low three bits of first byte of FP instruction
+ bits 7-0: second byte of floating-point instruction */
+ case 0x80000019:
+ EAX = 0;
+ break;
+ /* Floating point - last executed non-control opcode */
+ case 0x8000001a:
+ EAX = 0;
+ break;
+ /* Floating point - last non-control exception opcode - part
+ of FSTENV/FSAVE'd environment */
+ case 0x8000001b:
+ EAX = msr.fp_last_xcpt;
+ break;
+ /* Unknown */
+ case 0x8000001c:
+ EAX = 0x00000004;
+ break;
+ /* Probe Mode Control */
+ case 0x8000001d:
+ EAX = msr.probe_ctl;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001e:
+ EAX = msr.ecx8000001e;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001f:
+ EAX = msr.ecx8000001f;
+ break;
+ /* Reserved/Unimplemented */
+ case 0x80000003:
+ case 0x8000000a:
+ case 0x8000000f:
+ case 0x80000015 ... 0x80000017:
+ EAX = (ECX & 0x1f) * 2;
+ break;
+ default:
+pentium_invalid_rdmsr:
+ cpu_log("RDMSR: Invalid MSR: %08X\n", ECX);
+ x86gpf(NULL, 0);
+ break;
+ }
+ cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
+ break;
+
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
case CPU_Cx6x86:
case CPU_Cx6x86L:
case CPU_CxGX1:
case CPU_Cx6x86MX:
- if (cpu_s->cpu_type < CPU_Cx6x86)
-#endif
- EAX = EDX = 0;
switch (ECX) {
- case 0x00:
- case 0x01:
+ /* Test Data */
+ case 0x03:
+ EAX = msr.tr3;
break;
+ /* Test Address */
+ case 0x04:
+ EAX = msr.tr4;
+ break;
+ /* Test Command/Status */
+ case 0x05:
+ EAX = msr.tr5;
+ break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* Performance Monitor - Control and Event Select */
+ case 0x11:
+ EAX = msr.cesr;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ EAX = msr.pmc[0] & 0xffffffff;
+ EDX = msr.pmc[0] >> 32;
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ EAX = msr.pmc[1] & 0xffffffff;
+ EDX = msr.pmc[1] >> 32;
+ break;
}
cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
break;
+#endif
case CPU_PENTIUMPRO:
case CPU_PENTIUM2:
@@ -2807,32 +3112,46 @@ amd_k_invalid_rdmsr:
/* Per RichardG's probing of a real Deschutes using my RDMSR tool,
we have discovered that the top 18 bits are filtered out. */
switch (ECX & 0x00003fff) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* IA32_PLATFORM_ID - Platform ID */
case 0x17:
- if (cpu_s->cpu_type != CPU_PENTIUM2D)
+ if (cpu_s->cpu_type < CPU_PENTIUM2D)
goto i686_invalid_rdmsr;
if (cpu_f->package == CPU_PKG_SLOT2)
- EDX |= 0x80000;
+ EDX |= (1 << 19);
else if (cpu_f->package == CPU_PKG_SOCKET370)
- EDX |= 0x100000;
+ EDX |= (1 << 20);
break;
+ /* Unknown */
+ case 0x18:
+ break;
+ /* IA32_APIC_BASE - APIC Base Address */
case 0x1B:
EAX = msr.apic_base & 0xffffffff;
EDX = msr.apic_base >> 32;
cpu_log("APIC_BASE read : %08X%08X\n", EDX, EAX);
break;
- /* Unknown (undocumented?) MSR used by the Hyper-V BIOS. */
+ /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */
case 0x20:
EAX = msr.ecx20 & 0xffffffff;
EDX = msr.ecx20 >> 32;
break;
+ /* Unknown */
+ case 0x21:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_rdmsr;
+ break;
+ /* EBL_CR_POWERON - Processor Hard Power-On Configuration */
case 0x2a:
EAX = 0xc4000000;
EDX = 0;
@@ -2867,47 +3186,85 @@ amd_k_invalid_rdmsr:
EAX |= (1 << 19);
}
break;
+ /* Unknown */
+ case 0x32:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_rdmsr;
+ break;
+ /* TEST_CTL - Test Control Register */
+ case 0x33:
+ EAX = msr.test_ctl;
+ break;
+ /* Unknown */
+ case 0x34:
+ case 0x3a:
+ case 0x3b:
+ case 0x50 ... 0x54:
+ break;
+ /* BIOS_UPDT_TRIG - BIOS Update Trigger */
case 0x79:
- EAX = msr.ecx79 & 0xffffffff;
- EDX = msr.ecx79 >> 32;
+ EAX = msr.bios_updt & 0xffffffff;
+ EDX = msr.bios_updt >> 32;
break;
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- EAX = msr.ecx8x[ECX - 0x88] & 0xffffffff;
- EDX = msr.ecx8x[ECX - 0x88] >> 32;
+ /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register
+ 8Bh: BIOS_SIGN - BIOS Update Signature */
+ case 0x88 ... 0x8b:
+ EAX = msr.bbl_cr_dx[ECX - 0x88] & 0xffffffff;
+ EDX = msr.bbl_cr_dx[ECX - 0x88] >> 32;
break;
+ /* Unknown */
+ case 0xae:
+ break;
+ /* PERFCTR0 - Performance Counter Register 0 */
case 0xc1:
+ /* PERFCTR1 - Performance Counter Register 1 */
case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- EAX = msr.ia32_pmc[ECX - 0xC1] & 0xffffffff;
- EDX = msr.ia32_pmc[ECX - 0xC1] >> 32;
+ EAX = msr.perfctr[ECX - 0xC1] & 0xffffffff;
+ EDX = msr.perfctr[ECX - 0xC1] >> 32;
break;
+ /* MTRRcap */
case 0xfe:
EAX = msr.mtrr_cap & 0xffffffff;
EDX = msr.mtrr_cap >> 32;
break;
+ /* BBL_CR_ADDR - L2 Cache Address Register */
case 0x116:
- EAX = msr.ecx116 & 0xffffffff;
- EDX = msr.ecx116 >> 32;
+ EAX = msr.bbl_cr_addr & 0xffffffff;
+ EDX = msr.bbl_cr_addr >> 32;
break;
+ /* BBL_CR_DECC - L2 Cache Date ECC Register */
case 0x118:
+ EAX = msr.bbl_cr_decc & 0xffffffff;
+ EDX = msr.bbl_cr_decc >> 32;
+ break;
+ /* BBL_CR_CTL - L2 Cache Control Register */
case 0x119:
+ EAX = msr.bbl_cr_ctl & 0xffffffff;
+ EDX = msr.bbl_cr_ctl >> 32;
+ break;
+ /* BBL_CR_TRIG - L2 Cache Trigger Register */
case 0x11a:
+ EAX = msr.bbl_cr_trig & 0xffffffff;
+ EDX = msr.bbl_cr_trig >> 32;
+ break;
+ /* BBL_CR_BUSY - L2 Cache Busy Register */
case 0x11b:
- EAX = msr.ecx11x[ECX - 0x118] & 0xffffffff;
- EDX = msr.ecx11x[ECX - 0x118] >> 32;
+ EAX = msr.bbl_cr_busy & 0xffffffff;
+ EDX = msr.bbl_cr_busy >> 32;
break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
case 0x11e:
- EAX = msr.ecx11e & 0xffffffff;
- EDX = msr.ecx11e >> 32;
+ EAX = msr.bbl_cr_ctl3 & 0xffffffff;
+ EDX = msr.bbl_cr_ctl3 >> 32;
break;
+ /* Unknown */
+ case 0x131:
+ case 0x14e ... 0x151:
+ case 0x154:
+ case 0x15b:
+ case 0x15f:
+ break;
+ /* SYSENTER_CS - SYSENTER target CS */
case 0x174:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_rdmsr;
@@ -2916,6 +3273,7 @@ amd_k_invalid_rdmsr:
EAX |= msr.sysenter_cs;
EDX = 0x00000000;
break;
+ /* SYSENTER_ESP - SYSENTER target ESP */
case 0x175:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_rdmsr;
@@ -2923,6 +3281,7 @@ amd_k_invalid_rdmsr:
EAX = msr.sysenter_esp;
EDX = 0x00000000;
break;
+ /* SYSENTER_EIP - SYSENTER target EIP */
case 0x176:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_rdmsr;
@@ -2930,48 +3289,49 @@ amd_k_invalid_rdmsr:
EAX = msr.sysenter_eip;
EDX = 0x00000000;
break;
+ /* MCG_CAP - Machine Check Global Capability */
case 0x179:
EAX = 0x00000105;
EDX = 0x00000000;
break;
+ /* MCG_STATUS - Machine Check Global Status */
case 0x17a:
break;
+ /* MCG_CTL - Machine Check Global Control */
case 0x17b:
EAX = msr.mcg_ctl & 0xffffffff;
EDX = msr.mcg_ctl >> 32;
break;
+ /* EVNTSEL0 - Performance Counter Event Select 0 */
case 0x186:
- EAX = msr.ecx186 & 0xffffffff;
- EDX = msr.ecx186 >> 32;
- break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
case 0x187:
- EAX = msr.ecx187 & 0xffffffff;
- EDX = msr.ecx187 >> 32;
+ EAX = msr.evntsel[ECX - 0x186] & 0xffffffff;
+ EDX = msr.evntsel[ECX - 0x186] >> 32;
break;
+ /* Unknown */
+ case 0x1d3:
+ break;
+ /* DEBUGCTLMSR - Debugging Control Register */
case 0x1d9:
- EAX = msr.debug_ctl & 0xffffffff;
- EDX = msr.debug_ctl >> 32;
+ EAX = msr.debug_ctl;
break;
+ /* LASTBRANCHFROMIP - address from which a branch was last taken */
+ case 0x1db:
+ /* LASTBRANCHTOIP - destination address of the last taken branch instruction */
+ case 0x1dc:
+ /* LASTINTFROMIP - address at which an interrupt last occurred */
+ case 0x1dd:
+ /* LASTINTTOIP - address to which the last interrupt caused a branch */
+ case 0x1de:
+ break;
+ /* ROB_CR_BKUPTMPDR6 */
case 0x1e0:
- EAX = msr.ecx1e0 & 0xffffffff;
- EDX = msr.ecx1e0 >> 32;
+ EAX = msr.rob_cr_bkuptmpdr6;
break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1) {
EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff;
EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32;
@@ -2980,60 +3340,88 @@ amd_k_invalid_rdmsr:
EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32;
}
break;
+ /* MTRRfix64K_00000 */
case 0x250:
EAX = msr.mtrr_fix64k_8000 & 0xffffffff;
EDX = msr.mtrr_fix64k_8000 >> 32;
break;
+ /* MTRRfix16K_80000 */
case 0x258:
EAX = msr.mtrr_fix16k_8000 & 0xffffffff;
EDX = msr.mtrr_fix16k_8000 >> 32;
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
EAX = msr.mtrr_fix16k_a000 & 0xffffffff;
EDX = msr.mtrr_fix16k_a000 >> 32;
break;
- case 0x268:
- case 0x269:
- case 0x26a:
- case 0x26b:
- case 0x26c:
- case 0x26d:
- case 0x26e:
- case 0x26f:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff;
EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32;
break;
+ /* Page Attribute Table */
case 0x277:
+ if (cpu_s->cpu_type < CPU_PENTIUM2D)
+ goto i686_invalid_rdmsr;
EAX = msr.pat & 0xffffffff;
EDX = msr.pat >> 32;
break;
+ /* Unknown */
+ case 0x280:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_rdmsr;
+ break;
+ /* MTRRdefType */
case 0x2ff:
EAX = msr.mtrr_deftype & 0xffffffff;
EDX = msr.mtrr_deftype >> 32;
break;
+ /* MC0_CTL - Machine Check 0 Control */
case 0x400:
+ /* MC1_CTL - Machine Check 1 Control */
case 0x404:
+ /* MC2_CTL - Machine Check 2 Control */
case 0x408:
+ /* MC4_CTL - Machine Check 4 Control */
case 0x40c:
+ /* MC3_CTL - Machine Check 3 Control */
case 0x410:
EAX = msr.mca_ctl[(ECX - 0x400) >> 2] & 0xffffffff;
EDX = msr.mca_ctl[(ECX - 0x400) >> 2] >> 32;
break;
+ /* MC0_STATUS - Machine Check 0 Status */
case 0x401:
+ /* MC0_ADDR - Machine Check 0 Address */
case 0x402:
+ /* MC1_STATUS - Machine Check 1 Status */
case 0x405:
+ /* MC1_ADDR - Machine Check 1 Address */
case 0x406:
- case 0x407:
+ /* MC2_STATUS - Machine Check 2 Status */
case 0x409:
+ /* MC2_ADDR - Machine Check 2 Address */
+ case 0x40a:
+ /* MC4_STATUS - Machine Check 4 Status */
case 0x40d:
+ /* MC4_ADDR - Machine Check 4 Address */
case 0x40e:
+ /* MC3_STATUS - Machine Check 3 Status */
case 0x411:
+ /* MC3_ADDR - Machine Check 3 Address */
case 0x412:
break;
+ /* Unknown */
case 0x570:
EAX = msr.ecx570 & 0xffffffff;
EDX = msr.ecx570 >> 32;
break;
+ /* Unknown, possibly debug registers? */
+ case 0x1000 ... 0x1007:
+ /* Unknown, possibly control registers? */
+ case 0x2000:
+ case 0x2002 ... 0x2004:
+ break;
default:
i686_invalid_rdmsr:
cpu_log("RDMSR: Invalid MSR: %08X\n", ECX);
@@ -3055,38 +3443,59 @@ cpu_WRMSR(void)
switch (cpu_s->cpu_type) {
case CPU_IBM386SLC:
- case CPU_IBM486BL:
case CPU_IBM486SLC:
+ case CPU_IBM486BL:
switch (ECX) {
+ /* Processor Operation Register */
case 0x1000:
msr.ibm_por = EAX & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff);
cpu_cache_int_enabled = (EAX & (1 << 7));
break;
+ /* Cache Region Control Register */
case 0x1001:
- msr.ibm_crcr = EAX & 0xffffffffff;
+ msr.ibm_crcr = EAX | ((uint64_t) (EDX & 0x0000ffff) << 32);
break;
+ /* Processor Operation Register */
case 0x1002:
if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi)
msr.ibm_por2 = EAX & 0x3f000000;
break;
+ /* Processor Control Register */
+ case 0x1004:
+ if (cpu_s->cpu_type > CPU_IBM486SLC)
+ msr.ibm_pcr = EAX & 0x00d6001a;
+ break;
}
break;
case CPU_WINCHIP:
case CPU_WINCHIP2:
switch (ECX) {
+ /* Pentium Processor Parity Reversal Register */
case 0x02:
msr.tr1 = EAX & 2;
break;
+ /* Pentium Processor New Feature Control */
case 0x0e:
- msr.tr12 = EAX & 0x228;
+ msr.tr12 = EAX & 0x248;
break;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
+ /* Performance Monitor - Control and Event Select */
case 0x11:
msr.cesr = EAX & 0xff00ff;
break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ msr.pmc[0] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ msr.pmc[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Feature Control Register */
case 0x107:
msr.fcr = EAX;
if (EAX & (1 << 9))
@@ -3106,23 +3515,67 @@ cpu_WRMSR(void)
else
CPUID = cpu_s->cpuid_model;
break;
+ /* Feature Control Register 2 */
case 0x108:
msr.fcr2 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Feature Control Register 3 */
case 0x109:
msr.fcr3 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Memory Configuration Register 0..7 */
+ case 0x110 ... 0x117:
+ temp = ECX - 0x110;
+ if (cpu_s->cpu_type == CPU_WINCHIP2) {
+ if (EAX & 0x1f)
+ msr.mcr_ctrl |= (1 << (temp + 9));
+ else
+ msr.mcr_ctrl &= ~(1 << (temp + 9));
+ }
+ msr.mcr[temp] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Memory Configuration Register Control */
+ case 0x120:
+ msr.mcr_ctrl = EAX & ((cpu_s->cpu_type == CPU_WINCHIP2) ? 0x1df : 0x1f);
+ break;
+ /* Unknown */
+ case 0x131:
+ case 0x142 ... 0x145:
+ case 0x147:
+ case 0x150:
+ case 0x151:
+ break;
}
break;
case CPU_CYRIX3S:
switch (ECX) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
break;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
+ /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */
+ case 0xc1:
+ break;
+ /* PERFCTR0 - Performance Counter Register 1 */
+ case 0xc2:
+ msr.perfctr[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
+ case 0x11e:
+ /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */
+ case 0x186:
+ break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
+ case 0x187:
+ msr.evntsel[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Feature Control Register */
case 0x1107:
msr.fcr = EAX;
if (EAX & (1 << 1))
@@ -3134,52 +3587,39 @@ cpu_WRMSR(void)
else
cpu_CR4_mask &= ~CR4_PGE;
break;
+ /* Feature Control Register 2 */
case 0x1108:
msr.fcr2 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Feature Control Register 3 */
case 0x1109:
msr.fcr3 = EAX | ((uint64_t) EDX << 32);
break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1)
msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
else
msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix64K_00000 */
case 0x250:
msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_80000 */
case 0x258:
msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32);
break;
- case 0x268:
- case 0x269:
- case 0x26A:
- case 0x26B:
- case 0x26C:
- case 0x26D:
- case 0x26E:
- case 0x26F:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRdefType */
case 0x2ff:
msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32);
break;
@@ -3197,18 +3637,47 @@ cpu_WRMSR(void)
case CPU_K6_2P:
case CPU_K6_3P:
switch (ECX) {
- case 0x00:
- case 0x01:
+ /* Machine Check Address Register */
+ case 0x00000000:
+ if (cpu_s->cpu_type > CPU_5K86)
+ msr.mcar = EAX | ((uint64_t) EDX << 32);
break;
- case 0x0e:
- msr.tr12 = EAX & 0x228;
+ /* Machine Check Type Register */
+ case 0x00000001:
+ if (cpu_s->cpu_type > CPU_5K86)
+ msr.mctr = EAX | ((uint64_t) EDX << 32);
break;
- case 0x10:
+ /* Test Register 12 */
+ case 0x0000000e:
+ msr.tr12 = EAX & 0x8;
+ break;
+ /* Time Stamp Counter */
+ case 0x00000010:
tsc = EAX | ((uint64_t) EDX << 32);
break;
- case 0x83:
- msr.ecx83 = EAX | ((uint64_t) EDX << 32);
+ /* Array Access Register */
+ case 0x00000082:
+ if (cpu_s->cpu_type > CPU_5K86)
+ goto amd_k_invalid_wrmsr;
+ msr.amd_aar = EAX | ((uint64_t) EDX << 32);
break;
+ /* Hardware Configuration Register */
+ case 0x00000083:
+ msr.amd_hwcr = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Write Allocate Top-of-Memory and Control Register */
+ case 0x00000085:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_wrmsr;
+ msr.amd_watmcr = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Write Allocate Programmable Memory Range Register */
+ case 0x00000086:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_wrmsr;
+ msr.amd_wapmrr = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Extended Feature Enable Register */
case 0xc0000080:
temp = EAX | ((uint64_t) EDX << 32);
if (temp & ~1ULL)
@@ -3216,39 +3685,46 @@ cpu_WRMSR(void)
else
msr.amd_efer = temp;
break;
+ /* SYSCALL Target Address Register */
case 0xc0000081:
if (cpu_s->cpu_type < CPU_K6_2)
goto amd_k_invalid_wrmsr;
- msr.star = EAX | ((uint64_t) EDX << 32);
+ msr.amd_star = EAX | ((uint64_t) EDX << 32);
break;
+ /* Write-Handling Control Register */
case 0xc0000082:
msr.amd_whcr = EAX | ((uint64_t) EDX << 32);
break;
+ /* UC/WC Cacheability Control Register */
case 0xc0000085:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_wrmsr;
msr.amd_uwccr = EAX | ((uint64_t) EDX << 32);
break;
+ /* Enhanced Power Management Register */
case 0xc0000086:
if (cpu_s->cpu_type < CPU_K6_2P)
goto amd_k_invalid_wrmsr;
msr.amd_epmr = EAX | ((uint64_t) EDX << 32);
break;
+ /* Processor State Observability Register */
case 0xc0000087:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_wrmsr;
msr.amd_psor = EAX | ((uint64_t) EDX << 32);
break;
+ /* Page Flush/Invalidate Register */
case 0xc0000088:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_wrmsr;
msr.amd_pfir = EAX | ((uint64_t) EDX << 32);
break;
+ /* Level-2 Cache Array Access Register */
case 0xc0000089:
if (cpu_s->cpu_type < CPU_K6_3)
goto amd_k_invalid_wrmsr;
@@ -3265,32 +3741,190 @@ amd_k_invalid_wrmsr:
case CPU_P24T:
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
+ cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
+ /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per:
+ Ralf Brown, Pentium Model-Specific Registers and What They Reveal.
+ https://www.cs.cmu.edu/~ralf/papers/highmsr.html
+ But leave the bit 31 intact to be able to handle both low and high
+ MSRs in a single switch block. */
+ switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) {
+ /* Machine Check Exception Address */
+ case 0x00000000:
+ case 0x80000000:
+ /* Machine Check Exception Type */
+ case 0x00000001:
+ case 0x80000001:
+ break;
+ /* TR1 - Parity Reversal Test Register */
+ case 0x00000002:
+ case 0x80000002:
+ msr.tr1 = EAX & 0x3fff;
+ break;
+ /* TR2 - Instruction Cache End Bit */
+ case 0x00000004:
+ case 0x80000004:
+ if (cpu_s->cpu_type == CPU_PENTIUMMMX)
+ goto pentium_invalid_wrmsr;
+ msr.tr2 = EAX & 0xf;
+ break;
+ /* TR3 - Cache Test Data */
+ case 0x00000005:
+ case 0x80000005:
+ msr.tr3 = EAX;
+ break;
+ /* TR4 - Cache Test Tag */
+ case 0x00000006:
+ case 0x80000006:
+ msr.tr4 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffff1f : 0xffffff07);
+ break;
+ /* TR5 - Cache Test Control */
+ case 0x00000007:
+ case 0x80000007:
+ msr.tr5 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0x87fff : 0x7fff);
+ break;
+ /* TR6 - TLB Test Command */
+ case 0x00000008:
+ case 0x80000008:
+ msr.tr6 = EAX & 0xffffff07;
+ break;
+ /* TR7 - TLB Test Data */
+ case 0x00000009:
+ case 0x80000009:
+ msr.tr7 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xfffffc7f : 0xffffff9c);
+ break;
+ /* TR9 - Branch Target Buffer Tag */
+ case 0x0000000b:
+ case 0x8000000b:
+ msr.tr9 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffffff : 0xffffffc3);
+ break;
+ /* TR10 - Branch Target Buffer Target */
+ case 0x0000000c:
+ case 0x8000000c:
+ msr.tr10 = EAX;
+ break;
+ /* TR11 - Branch Target Buffer Control */
+ case 0x0000000d:
+ case 0x8000000d:
+ msr.tr11 = EAX & ((cpu_s->cpu_type >= CPU_PENTIUMMMX) ? 0x3001fcf : 0xfcf);
+ break;
+ /* TR12 - New Feature Control */
+ case 0x0000000e:
+ case 0x8000000e:
+ if (cpu_s->cpu_type == CPU_PENTIUMMMX)
+ temp = EAX & 0x38034f;
+ else if ((CPUID & 0xfff) >= 0x52b)
+ temp = EAX & 0x20435f;
+ else if ((CPUID & 0xfff) >= 0x520)
+ temp = EAX & 0x20035f;
+ else
+ temp = EAX & 0x20030f;
+ msr.tr12 = temp;
+ break;
+ /* Time Stamp Counter */
+ case 0x00000010:
+ case 0x80000010:
+ tsc = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Control and Event Select */
+ case 0x00000011:
+ case 0x80000011:
+ msr.cesr = EAX & 0x3ff03ff;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x00000012:
+ case 0x80000012:
+ msr.pmc[0] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x00000013:
+ case 0x80000013:
+ msr.pmc[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Unknown */
+ case 0x00000014:
+ case 0x80000014:
+ if ((CPUID & 0xfff) <= 0x520)
+ goto pentium_invalid_wrmsr;
+ break;
+ /* Unknown, possibly paging-related; initial value is 0004h,
+ becomes 0008h once paging is enabled */
+ case 0x80000018:
+ /* Floating point - last prefetched opcode
+ bits 10-8: low three bits of first byte of FP instruction
+ bits 7-0: second byte of floating-point instruction */
+ case 0x80000019:
+ /* Floating point - last executed non-control opcode */
+ case 0x8000001a:
+ break;
+ /* Floating point - last non-control exception opcode - part
+ of FSTENV/FSAVE'd environment */
+ case 0x8000001b:
+ EAX = msr.fp_last_xcpt & 0x7ff;
+ break;
+ /* Unknown */
+ case 0x8000001c:
+ break;
+ /* Probe Mode Control */
+ case 0x8000001d:
+ EAX = msr.probe_ctl & 0x7;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001e:
+ msr.ecx8000001e = EAX;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001f:
+ msr.ecx8000001f = EAX;
+ break;
+ /* Reserved/Unimplemented */
+ case 0x80000003:
+ case 0x8000000a:
+ case 0x8000000f:
+ case 0x80000015 ... 0x80000017:
+ break;
+ default:
+pentium_invalid_wrmsr:
+ cpu_log("WRMSR: Invalid MSR: %08X\n", ECX);
+ x86gpf(NULL, 0);
+ break;
+ }
+ break;
+
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
case CPU_Cx6x86:
case CPU_Cx6x86L:
case CPU_CxGX1:
case CPU_Cx6x86MX:
-#endif
cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
switch (ECX) {
- case 0x00:
- case 0x01:
- break;
+ /* Test Data */
+ case 0x03:
+ msr.tr3 = EAX;
+ /* Test Address */
+ case 0x04:
+ msr.tr4 = EAX;
+ /* Test Command/Status */
+ case 0x05:
+ msr.tr5 = EAX & 0x008f0f3b;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
- case 0x8b:
-#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
- if (cpu_s->cpu_type < CPU_Cx6x86) {
-#endif
- cpu_log("WRMSR: Invalid MSR: 0x8B\n");
- x86gpf(NULL, 0); /* Needed for Vista to correctly break on Pentium */
-#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
- }
-#endif
+ /* Performance Monitor - Control and Event Select */
+ case 0x11:
+ msr.cesr = EAX & 0x7ff07ff;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ msr.pmc[0] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ msr.pmc[1] = EAX | ((uint64_t) EDX << 32);
break;
}
break;
+#endif
case CPU_PENTIUMPRO:
case CPU_PENTIUM2:
@@ -3298,168 +3932,240 @@ amd_k_invalid_wrmsr:
/* Per RichardG's probing of a real Deschutes using my RDMSR tool,
we have discovered that the top 18 bits are filtered out. */
switch (ECX & 0x00003fff) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
if (EAX || EDX)
x86gpf(NULL, 0);
break;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x18:
+ break;
+ /* IA32_APIC_BASE - APIC Base Address */
case 0x1b:
cpu_log("APIC_BASE write: %08X%08X\n", EDX, EAX);
#if 0
msr.apic_base = EAX | ((uint64_t) EDX << 32);
#endif
break;
- /* Unknown (undocumented?) MSR used by the Hyper-V BIOS. */
+ /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */
case 0x20:
msr.ecx20 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x21:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_wrmsr;
+ break;
+ /* EBL_CR_POWERON - Processor Hard Power-On Configuration */
case 0x2a:
break;
+ /* Unknown */
+ case 0x32:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_wrmsr;
+ break;
+ /* TEST_CTL - Test Control Register */
+ case 0x33:
+ msr.test_ctl = EAX;
+ break;
+ /* Unknown */
+ case 0x34:
+ case 0x3a:
+ case 0x3b:
+ case 0x50 ... 0x54:
+ break;
+ /* BIOS_UPDT_TRIG - BIOS Update Trigger */
case 0x79:
- msr.ecx79 = EAX | ((uint64_t) EDX << 32);
+ msr.bios_updt = EAX | ((uint64_t) EDX << 32);
break;
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- msr.ecx8x[ECX - 0x88] = EAX | ((uint64_t) EDX << 32);
+ /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register
+ 8Bh: BIOS_SIGN - BIOS Update Signature */
+ case 0x88 ... 0x8b:
+ msr.bbl_cr_dx[ECX - 0x88] = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0xae:
+ break;
+ /* PERFCTR0 - Performance Counter Register 0 */
case 0xc1:
+ /* PERFCTR1 - Performance Counter Register 1 */
case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- msr.ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32);
+ msr.perfctr[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRcap */
case 0xfe:
msr.mtrr_cap = EAX | ((uint64_t) EDX << 32);
break;
+ /* BBL_CR_ADDR - L2 Cache Address Register */
case 0x116:
- msr.ecx116 = EAX | ((uint64_t) EDX << 32);
+ msr.bbl_cr_addr = EAX | ((uint64_t) EDX << 32);
break;
+ /* BBL_CR_DECC - L2 Cache Date ECC Register */
case 0x118:
+ msr.bbl_cr_decc = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_CTL - L2 Cache Control Register */
case 0x119:
+ msr.bbl_cr_ctl = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_TRIG - L2 Cache Trigger Register */
case 0x11a:
+ msr.bbl_cr_trig = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_BUSY - L2 Cache Busy Register */
case 0x11b:
- msr.ecx11x[ECX - 0x118] = EAX | ((uint64_t) EDX << 32);
+ msr.bbl_cr_busy = EAX | ((uint64_t) EDX << 32);
break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
case 0x11e:
- msr.ecx11e = EAX | ((uint64_t) EDX << 32);
+ msr.bbl_cr_ctl3 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x131:
+ case 0x14e ... 0x151:
+ case 0x154:
+ case 0x15b:
+ case 0x15f:
+ break;
+ /* SYSENTER_CS - SYSENTER target CS */
case 0x174:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_wrmsr;
msr.sysenter_cs = EAX & 0xFFFF;
break;
+ /* SYSENTER_ESP - SYSENTER target ESP */
case 0x175:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_wrmsr;
msr.sysenter_esp = EAX;
break;
+ /* SYSENTER_EIP - SYSENTER target EIP */
case 0x176:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_wrmsr;
msr.sysenter_eip = EAX;
break;
+ /* MCG_CAP - Machine Check Global Capability */
case 0x179:
break;
+ /* MCG_STATUS - Machine Check Global Status */
case 0x17a:
if (EAX || EDX)
x86gpf(NULL, 0);
break;
+ /* MCG_CTL - Machine Check Global Control */
case 0x17b:
msr.mcg_ctl = EAX | ((uint64_t) EDX << 32);
break;
+ /* EVNTSEL0 - Performance Counter Event Select 0 */
case 0x186:
- msr.ecx186 = EAX | ((uint64_t) EDX << 32);
- break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
case 0x187:
- msr.ecx187 = EAX | ((uint64_t) EDX << 32);
+ msr.evntsel[ECX - 0x186] = EAX | ((uint64_t) EDX << 32);
break;
+ case 0x1d3:
+ break;
+ /* DEBUGCTLMSR - Debugging Control Register */
case 0x1d9:
- msr.debug_ctl = EAX | ((uint64_t) EDX << 32);
+ msr.debug_ctl = EAX;
break;
+ /* ROB_CR_BKUPTMPDR6 */
case 0x1e0:
- msr.ecx1e0 = EAX | ((uint64_t) EDX << 32);
+ msr.rob_cr_bkuptmpdr6 = EAX;
break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1)
msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
else
msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix64K_00000 */
case 0x250:
msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_80000 */
case 0x258:
msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32);
break;
- case 0x268:
- case 0x269:
- case 0x26a:
- case 0x26b:
- case 0x26c:
- case 0x26d:
- case 0x26e:
- case 0x26f:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32);
break;
+ /* Page Attribute Table */
case 0x277:
+ if (cpu_s->cpu_type < CPU_PENTIUM2D)
+ goto i686_invalid_wrmsr;
msr.pat = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x280:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_wrmsr;
+ break;
+ /* MTRRdefType */
case 0x2ff:
msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32);
break;
+ /* MC0_CTL - Machine Check 0 Control */
case 0x400:
+ /* MC1_CTL - Machine Check 1 Control */
case 0x404:
+ /* MC2_CTL - Machine Check 2 Control */
case 0x408:
+ /* MC4_CTL - Machine Check 4 Control */
case 0x40c:
+ /* MC3_CTL - Machine Check 3 Control */
case 0x410:
msr.mca_ctl[(ECX - 0x400) >> 2] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MC0_STATUS - Machine Check 0 Status */
case 0x401:
+ /* MC0_ADDR - Machine Check 0 Address */
case 0x402:
+ /* MC1_STATUS - Machine Check 1 Status */
case 0x405:
+ /* MC1_ADDR - Machine Check 1 Address */
case 0x406:
- case 0x407:
+ /* MC2_STATUS - Machine Check 2 Status */
case 0x409:
+ /* MC2_ADDR - Machine Check 2 Address */
+ case 0x40a:
+ /* MC4_STATUS - Machine Check 4 Status */
case 0x40d:
+ /* MC4_ADDR - Machine Check 4 Address */
case 0x40e:
+ /* MC3_STATUS - Machine Check 3 Status */
case 0x411:
+ /* MC3_ADDR - Machine Check 3 Address */
case 0x412:
if (EAX || EDX)
x86gpf(NULL, 0);
break;
+ /* Unknown */
case 0x570:
msr.ecx570 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown, possibly debug registers? */
+ case 0x1000 ... 0x1007:
+ /* Unknown, possibly control registers? */
+ case 0x2000:
+ case 0x2002 ... 0x2004:
+ break;
default:
i686_invalid_wrmsr:
cpu_log("WRMSR: Invalid MSR: %08X\n", ECX);
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 8e378ebce..c829a0e17 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -226,101 +226,97 @@ typedef union {
} MMX_REG;
typedef struct {
- /* IDT WinChip and WinChip 2 MSR's */
- uint32_t tr1; /* 0x00000002, 0x0000000e */
- uint32_t tr12; /* 0x00000002, 0x0000000e */
- uint32_t cesr; /* 0x00000011 */
+ /* IBM 386SLC/486SLC/486BL MSRs */
+ uint64_t ibm_por; /* 0x00001000 - 386SLC and later */
+ uint64_t ibm_crcr; /* 0x00001001 - 386SLC and later */
+ uint64_t ibm_por2; /* 0x00001002 - 486SLC and later */
+ uint64_t ibm_pcr; /* 0x00001004 - 486BL3 */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */
+ /* IDT WinChip C6/2/VIA Cyrix III MSRs */
+ uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
+ uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */
+ uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
+ uint64_t mcr[8]; /* 0x00000110 - 0x00000117 (IDT) */
+ uint32_t mcr_ctrl; /* 0x00000120 (IDT) */
- /* Weird long MSR's used by the Hyper-V BIOS. */
- uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits
- like a real Deschutes does. */
+ /* AMD K5/K6 MSRs */
+ uint64_t amd_aar; /* 0x00000082 - all K5 */
+ uint64_t amd_hwcr; /* 0x00000083 - all K5 and all K6 */
+ uint64_t amd_watmcr; /* 0x00000085 - K5 Model 1 and later */
+ uint64_t amd_wapmrr; /* 0x00000086 - K5 Model 1 and later */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t ecx79; /* 0x00000079 */
+ uint64_t amd_efer; /* 0xc0000080 - all K5 and all K6 */
+ uint64_t amd_star; /* 0xc0000081 - K6-2 and later */
+ uint64_t amd_whcr; /* 0xc0000082 - all K5 and all K6 */
+ uint64_t amd_uwccr; /* 0xc0000085 - K6-2C and later */
+ uint64_t amd_epmr; /* 0xc0000086 - K6-III+/2+ only */
+ uint64_t amd_psor; /* 0xc0000087 - K6-2C and later */
+ uint64_t amd_pfir; /* 0xc0000088 - K6-2C and later */
+ uint64_t amd_l2aar; /* 0xc0000089 - K6-III and later */
- /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t ecx83; /* 0x00000083 - AMD K5 and K6 MSR's. */
+ /* Pentium/Pentium MMX MSRs */
+ uint64_t mcar; /* 0x00000000 - also on K5 and (R/W) K6 */
+ uint64_t mctr; /* 0x00000001 - also on K5 and (R/W) K6 */
+ uint32_t tr1; /* 0x00000002 - also on WinChip C6/2 */
+ uint32_t tr2; /* 0x00000004 - reserved on PMMX */
+ uint32_t tr3; /* 0x00000005 */
+ uint32_t tr4; /* 0x00000006 */
+ uint32_t tr5; /* 0x00000007 */
+ uint32_t tr6; /* 0x00000008 */
+ uint32_t tr7; /* 0x00000009 */
+ uint32_t tr9; /* 0x0000000b */
+ uint32_t tr10; /* 0x0000000c */
+ uint32_t tr11; /* 0x0000000d */
+ uint32_t tr12; /* 0x0000000e - also on WinChip C6/2 and K6 */
+ uint32_t cesr; /* 0x00000011 - also on WinChip C6/2 and Cx6x86MX */
+ uint64_t pmc[2]; /* 0x00000012, 0x00000013 - also on WinChip C6/2 and Cx6x86MX */
+ uint32_t fp_last_xcpt; /* 0x8000001b - undocumented */
+ uint32_t probe_ctl; /* 0x8000001d - undocumented */
+ uint32_t ecx8000001e; /* 0x8000001e - undocumented */
+ uint32_t ecx8000001f; /* 0x8000001f - undocumented */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t ecx8x[4]; /* 0x00000088 - 0x0000008b */
- uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */
- uint64_t mtrr_cap; /* 0x000000fe */
+ /* Pentium Pro/II MSRs */
+ uint64_t apic_base; /* 0x0000001b */
+ uint32_t test_ctl; /* 0x00000033 */
+ uint64_t bios_updt; /* 0x00000079 */
- /* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III */
- uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
- uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */
- uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
+ uint64_t bbl_cr_dx[4]; /* 0x00000088 - 0x0000008b */
+ uint64_t perfctr[2]; /* 0x000000c1, 0x000000c2 */
+ uint64_t mtrr_cap; /* 0x000000fe */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t ecx116; /* 0x00000116 */
- uint64_t ecx11x[4]; /* 0x00000118 - 0x0000011b */
- uint64_t ecx11e; /* 0x0000011e */
+ uint64_t bbl_cr_addr; /* 0x00000116 */
+ uint64_t bbl_cr_decc; /* 0x00000118 */
+ uint64_t bbl_cr_ctl; /* 0x00000119 */
+ uint64_t bbl_cr_trig; /* 0x0000011a */
+ uint64_t bbl_cr_busy; /* 0x0000011b */
+ uint64_t bbl_cr_ctl3; /* 0x0000011e */
- /* Pentium II Klamath and Pentium II Deschutes MSR's */
- uint16_t sysenter_cs; /* 0x00000174 - SYSENTER/SYSEXIT MSR's */
- uint32_t sysenter_esp; /* 0x00000175 - SYSENTER/SYSEXIT MSR's */
- uint32_t sysenter_eip; /* 0x00000176 - SYSENTER/SYSEXIT MSR's */
+ uint16_t sysenter_cs; /* 0x00000174 - Pentium II and later */
+ uint32_t sysenter_esp; /* 0x00000175 - Pentium II and later */
+ uint32_t sysenter_eip; /* 0x00000176 - Pentium II and later */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */
- uint64_t ecx186; /* 0x00000186, 0x00000187 */
- uint64_t ecx187; /* 0x00000186, 0x00000187 */
+ uint64_t mcg_ctl; /* 0x0000017b */
+ uint64_t evntsel[2]; /* 0x00000186, 0x00000187 */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */
- uint64_t ecx1e0; /* 0x000001e0 */
+ uint32_t debug_ctl; /* 0x000001d9 */
+ uint32_t rob_cr_bkuptmpdr6; /* 0x000001e0 */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
- on the VIA Cyrix III */
- uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */
+ /* MTTR-related MSRs also present on the VIA Cyrix III */
+ uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f (ECX & 0) */
uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */
uint64_t mtrr_fix64k_8000; /* 0x00000250 */
uint64_t mtrr_fix16k_8000; /* 0x00000258 */
uint64_t mtrr_fix16k_a000; /* 0x00000259 */
uint64_t mtrr_fix4k[8]; /* 0x00000268 - 0x0000026f */
+ uint64_t mtrr_deftype; /* 0x000002ff */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t pat; /* 0x00000277 */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
- on the VIA Cyrix III */
- uint64_t mtrr_deftype; /* 0x000002ff */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */
+ uint64_t pat; /* 0x00000277 - Pentium II Deschutes and later */
+ uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 */
uint64_t ecx570; /* 0x00000570 */
- /* IBM 386SLC, 486SLC, and 486BL MSR's */
- uint64_t ibm_por; /* 0x00001000 - Processor Operation Register */
- uint64_t ibm_crcr; /* 0x00001001 - Cache Region Control Register */
-
- /* IBM 486SLC and 486BL MSR's */
- uint64_t ibm_por2; /* 0x00001002 - Processor Operation Register */
-
- /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_efer; /* 0xc0000080 */
-
- /* AMD K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t star; /* 0xc0000081 */
-
- /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_whcr; /* 0xc0000082 */
-
- /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_uwccr; /* 0xc0000085 */
-
- /* AMD K6-2P and K6-3P MSR's */
- uint64_t amd_epmr; /* 0xc0000086 */
-
- /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_psor; /* 0xc0000087, 0xc0000088 */
- uint64_t amd_pfir; /* 0xc0000087, 0xc0000088 */
-
- /* K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_l2aar; /* 0xc0000089 */
+ /* Other/Unclassified MSRs */
+ uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits
+ like a real Deschutes does. */
} msr_t;
typedef struct {
@@ -586,7 +582,6 @@ extern double bus_timing;
extern double isa_timing;
extern double pci_timing;
extern double agp_timing;
-extern uint64_t pmc[2];
extern uint16_t temp_seg_data[4];
extern uint16_t cs_msr;
extern uint32_t esp_msr;
diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c
index 7a478f6f0..502b2c86e 100644
--- a/src/cpu/cpu_table.c
+++ b/src/cpu/cpu_table.c
@@ -1398,9 +1398,9 @@ const cpu_family_t cpu_families[] = {
.name = "Am5x86",
.internal_name = "am5x86",
.cpus = (const CPU[]) {
- {"P75", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
- {"P75+", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
- {"P90", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
+ {"133 (P75)", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
+ {"150 (P75+)", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
+ {"160 (P90)", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
{"", 0}
}
}, {
@@ -1615,23 +1615,7 @@ const cpu_family_t cpu_families[] = {
{
.package = CPU_PKG_SOCKET5_7,
.manufacturer = "AMD",
- .name = "K5 (5k86)",
- .internal_name = "k5_5k86",
- .cpus = (const CPU[]) {
- {"75 (P75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
- {"90 (P90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
- {"100 (P100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
- {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
- {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
- {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
- {"116.5 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
- {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
- {"", 0}
- }
- }, {
- .package = CPU_PKG_SOCKET5_7,
- .manufacturer = "AMD",
- .name = "K5 (SSA/5)",
+ .name = "K5 (Model 0)",
.internal_name = "k5_ssa5",
.cpus = (const CPU[]) {
{"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
@@ -1639,6 +1623,19 @@ const cpu_family_t cpu_families[] = {
{"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"", 0}
}
+ }, {
+ .package = CPU_PKG_SOCKET5_7,
+ .manufacturer = "AMD",
+ .name = "K5 (Model 1/2/3)",
+ .internal_name = "k5_5k86",
+ .cpus = (const CPU[]) {
+ {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
+ {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
+ {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
+ {"116.7 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
+ {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
+ {"", 0}
+ }
},
#endif
{
@@ -1774,12 +1771,12 @@ const cpu_family_t cpu_families[] = {
.name = "Cx6x86",
.internal_name = "cx6x86",
.cpus = (const CPU[]) {
- {"P90", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
- {"PR120+", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
- {"PR133+", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
- {"PR150+", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
- {"PR166+", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
- {"PR200+", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
+ {"80 (PR90+)", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
+ {"100 (PR120+)", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
+ {"110 (PR133+)", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
+ {"120 (PR150+)", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
+ {"133 (PR166+)", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
+ {"150 (PR200+)", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
{"", 0}
}
}, {
@@ -1788,10 +1785,10 @@ const cpu_family_t cpu_families[] = {
.name = "Cx6x86L",
.internal_name = "cx6x86l",
.cpus = (const CPU[]) {
- {"PR133+", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
- {"PR150+", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
- {"PR166+", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
- {"PR200+", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
+ {"110 (PR133+)", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
+ {"120 (PR150+)", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
+ {"133 (PR166+)", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
+ {"150 (PR200+)", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
{"", 0}
}
}, {
@@ -1800,10 +1797,10 @@ const cpu_family_t cpu_families[] = {
.name = "Cx6x86MX",
.internal_name = "cx6x86mx",
.cpus = (const CPU[]) {
- {"PR166", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
- {"PR200", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
- {"PR233", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
- {"PR266", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
+ {"133 (PR166)", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
+ {"166 (PR200)", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
+ {"187.5 (PR233)", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
+ {"208.3 (PR266)", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"", 0}
}
}, {
@@ -1812,11 +1809,11 @@ const cpu_family_t cpu_families[] = {
.name = "MII",
.internal_name = "mii",
.cpus = (const CPU[]) {
- {"PR300", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
- {"PR333", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
- {"PR366", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
- {"PR400", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
- {"PR433", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
+ {"233 (PR300)", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
+ {"250/83 (PR333)", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
+ {"250/100 (PR366)", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
+ {"285 (PR400)", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
+ {"300 (PR433)", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
{"", 0}
}
},
diff --git a/src/cpu/x886seg_2386.c b/src/cpu/x886seg_2386.c
deleted file mode 100644
index 335c757e4..000000000
--- a/src/cpu/x886seg_2386.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 86Box A hypervisor and IBM PC system emulator that specializes in
- * running old operating systems and software designed for IBM
- * PC systems and compatibles from 1981 through fairly recent
- * system designs based on the PCI bus.
- *
- * This file is part of the 86Box distribution.
- *
- * x86 CPU segment emulation for the 286/386 interpreter.
- *
- *
- *
- * Authors: Sarah Walker,
- * Miran Grca,
- *
- * Copyright 2008-2018 Sarah Walker.
- * Copyright 2016-2018 Miran Grca.
- */
-#ifndef OPS_286_386
-# define OPS_286_386
-#endif
-#include "x86seg.c"