Add custom ISA/PCI/AGP clock facility, and fix PIT clock calculation oversight for CPU clocks ending in (but not equal to) 33 and 66 MHz
This commit is contained in:
168
src/cpu/cpu.c
168
src/cpu/cpu.c
@@ -167,7 +167,7 @@ int cpu_prefetch_cycles, cpu_prefetch_width,
|
||||
cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles;
|
||||
int cpu_waitstates;
|
||||
int cpu_cache_int_enabled, cpu_cache_ext_enabled;
|
||||
int cpu_pci_speed, cpu_alt_reset;
|
||||
int cpu_isa_speed, cpu_pci_speed, cpu_isa_pci_div, cpu_agp_speed, cpu_alt_reset;
|
||||
uint16_t cpu_fast_off_count, cpu_fast_off_val;
|
||||
uint32_t cpu_fast_off_flags;
|
||||
int is_vpc;
|
||||
@@ -564,22 +564,16 @@ cpu_set(void)
|
||||
|
||||
cpu_update_waitstates();
|
||||
|
||||
isa_cycles = cpu_s->atclk_div;
|
||||
isa_cycles = cpu_s->atclk_div;
|
||||
|
||||
if (cpu_s->rspeed <= 8000000)
|
||||
cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles;
|
||||
else
|
||||
cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000;
|
||||
|
||||
if (cpu_busspeed < 42500000)
|
||||
cpu_pci_speed = cpu_busspeed;
|
||||
else if ((cpu_busspeed > 42500000) && (cpu_busspeed < 84000000))
|
||||
cpu_pci_speed = cpu_busspeed / 2;
|
||||
else
|
||||
cpu_pci_speed = cpu_busspeed / 3;
|
||||
|
||||
pci_burst_time = cpu_s->rspeed / cpu_pci_speed;
|
||||
pci_nonburst_time = 4 * pci_burst_time;
|
||||
cpu_set_isa_pci_div(0);
|
||||
cpu_set_pci_speed(0);
|
||||
cpu_set_agp_speed(0);
|
||||
|
||||
if (cpu_iscyrix)
|
||||
io_sethandler(0x0022, 0x0002, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL);
|
||||
@@ -710,34 +704,34 @@ cpu_set(void)
|
||||
if (fpu_type == FPU_287)
|
||||
{
|
||||
#ifdef USE_DYNAREC
|
||||
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16;
|
||||
x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32;
|
||||
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16;
|
||||
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32;
|
||||
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16;
|
||||
x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32;
|
||||
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16;
|
||||
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32;
|
||||
x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16;
|
||||
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32;
|
||||
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32;
|
||||
x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16;
|
||||
x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32;
|
||||
x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32;
|
||||
x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16;
|
||||
x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32;
|
||||
x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32;
|
||||
x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16;
|
||||
x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32;
|
||||
x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32;
|
||||
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16;
|
||||
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32;
|
||||
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32;
|
||||
#endif
|
||||
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
|
||||
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
|
||||
x86_opcodes_da_a16 = ops_fpu_287_da_a16;
|
||||
x86_opcodes_da_a32 = ops_fpu_287_da_a32;
|
||||
x86_opcodes_db_a16 = ops_fpu_287_db_a16;
|
||||
x86_opcodes_db_a16 = ops_fpu_287_db_a16;
|
||||
x86_opcodes_db_a32 = ops_fpu_287_db_a32;
|
||||
x86_opcodes_dc_a16 = ops_fpu_287_dc_a16;
|
||||
x86_opcodes_dc_a16 = ops_fpu_287_dc_a16;
|
||||
x86_opcodes_dc_a32 = ops_fpu_287_dc_a32;
|
||||
x86_opcodes_dd_a16 = ops_fpu_287_dd_a16;
|
||||
x86_opcodes_dd_a16 = ops_fpu_287_dd_a16;
|
||||
x86_opcodes_dd_a32 = ops_fpu_287_dd_a32;
|
||||
x86_opcodes_de_a16 = ops_fpu_287_de_a16;
|
||||
x86_opcodes_de_a16 = ops_fpu_287_de_a16;
|
||||
x86_opcodes_de_a32 = ops_fpu_287_de_a32;
|
||||
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
|
||||
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
|
||||
x86_opcodes_df_a32 = ops_fpu_287_df_a32;
|
||||
}
|
||||
timing_rr = 2; /*register dest - register src*/
|
||||
@@ -820,34 +814,34 @@ cpu_set(void)
|
||||
if (fpu_type == FPU_287) /*In case we get Deskpro 386 emulation*/
|
||||
{
|
||||
#ifdef USE_DYNAREC
|
||||
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16;
|
||||
x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32;
|
||||
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16;
|
||||
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32;
|
||||
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16;
|
||||
x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32;
|
||||
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16;
|
||||
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32;
|
||||
x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16;
|
||||
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32;
|
||||
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32;
|
||||
x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16;
|
||||
x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32;
|
||||
x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32;
|
||||
x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16;
|
||||
x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32;
|
||||
x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32;
|
||||
x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16;
|
||||
x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32;
|
||||
x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32;
|
||||
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16;
|
||||
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32;
|
||||
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32;
|
||||
#endif
|
||||
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
|
||||
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
|
||||
x86_opcodes_da_a16 = ops_fpu_287_da_a16;
|
||||
x86_opcodes_da_a32 = ops_fpu_287_da_a32;
|
||||
x86_opcodes_db_a16 = ops_fpu_287_db_a16;
|
||||
x86_opcodes_db_a16 = ops_fpu_287_db_a16;
|
||||
x86_opcodes_db_a32 = ops_fpu_287_db_a32;
|
||||
x86_opcodes_dc_a16 = ops_fpu_287_dc_a16;
|
||||
x86_opcodes_dc_a16 = ops_fpu_287_dc_a16;
|
||||
x86_opcodes_dc_a32 = ops_fpu_287_dc_a32;
|
||||
x86_opcodes_dd_a16 = ops_fpu_287_dd_a16;
|
||||
x86_opcodes_dd_a16 = ops_fpu_287_dd_a16;
|
||||
x86_opcodes_dd_a32 = ops_fpu_287_dd_a32;
|
||||
x86_opcodes_de_a16 = ops_fpu_287_de_a16;
|
||||
x86_opcodes_de_a16 = ops_fpu_287_de_a16;
|
||||
x86_opcodes_de_a32 = ops_fpu_287_de_a32;
|
||||
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
|
||||
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
|
||||
x86_opcodes_df_a32 = ops_fpu_287_df_a32;
|
||||
}
|
||||
timing_rr = 2; /*register dest - register src*/
|
||||
@@ -1416,9 +1410,9 @@ cpu_set(void)
|
||||
cpu_features = CPU_FEATURE_RDTSC;
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
#ifdef USE_DYNAREC
|
||||
codegen_timing_set(&codegen_timing_686);
|
||||
codegen_timing_set(&codegen_timing_686);
|
||||
#endif
|
||||
ccr4 = 0x80;
|
||||
ccr4 = 0x80;
|
||||
break;
|
||||
|
||||
|
||||
@@ -1443,7 +1437,7 @@ cpu_set(void)
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
|
||||
#ifdef USE_DYNAREC
|
||||
codegen_timing_set(&codegen_timing_686);
|
||||
codegen_timing_set(&codegen_timing_686);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -1499,9 +1493,9 @@ cpu_set(void)
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
|
||||
#ifdef USE_DYNAREC
|
||||
codegen_timing_set(&codegen_timing_686);
|
||||
codegen_timing_set(&codegen_timing_686);
|
||||
#endif
|
||||
ccr4 = 0x80;
|
||||
ccr4 = 0x80;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -1692,7 +1686,7 @@ cpu_set(void)
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_PAE | CR4_MCE | CR4_PCE;
|
||||
#ifdef USE_DYNAREC
|
||||
codegen_timing_set(&codegen_timing_p6);
|
||||
codegen_timing_set(&codegen_timing_p6);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -1747,7 +1741,7 @@ cpu_set(void)
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_PAE | CR4_MCE | CR4_PCE;
|
||||
#ifdef USE_DYNAREC
|
||||
codegen_timing_set(&codegen_timing_p6);
|
||||
codegen_timing_set(&codegen_timing_p6);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -1802,7 +1796,7 @@ cpu_set(void)
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PAE | CR4_PCE | CR4_OSFXSR;
|
||||
#ifdef USE_DYNAREC
|
||||
codegen_timing_set(&codegen_timing_p6);
|
||||
codegen_timing_set(&codegen_timing_p6);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -1879,6 +1873,82 @@ cpu_set(void)
|
||||
x87_timings = x87_timings_486;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cpu_set_isa_speed(int speed)
|
||||
{
|
||||
if (speed) {
|
||||
cpu_isa_speed = speed;
|
||||
pc_speed_changed();
|
||||
} else
|
||||
cpu_isa_speed = 8000000;
|
||||
|
||||
cpu_log("cpu_set_isa_speed(%d) = %d\n", speed, cpu_isa_speed);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cpu_set_pci_speed(int speed)
|
||||
{
|
||||
if (speed)
|
||||
cpu_pci_speed = speed;
|
||||
else if (cpu_busspeed < 42500000)
|
||||
cpu_pci_speed = cpu_busspeed;
|
||||
else if (cpu_busspeed < 84000000)
|
||||
cpu_pci_speed = cpu_busspeed / 2;
|
||||
else if (cpu_busspeed < 120000000)
|
||||
cpu_pci_speed = cpu_busspeed / 3;
|
||||
else
|
||||
cpu_pci_speed = cpu_busspeed / 4;
|
||||
|
||||
if (cpu_isa_pci_div)
|
||||
cpu_set_isa_pci_div(cpu_isa_pci_div);
|
||||
else if (speed)
|
||||
pc_speed_changed();
|
||||
|
||||
pci_burst_time = cpu_s->rspeed / cpu_pci_speed;
|
||||
pci_nonburst_time = 4 * pci_burst_time;
|
||||
|
||||
cpu_log("cpu_set_pci_speed(%d) = %d\n", speed, cpu_pci_speed);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cpu_set_isa_pci_div(int div)
|
||||
{
|
||||
cpu_isa_pci_div = div;
|
||||
|
||||
cpu_log("cpu_set_isa_pci_div(%d)\n", cpu_isa_pci_div);
|
||||
|
||||
if (cpu_isa_pci_div)
|
||||
cpu_set_isa_speed(cpu_pci_speed / cpu_isa_pci_div);
|
||||
else
|
||||
cpu_set_isa_speed(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cpu_set_agp_speed(int speed)
|
||||
{
|
||||
if (speed) {
|
||||
cpu_agp_speed = speed;
|
||||
pc_speed_changed();
|
||||
}
|
||||
else if (cpu_busspeed < 84000000)
|
||||
cpu_agp_speed = cpu_busspeed;
|
||||
else if (cpu_busspeed < 120000000)
|
||||
cpu_agp_speed = cpu_busspeed / 1.5;
|
||||
else
|
||||
cpu_agp_speed = cpu_busspeed / 2;
|
||||
|
||||
agp_burst_time = cpu_s->rspeed / cpu_agp_speed;
|
||||
agp_nonburst_time = 4 * agp_burst_time;
|
||||
|
||||
cpu_log("cpu_set_agp_speed(%d) = %d\n", speed, cpu_agp_speed);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
cpu_current_pc(char *bufp)
|
||||
{
|
||||
@@ -3209,12 +3279,12 @@ void cpu_RDMSR()
|
||||
case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F:
|
||||
if (ECX & 1)
|
||||
{
|
||||
EAX = mtrr_physmask_msr[(ECX - 0x200) >> 1] & 0xffffffff;
|
||||
EAX = mtrr_physmask_msr[(ECX - 0x200) >> 1] & 0xffffffff;
|
||||
EDX = mtrr_physmask_msr[(ECX - 0x200) >> 1] >> 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
EAX = mtrr_physbase_msr[(ECX - 0x200) >> 1] & 0xffffffff;
|
||||
EAX = mtrr_physbase_msr[(ECX - 0x200) >> 1] & 0xffffffff;
|
||||
EDX = mtrr_physbase_msr[(ECX - 0x200) >> 1] >> 32;
|
||||
}
|
||||
break;
|
||||
|
@@ -433,7 +433,7 @@ extern uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
|
||||
extern uint32_t pccache;
|
||||
extern uint8_t *pccache2;
|
||||
|
||||
extern double bus_timing, pci_timing;
|
||||
extern double bus_timing, isa_timing, pci_timing, agp_timing;
|
||||
extern uint64_t pmc[2];
|
||||
extern uint16_t temp_seg_data[4];
|
||||
extern uint16_t cs_msr;
|
||||
@@ -477,7 +477,7 @@ extern int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_writ
|
||||
extern int cpu_prefetch_cycles, cpu_prefetch_width, cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles;
|
||||
extern int cpu_waitstates;
|
||||
extern int cpu_cache_int_enabled, cpu_cache_ext_enabled;
|
||||
extern int cpu_pci_speed;
|
||||
extern int cpu_isa_speed, cpu_pci_speed, cpu_agp_speed;
|
||||
|
||||
extern int timing_rr;
|
||||
extern int timing_mr, timing_mrl;
|
||||
@@ -523,6 +523,10 @@ extern char *cpu_current_pc(char *bufp);
|
||||
|
||||
extern void cpu_update_waitstates(void);
|
||||
extern void cpu_set(void);
|
||||
extern void cpu_set_isa_speed(int speed);
|
||||
extern void cpu_set_pci_speed(int speed);
|
||||
extern void cpu_set_isa_pci_div(int div);
|
||||
extern void cpu_set_agp_speed(int speed);
|
||||
|
||||
extern void cpu_CPUID(void);
|
||||
extern void cpu_RDMSR(void);
|
||||
|
@@ -49,7 +49,7 @@ typedef struct PIT {
|
||||
extern pit_t *pit,
|
||||
*pit2;
|
||||
|
||||
extern double SYSCLK, PCICLK;
|
||||
extern double SYSCLK, PCICLK, AGPCLK;
|
||||
|
||||
extern uint64_t PITCONST, ISACONST,
|
||||
CGACONST,
|
||||
|
19
src/pit.c
19
src/pit.c
@@ -44,8 +44,8 @@ pit_t *pit, *pit2;
|
||||
double cpuclock, PITCONSTD,
|
||||
SYSCLK,
|
||||
isa_timing,
|
||||
bus_timing, pci_timing,
|
||||
PCICLK;
|
||||
bus_timing, pci_timing, agp_timing,
|
||||
PCICLK, AGPCLK;
|
||||
|
||||
uint64_t PITCONST, ISACONST,
|
||||
CGACONST,
|
||||
@@ -961,17 +961,18 @@ pit_set_clock(int clock)
|
||||
{
|
||||
/* Set default CPU/crystal clock and xt_cpu_multi. */
|
||||
if (cpu_s->cpu_type >= CPU_286) {
|
||||
if (clock == 66666666)
|
||||
cpuclock = 200000000.0 / 3.0;
|
||||
else if (clock == 33333333)
|
||||
cpuclock = 100000000.0 / 3.0;
|
||||
int remainder = (clock % 100000000);
|
||||
if (remainder == 66666666)
|
||||
cpuclock = (double) (clock - remainder) + (200000000.0 / 3.0);
|
||||
else if (remainder == 33333333)
|
||||
cpuclock = (double) (clock - remainder) + (100000000.0 / 3.0);
|
||||
else
|
||||
cpuclock = (double) clock;
|
||||
|
||||
PITCONSTD = (cpuclock / 1193182.0);
|
||||
PITCONST = (uint64_t) (PITCONSTD * (double)(1ull << 32));
|
||||
CGACONST = (uint64_t) ((cpuclock / (19687503.0/11.0)) * (double)(1ull << 32));
|
||||
ISACONST = (uint64_t) ((cpuclock / 8000000.0) * (double)(1ull << 32));
|
||||
ISACONST = (uint64_t) ((cpuclock / (double)cpu_isa_speed) * (double)(1ull << 32));
|
||||
xt_cpu_multi = 1ULL;
|
||||
} else {
|
||||
cpuclock = 14318184.0;
|
||||
@@ -1039,15 +1040,17 @@ pit_set_clock(int clock)
|
||||
|
||||
TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32));
|
||||
|
||||
isa_timing = (cpuclock / (double)8000000.0);
|
||||
isa_timing = (cpuclock / (double)cpu_isa_speed);
|
||||
if (cpu_64bitbus)
|
||||
bus_timing = (cpuclock / ((double)cpu_busspeed / 2));
|
||||
else
|
||||
bus_timing = (cpuclock / (double)cpu_busspeed);
|
||||
pci_timing = (cpuclock / (double)cpu_pci_speed);
|
||||
agp_timing = (cpuclock / (double)cpu_agp_speed);
|
||||
|
||||
/* PCICLK in us for use with timer_on_auto(). */
|
||||
PCICLK = pci_timing / (cpuclock / 1000000.0);
|
||||
AGPCLK = agp_timing / (cpuclock / 1000000.0);
|
||||
|
||||
if (cpu_busspeed >= 30000000)
|
||||
SYSCLK = bus_timing * 4.0;
|
||||
|
Reference in New Issue
Block a user