From 262b188790ddba8f3a9c957d4e237047d8cfb708 Mon Sep 17 00:00:00 2001 From: TomW Date: Sat, 23 Aug 2014 16:28:16 +0100 Subject: [PATCH] Implemented CR4 register for Winchip. Currently only Time Stamp Disable (TSD) has an effect. Fixed stupid bug in WRMSR - MSRs can now be written with values other than zero. --- src/808x.c | 2 ++ src/cpu.c | 8 +++++++- src/cpu.h | 8 ++++++++ src/ibm.h | 2 +- src/x86_ops_mov_ctrl.h | 26 ++++++++++++++++++++++++++ src/x86_ops_msr.h | 5 +++++ 6 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/808x.c b/src/808x.c index 91e4447..85ea40c 100644 --- a/src/808x.c +++ b/src/808x.c @@ -630,6 +630,7 @@ void resetx86() pc=0; msw=0; cr0=0; + cr4 = 0; eflags=0; cgate32=0; loadcs(0xFFFF); @@ -660,6 +661,7 @@ void softresetx86() pc=0; msw=0; cr0=0; + cr4 = 0; eflags=0; cgate32=0; loadcs(0xFFFF); diff --git a/src/cpu.c b/src/cpu.c index c607a97..e0ce645 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -20,6 +20,10 @@ int cpu_16bitbus; int cpu_busspeed; int cpu_hasrdtsc; int cpu_hasMMX, cpu_hasMSR; +int cpu_hasCR4; + +uint64_t cpu_CR4_mask; + uint64_t tsc = 0; int timing_rr; @@ -267,6 +271,7 @@ void cpu_set() cpu_hasrdtsc = 0; cpu_hasMMX = 0; cpu_hasMSR = 0; + cpu_hasCR4 = 0; if (cpu_iscyrix) io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); @@ -413,6 +418,8 @@ void cpu_set() cpu_hasrdtsc = 1; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_hasMMX = cpu_hasMSR = 1; + cpu_hasCR4 = 1; + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; break; default: @@ -549,7 +556,6 @@ void cpu_WRMSR() switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type) { case CPU_WINCHIP: - EAX = EDX = 0; switch (ECX) { case 0x02: diff --git a/src/cpu.h b/src/cpu.h index 564691b..c3a770a 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -74,6 +74,14 @@ extern int cpu_multi; extern int cpu_hasrdtsc; extern int cpu_hasMSR; extern int cpu_hasMMX; +extern int cpu_hasCR4; + +#define CR4_TSD (1 << 2) +#define CR4_DE (1 << 3) +#define CR4_MCE (1 << 6) +#define CR4_PCE (1 << 8) + +extern uint64_t cpu_CR4_mask; extern uint64_t tsc; diff --git a/src/ibm.h b/src/ibm.h index d282f59..a44250f 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -154,7 +154,7 @@ union #define cr0 CR0.l #define msw CR0.w -uint32_t cr2,cr3; +uint32_t cr2, cr3, cr4; #define C_FLAG 0x0001 #define P_FLAG 0x0004 diff --git a/src/x86_ops_mov_ctrl.h b/src/x86_ops_mov_ctrl.h index e95dc5e..a32f0f8 100644 --- a/src/x86_ops_mov_ctrl.h +++ b/src/x86_ops_mov_ctrl.h @@ -19,6 +19,12 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) case 3: regs[rm].l = cr3; break; + case 4: + if (cpu_hasCR4) + { + regs[rm].l = cr4; + break; + } default: pclog("Bad read of CR%i %i\n",rmdat&7,reg); pc = oldpc; @@ -49,6 +55,12 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat) case 3: regs[rm].l = cr3; break; + case 4: + if (cpu_hasCR4) + { + regs[rm].l = cr4; + break; + } default: pclog("Bad read of CR%i %i\n",rmdat&7,reg); pc = oldpc; @@ -110,6 +122,13 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) cr3 = regs[rm].l; flushmmucache(); break; + case 4: + if (cpu_hasCR4) + { + cr4 = regs[rm].l & cpu_CR4_mask; + break; + } + default: pclog("Bad load CR%i\n", reg); pc = oldpc; @@ -143,6 +162,13 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) cr3 = regs[rm].l; flushmmucache(); break; + case 4: + if (cpu_hasCR4) + { + cr4 = regs[rm].l & cpu_CR4_mask; + break; + } + default: pclog("Bad load CR%i\n", reg); pc = oldpc; diff --git a/src/x86_ops_msr.h b/src/x86_ops_msr.h index 4ca1503..743af64 100644 --- a/src/x86_ops_msr.h +++ b/src/x86_ops_msr.h @@ -6,6 +6,11 @@ static int opRDTSC(uint32_t fetchdat) x86illegal(); return 0; } + if ((cr4 & CR4_TSD) && CPL) + { + x86gpf("RDTSC when TSD set and CPL != 0", 0); + return 0; + } EAX = tsc & 0xffffffff; EDX = tsc >> 32; cycles--;