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:
RichardG867
2021-03-14 19:41:52 -03:00
parent 84c40909c7
commit dfee1165ea
4 changed files with 137 additions and 60 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;