From dfee1165ea1241de65ba11f5a04644511271a98d Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 14 Mar 2021 19:41:52 -0300 Subject: [PATCH] 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 --- src/cpu/cpu.c | 168 ++++++++++++++++++++++++++++------------ src/cpu/cpu.h | 8 +- src/include/86box/pit.h | 2 +- src/pit.c | 19 +++-- 4 files changed, 137 insertions(+), 60 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 98b885cd7..062ba292a 100644 --- a/src/cpu/cpu.c +++ b/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; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 061f8154c..c97016e82 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -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); diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index 366be2ad6..82a885dc5 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -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, diff --git a/src/pit.c b/src/pit.c index 2e10a7b38..7087a1f6a 100644 --- a/src/pit.c +++ b/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;