pcem/src/cpu.c
SarahW 114cdd7a15 Add VIA Cyrix III CPUs. Note that this is currently limited to 500 MHz,
as Windows 98 won't boot on anything any faster than this. This is most
likely a limitation of the current timer subsystem.
2020-11-14 19:33:53 +00:00

2149 lines
87 KiB
C

#include "ibm.h"
#include "cpu.h"
#include "model.h"
#include "io.h"
#include "x86_ops.h"
#include "mem.h"
#include "pci.h"
#include "codegen.h"
#include "x87_timings.h"
int fpu_type;
uint32_t cpu_features;
static int cpu_turbo_speed, cpu_nonturbo_speed;
static int cpu_turbo = 1;
int isa_cycles;
int has_vlb;
static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6;
OpFn *x86_dynarec_opcodes;
OpFn *x86_dynarec_opcodes_0f;
OpFn *x86_dynarec_opcodes_d8_a16;
OpFn *x86_dynarec_opcodes_d8_a32;
OpFn *x86_dynarec_opcodes_d9_a16;
OpFn *x86_dynarec_opcodes_d9_a32;
OpFn *x86_dynarec_opcodes_da_a16;
OpFn *x86_dynarec_opcodes_da_a32;
OpFn *x86_dynarec_opcodes_db_a16;
OpFn *x86_dynarec_opcodes_db_a32;
OpFn *x86_dynarec_opcodes_dc_a16;
OpFn *x86_dynarec_opcodes_dc_a32;
OpFn *x86_dynarec_opcodes_dd_a16;
OpFn *x86_dynarec_opcodes_dd_a32;
OpFn *x86_dynarec_opcodes_de_a16;
OpFn *x86_dynarec_opcodes_de_a32;
OpFn *x86_dynarec_opcodes_df_a16;
OpFn *x86_dynarec_opcodes_df_a32;
OpFn *x86_dynarec_opcodes_REPE;
OpFn *x86_dynarec_opcodes_REPNE;
OpFn *x86_dynarec_opcodes_3DNOW;
OpFn *x86_opcodes;
OpFn *x86_opcodes_0f;
OpFn *x86_opcodes_d8_a16;
OpFn *x86_opcodes_d8_a32;
OpFn *x86_opcodes_d9_a16;
OpFn *x86_opcodes_d9_a32;
OpFn *x86_opcodes_da_a16;
OpFn *x86_opcodes_da_a32;
OpFn *x86_opcodes_db_a16;
OpFn *x86_opcodes_db_a32;
OpFn *x86_opcodes_dc_a16;
OpFn *x86_opcodes_dc_a32;
OpFn *x86_opcodes_dd_a16;
OpFn *x86_opcodes_dd_a32;
OpFn *x86_opcodes_de_a16;
OpFn *x86_opcodes_de_a32;
OpFn *x86_opcodes_df_a16;
OpFn *x86_opcodes_df_a32;
OpFn *x86_opcodes_REPE;
OpFn *x86_opcodes_REPNE;
OpFn *x86_opcodes_3DNOW;
enum
{
CPUID_FPU = (1 << 0),
CPUID_VME = (1 << 1),
CPUID_PSE = (1 << 3),
CPUID_TSC = (1 << 4),
CPUID_MSR = (1 << 5),
CPUID_CMPXCHG8B = (1 << 8),
CPUID_SEP = (1 << 11),
CPUID_CMOV = (1 << 15),
CPUID_MMX = (1 << 23)
};
/*Addition flags returned by CPUID function 0x80000001*/
enum
{
CPUID_3DNOW = (1 << 31)
};
int cpu = 3, cpu_manufacturer = 0;
CPU *cpu_s;
int cpu_multi;
int cpu_iscyrix;
int cpu_16bitbus;
int cpu_busspeed;
int cpu_use_dynarec;
int cpu_cyrix_alignment;
uint64_t cpu_CR4_mask;
int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l;
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 is386;
int is486;
int CPUID;
uint64_t tsc = 0;
int timing_rr;
int timing_mr, timing_mrl;
int timing_rm, timing_rml;
int timing_mm, timing_mml;
int timing_bt, timing_bnt;
int timing_int, timing_int_rm, timing_int_v86, timing_int_pm, timing_int_pm_outer;
int timing_iret_rm, timing_iret_v86, timing_iret_pm, timing_iret_pm_outer;
int timing_call_rm, timing_call_pm, timing_call_pm_gate, timing_call_pm_gate_inner;
int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer;
int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
int timing_misaligned;
static struct
{
uint32_t tr1, tr12;
uint32_t cesr;
uint32_t fcr;
uint64_t fcr2, fcr3;
} msr;
void cpu_set_edx()
{
EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
}
int fpu_get_type(int model, int manu, int cpu, const char *internal_name)
{
CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
const FPU *fpus = cpu_s->fpus;
int fpu_type = fpus[0].type;
int c = 0;
while (fpus[c].internal_name)
{
if (!strcmp(internal_name, fpus[c].internal_name))
fpu_type = fpus[c].type;
c++;
}
return fpu_type;
}
const char *fpu_get_internal_name(int model, int manu, int cpu, int type)
{
CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
const FPU *fpus = cpu_s->fpus;
int c = 0;
while (fpus[c].internal_name)
{
if (fpus[c].type == type)
return fpus[c].internal_name;
c++;
}
return fpus[0].internal_name;
}
const char *fpu_get_name_from_index(int model, int manu, int cpu, int c)
{
CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
const FPU *fpus = cpu_s->fpus;
return fpus[c].name;
}
int fpu_get_type_from_index(int model, int manu, int cpu, int c)
{
CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
const FPU *fpus = cpu_s->fpus;
return fpus[c].type;
}
void cpu_set()
{
CPU *cpu_s;
if (!models[model].cpu[cpu_manufacturer].cpus)
{
/*CPU is invalid, set to default*/
cpu_manufacturer = 0;
cpu = 0;
}
cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
CPUID = cpu_s->cpuid_model;
cpuspeed = cpu_s->speed;
is8086 = (cpu_s->cpu_type > CPU_8088);
is386 = (cpu_s->cpu_type >= CPU_386SX);
is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC);
hasfpu = (fpu_type != FPU_NONE);
cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1);
cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC);
if (cpu_s->multi)
cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
cpu_multi = cpu_s->multi;
ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0;
has_vlb = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type <= CPU_Cx5x86);
cpu_turbo_speed = cpu_s->rspeed;
if (cpu_s->cpu_type < CPU_286)
cpu_nonturbo_speed = 4772728;
else if (cpu_s->rspeed < 8000000)
cpu_nonturbo_speed = cpu_s->rspeed;
else
cpu_nonturbo_speed = 8000000;
cpu_update_waitstates();
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_s->pci_speed)
{
pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed;
pci_burst_time = cpu_s->rspeed / cpu_s->pci_speed;
}
else
{
pci_nonburst_time = 4;
pci_burst_time = 1;
}
pclog("PCI burst=%i nonburst=%i\n", pci_burst_time, pci_nonburst_time);
if (cpu_iscyrix)
io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
else
io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
pclog("hasfpu - %i\n",hasfpu);
pclog("is486 - %i %i\n",is486,cpu_s->cpu_type);
x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f);
x86_opcodes_REPE = ops_REPE;
x86_opcodes_REPNE = ops_REPNE;
x86_opcodes_3DNOW = ops_3DNOW;
x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE;
x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW;
if (hasfpu)
{
x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16;
x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32;
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16;
x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32;
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32;
x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16;
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32;
x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16;
x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32;
x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16;
x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32;
x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16;
x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32;
}
else
{
x86_dynarec_opcodes_d8_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_d8_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_d9_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_d9_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_da_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_db_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_db_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_dc_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_dc_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_dd_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_dd_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_de_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_de_a32 = dynarec_ops_nofpu_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32;
}
codegen_timing_set(&codegen_timing_486);
if (hasfpu)
{
x86_opcodes_d8_a16 = ops_fpu_d8_a16;
x86_opcodes_d8_a32 = ops_fpu_d8_a32;
x86_opcodes_d9_a16 = ops_fpu_d9_a16;
x86_opcodes_d9_a32 = ops_fpu_d9_a32;
x86_opcodes_da_a16 = ops_fpu_da_a16;
x86_opcodes_da_a32 = ops_fpu_da_a32;
x86_opcodes_db_a16 = ops_fpu_db_a16;
x86_opcodes_db_a32 = ops_fpu_db_a32;
x86_opcodes_dc_a16 = ops_fpu_dc_a16;
x86_opcodes_dc_a32 = ops_fpu_dc_a32;
x86_opcodes_dd_a16 = ops_fpu_dd_a16;
x86_opcodes_dd_a32 = ops_fpu_dd_a32;
x86_opcodes_de_a16 = ops_fpu_de_a16;
x86_opcodes_de_a32 = ops_fpu_de_a32;
x86_opcodes_df_a16 = ops_fpu_df_a16;
x86_opcodes_df_a32 = ops_fpu_df_a32;
}
else
{
x86_opcodes_d8_a16 = ops_nofpu_a16;
x86_opcodes_d8_a32 = ops_nofpu_a32;
x86_opcodes_d9_a16 = ops_nofpu_a16;
x86_opcodes_d9_a32 = ops_nofpu_a32;
x86_opcodes_da_a16 = ops_nofpu_a16;
x86_opcodes_da_a32 = ops_nofpu_a32;
x86_opcodes_db_a16 = ops_nofpu_a16;
x86_opcodes_db_a32 = ops_nofpu_a32;
x86_opcodes_dc_a16 = ops_nofpu_a16;
x86_opcodes_dc_a32 = ops_nofpu_a32;
x86_opcodes_dd_a16 = ops_nofpu_a16;
x86_opcodes_dd_a32 = ops_nofpu_a32;
x86_opcodes_de_a16 = ops_nofpu_a16;
x86_opcodes_de_a32 = ops_nofpu_a32;
x86_opcodes_df_a16 = ops_nofpu_a16;
x86_opcodes_df_a32 = ops_nofpu_a32;
}
memset(&msr, 0, sizeof(msr));
timing_misaligned = 0;
cpu_cyrix_alignment = 0;
switch (cpu_s->cpu_type)
{
case CPU_8088:
case CPU_8086:
break;
case CPU_286:
x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f);
timing_rr = 2; /*register dest - register src*/
timing_rm = 7; /*register dest - memory src*/
timing_mr = 7; /*memory dest - register src*/
timing_mm = 7; /*memory dest - memory src*/
timing_rml = 9; /*register dest - memory src long*/
timing_mrl = 11; /*memory dest - register src long*/
timing_mml = 11; /*memory dest - memory src*/
timing_bt = 7-3; /*branch taken*/
timing_bnt = 3; /*branch not taken*/
timing_int = 0;
timing_int_rm = 23;
timing_int_v86 = 0;
timing_int_pm = 40;
timing_int_pm_outer = 78;
timing_iret_rm = 17;
timing_iret_v86 = 0;
timing_iret_pm = 31;
timing_iret_pm_outer = 55;
timing_call_rm = 13;
timing_call_pm = 26;
timing_call_pm_gate = 52;
timing_call_pm_gate_inner = 82;
timing_retf_rm = 15;
timing_retf_pm = 25;
timing_retf_pm_outer = 55;
timing_jmp_rm = 11;
timing_jmp_pm = 23;
timing_jmp_pm_gate = 38;
break;
case CPU_386SX:
timing_rr = 2; /*register dest - register src*/
timing_rm = 6; /*register dest - memory src*/
timing_mr = 7; /*memory dest - register src*/
timing_mm = 6; /*memory dest - memory src*/
timing_rml = 8; /*register dest - memory src long*/
timing_mrl = 11; /*memory dest - register src long*/
timing_mml = 10; /*memory dest - memory src*/
timing_bt = 7-3; /*branch taken*/
timing_bnt = 3; /*branch not taken*/
timing_int = 0;
timing_int_rm = 37;
timing_int_v86 = 59;
timing_int_pm = 99;
timing_int_pm_outer = 119;
timing_iret_rm = 22;
timing_iret_v86 = 60;
timing_iret_pm = 38;
timing_iret_pm_outer = 82;
timing_call_rm = 17;
timing_call_pm = 34;
timing_call_pm_gate = 52;
timing_call_pm_gate_inner = 86;
timing_retf_rm = 18;
timing_retf_pm = 32;
timing_retf_pm_outer = 68;
timing_jmp_rm = 12;
timing_jmp_pm = 27;
timing_jmp_pm_gate = 45;
break;
case CPU_386DX:
timing_rr = 2; /*register dest - register src*/
timing_rm = 6; /*register dest - memory src*/
timing_mr = 7; /*memory dest - register src*/
timing_mm = 6; /*memory dest - memory src*/
timing_rml = 6; /*register dest - memory src long*/
timing_mrl = 7; /*memory dest - register src long*/
timing_mml = 6; /*memory dest - memory src*/
timing_bt = 7-3; /*branch taken*/
timing_bnt = 3; /*branch not taken*/
timing_int = 0;
timing_int_rm = 37;
timing_int_v86 = 59;
timing_int_pm = 99;
timing_int_pm_outer = 119;
timing_iret_rm = 22;
timing_iret_v86 = 60;
timing_iret_pm = 38;
timing_iret_pm_outer = 82;
timing_call_rm = 17;
timing_call_pm = 34;
timing_call_pm_gate = 52;
timing_call_pm_gate_inner = 86;
timing_retf_rm = 18;
timing_retf_pm = 32;
timing_retf_pm_outer = 68;
timing_jmp_rm = 12;
timing_jmp_pm = 27;
timing_jmp_pm_gate = 45;
break;
case CPU_486SLC:
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 5; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 5; /*register dest - memory src long*/
timing_mrl = 7; /*memory dest - register src long*/
timing_mml = 7;
timing_bt = 6-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
/*unknown*/
timing_int = 4;
timing_int_rm = 14;
timing_int_v86 = 82;
timing_int_pm = 49;
timing_int_pm_outer = 77;
timing_iret_rm = 14;
timing_iret_v86 = 66;
timing_iret_pm = 31;
timing_iret_pm_outer = 66;
timing_call_rm = 12;
timing_call_pm = 30;
timing_call_pm_gate = 41;
timing_call_pm_gate_inner = 83;
timing_retf_rm = 13;
timing_retf_pm = 26;
timing_retf_pm_outer = 61;
timing_jmp_rm = 9;
timing_jmp_pm = 26;
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_486DLC:
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 3; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 6-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
/*unknown*/
timing_int = 4;
timing_int_rm = 14;
timing_int_v86 = 82;
timing_int_pm = 49;
timing_int_pm_outer = 77;
timing_iret_rm = 14;
timing_iret_v86 = 66;
timing_iret_pm = 31;
timing_iret_pm_outer = 66;
timing_call_rm = 12;
timing_call_pm = 30;
timing_call_pm_gate = 41;
timing_call_pm_gate_inner = 83;
timing_retf_rm = 13;
timing_retf_pm = 26;
timing_retf_pm_outer = 61;
timing_jmp_rm = 9;
timing_jmp_pm = 26;
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_iDX4:
cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME;
case CPU_i486SX:
case CPU_i486DX:
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 3-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 4;
timing_int_rm = 26;
timing_int_v86 = 82;
timing_int_pm = 44;
timing_int_pm_outer = 71;
timing_iret_rm = 15;
timing_iret_v86 = 36; /*unknown*/
timing_iret_pm = 20;
timing_iret_pm_outer = 36;
timing_call_rm = 18;
timing_call_pm = 20;
timing_call_pm_gate = 35;
timing_call_pm_gate_inner = 69;
timing_retf_rm = 13;
timing_retf_pm = 17;
timing_retf_pm_outer = 35;
timing_jmp_rm = 17;
timing_jmp_pm = 19;
timing_jmp_pm_gate = 32;
timing_misaligned = 3;
break;
case CPU_Am486SX:
case CPU_Am486DX:
/*AMD timing identical to Intel*/
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 3-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 4;
timing_int_rm = 26;
timing_int_v86 = 82;
timing_int_pm = 44;
timing_int_pm_outer = 71;
timing_iret_rm = 15;
timing_iret_v86 = 36; /*unknown*/
timing_iret_pm = 20;
timing_iret_pm_outer = 36;
timing_call_rm = 18;
timing_call_pm = 20;
timing_call_pm_gate = 35;
timing_call_pm_gate_inner = 69;
timing_retf_rm = 13;
timing_retf_pm = 17;
timing_retf_pm_outer = 35;
timing_jmp_rm = 17;
timing_jmp_pm = 19;
timing_jmp_pm_gate = 32;
timing_misaligned = 3;
break;
case CPU_Cx486S:
case CPU_Cx486DX:
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 3; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 4-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 4;
timing_int_rm = 14;
timing_int_v86 = 82;
timing_int_pm = 49;
timing_int_pm_outer = 77;
timing_iret_rm = 14;
timing_iret_v86 = 66; /*unknown*/
timing_iret_pm = 31;
timing_iret_pm_outer = 66;
timing_call_rm = 12;
timing_call_pm = 30;
timing_call_pm_gate = 41;
timing_call_pm_gate_inner = 83;
timing_retf_rm = 13;
timing_retf_pm = 26;
timing_retf_pm_outer = 61;
timing_jmp_rm = 9;
timing_jmp_pm = 26;
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_Cx5x86:
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 2;
timing_rml = 1; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 2;
timing_bt = 5-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 0;
timing_int_rm = 9;
timing_int_v86 = 82; /*unknown*/
timing_int_pm = 21;
timing_int_pm_outer = 32;
timing_iret_rm = 7;
timing_iret_v86 = 26; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 4;
timing_call_pm = 15;
timing_call_pm_gate = 26;
timing_call_pm_gate_inner = 35;
timing_retf_rm = 4;
timing_retf_pm = 7;
timing_retf_pm_outer = 23;
timing_jmp_rm = 5;
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
break;
case CPU_WINCHIP:
x86_setopcodes(ops_386, ops_winchip_0f, dynarec_ops_386, dynarec_ops_winchip_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 3-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4;
msr.fcr = (1 << 8) | (1 << 16);
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
/*unknown*/
timing_int_rm = 26;
timing_int_v86 = 82;
timing_int_pm = 44;
timing_int_pm_outer = 71;
timing_iret_rm = 7;
timing_iret_v86 = 26;
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 4;
timing_call_pm = 15;
timing_call_pm_gate = 26;
timing_call_pm_gate_inner = 35;
timing_retf_rm = 4;
timing_retf_pm = 7;
timing_retf_pm_outer = 23;
timing_jmp_rm = 5;
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
codegen_timing_set(&codegen_timing_winchip);
break;
case CPU_WINCHIP2:
x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 3-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21);
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
/*unknown*/
timing_int_rm = 26;
timing_int_v86 = 82;
timing_int_pm = 44;
timing_int_pm_outer = 71;
timing_iret_rm = 7;
timing_iret_v86 = 26;
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 4;
timing_call_pm = 15;
timing_call_pm_gate = 26;
timing_call_pm_gate_inner = 35;
timing_retf_rm = 4;
timing_retf_pm = 7;
timing_retf_pm_outer = 23;
timing_jmp_rm = 5;
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
codegen_timing_set(&codegen_timing_winchip2);
break;
case CPU_PENTIUM:
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 2; /*branch not taken*/
timing_int = 6;
timing_int_rm = 11;
timing_int_v86 = 54;
timing_int_pm = 25;
timing_int_pm_outer = 42;
timing_iret_rm = 7;
timing_iret_v86 = 27; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 27;
timing_call_rm = 4;
timing_call_pm = 4;
timing_call_pm_gate = 22;
timing_call_pm_gate_inner = 44;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME;
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_PCE;
codegen_timing_set(&codegen_timing_pentium);
break;
case CPU_PENTIUMMMX:
x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 6;
timing_int_rm = 11;
timing_int_v86 = 54;
timing_int_pm = 25;
timing_int_pm_outer = 42;
timing_iret_rm = 7;
timing_iret_v86 = 27; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 27;
timing_call_rm = 4;
timing_call_pm = 4;
timing_call_pm_gate = 22;
timing_call_pm_gate_inner = 44;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX;
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_PCE;
codegen_timing_set(&codegen_timing_pentium);
break;
case CPU_Cx6x86:
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 2;
timing_rml = 1; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 2;
timing_bt = 0; /*branch taken*/
timing_bnt = 2; /*branch not taken*/
timing_int_rm = 9;
timing_int_v86 = 46;
timing_int_pm = 21;
timing_int_pm_outer = 32;
timing_iret_rm = 7;
timing_iret_v86 = 26;
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 3;
timing_call_pm = 4;
timing_call_pm_gate = 15;
timing_call_pm_gate_inner = 26;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 1;
timing_jmp_pm = 4;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_features = CPU_FEATURE_RDTSC;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
codegen_timing_set(&codegen_timing_686);
CPUID = 0; /*Disabled on powerup by default*/
break;
case CPU_Cx6x86L:
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 2;
timing_rml = 1; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 2;
timing_bt = 0; /*branch taken*/
timing_bnt = 2; /*branch not taken*/
timing_int_rm = 9;
timing_int_v86 = 46;
timing_int_pm = 21;
timing_int_pm_outer = 32;
timing_iret_rm = 7;
timing_iret_v86 = 26;
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 3;
timing_call_pm = 4;
timing_call_pm_gate = 15;
timing_call_pm_gate_inner = 26;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 1;
timing_jmp_pm = 4;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_features = CPU_FEATURE_RDTSC;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
codegen_timing_set(&codegen_timing_686);
ccr4 = 0x80;
break;
case CPU_CxGX1:
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 2;
timing_rml = 1; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 2;
timing_bt = 5-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
codegen_timing_set(&codegen_timing_686);
break;
case CPU_Cx6x86MX:
x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16;
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
x86_opcodes_db_a32 = ops_fpu_686_db_a32;
x86_opcodes_df_a16 = ops_fpu_686_df_a16;
x86_opcodes_df_a32 = ops_fpu_686_df_a32;
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
timing_mm = 2;
timing_rml = 1; /*register dest - memory src long*/
timing_mrl = 2; /*memory dest - register src long*/
timing_mml = 2;
timing_bt = 0; /*branch taken*/
timing_bnt = 2; /*branch not taken*/
timing_int_rm = 9;
timing_int_v86 = 46;
timing_int_pm = 21;
timing_int_pm_outer = 32;
timing_iret_rm = 7;
timing_iret_v86 = 26;
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 3;
timing_call_pm = 4;
timing_call_pm_gate = 15;
timing_call_pm_gate_inner = 26;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 1;
timing_jmp_pm = 4;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_MMX;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
codegen_timing_set(&codegen_timing_686);
ccr4 = 0x80;
break;
case CPU_K6:
x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 6;
timing_int_rm = 11;
timing_int_v86 = 54;
timing_int_pm = 25;
timing_int_pm_outer = 42;
timing_iret_rm = 7;
timing_iret_v86 = 27; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 27;
timing_call_rm = 4;
timing_call_pm = 4;
timing_call_pm_gate = 22;
timing_call_pm_gate_inner = 44;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX;
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;
codegen_timing_set(&codegen_timing_k6);
break;
case CPU_K6_2:
case CPU_K6_3:
case CPU_K6_2P:
case CPU_K6_3P:
x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
timing_int = 6;
timing_int_rm = 11;
timing_int_v86 = 54;
timing_int_pm = 25;
timing_int_pm_outer = 42;
timing_iret_rm = 7;
timing_iret_v86 = 27; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 27;
timing_call_rm = 4;
timing_call_pm = 4;
timing_call_pm_gate = 22;
timing_call_pm_gate_inner = 44;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX | CPU_FEATURE_3DNOW;
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;
codegen_timing_set(&codegen_timing_k6);
break;
case CPU_PENTIUMPRO:
x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16;
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
x86_opcodes_db_a32 = ops_fpu_686_db_a32;
x86_opcodes_df_a16 = ops_fpu_686_df_a16;
x86_opcodes_df_a32 = ops_fpu_686_df_a32;
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 2; /*branch not taken*/
timing_int = 6;
timing_int_rm = 11;
timing_int_v86 = 54;
timing_int_pm = 25;
timing_int_pm_outer = 42;
timing_iret_rm = 7;
timing_iret_v86 = 27; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 27;
timing_call_rm = 4;
timing_call_pm = 4;
timing_call_pm_gate = 22;
timing_call_pm_gate_inner = 44;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_CX8 | CPU_FEATURE_SYSCALL;
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_PCE;
codegen_timing_set(&codegen_timing_p6);
break;
case CPU_PENTIUM_2:
case CPU_CELERON:
case CPU_CELERON_A:
x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f);
x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16;
x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
x86_opcodes_da_a16 = ops_fpu_686_da_a16;
x86_opcodes_da_a32 = ops_fpu_686_da_a32;
x86_opcodes_db_a16 = ops_fpu_686_db_a16;
x86_opcodes_db_a32 = ops_fpu_686_db_a32;
x86_opcodes_df_a16 = ops_fpu_686_df_a16;
x86_opcodes_df_a32 = ops_fpu_686_df_a32;
timing_rr = 1; /*register dest - register src*/
timing_rm = 2; /*register dest - memory src*/
timing_mr = 3; /*memory dest - register src*/
timing_mm = 3;
timing_rml = 2; /*register dest - memory src long*/
timing_mrl = 3; /*memory dest - register src long*/
timing_mml = 3;
timing_bt = 0; /*branch taken*/
timing_bnt = 2; /*branch not taken*/
timing_int = 6;
timing_int_rm = 11;
timing_int_v86 = 54;
timing_int_pm = 25;
timing_int_pm_outer = 42;
timing_iret_rm = 7;
timing_iret_v86 = 27; /*unknown*/
timing_iret_pm = 10;
timing_iret_pm_outer = 27;
timing_call_rm = 4;
timing_call_pm = 4;
timing_call_pm_gate = 22;
timing_call_pm_gate_inner = 44;
timing_retf_rm = 4;
timing_retf_pm = 4;
timing_retf_pm_outer = 23;
timing_jmp_rm = 3;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_CX8 | CPU_FEATURE_MMX | CPU_FEATURE_SYSCALL;
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_PCE;
codegen_timing_set(&codegen_timing_p6);
break;
case CPU_CYRIX_III:
x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 1; /*memory dest - register src*/
timing_mm = 1;
timing_rml = 1; /*register dest - memory src long*/
timing_mrl = 1; /*memory dest - register src long*/
timing_mml = 1;
timing_bt = 1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21);
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
/*unknown*/
timing_int_rm = 26;
timing_int_v86 = 82;
timing_int_pm = 44;
timing_int_pm_outer = 71;
timing_iret_rm = 7;
timing_iret_v86 = 26;
timing_iret_pm = 10;
timing_iret_pm_outer = 26;
timing_call_rm = 4;
timing_call_pm = 15;
timing_call_pm_gate = 26;
timing_call_pm_gate_inner = 35;
timing_retf_rm = 4;
timing_retf_pm = 7;
timing_retf_pm_outer = 23;
timing_jmp_rm = 5;
timing_jmp_pm = 7;
timing_jmp_pm_gate = 17;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
codegen_timing_set(&codegen_timing_cyrixiii);
break;
default:
fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type);
}
switch (fpu_type)
{
case FPU_NONE:
break;
case FPU_8087:
x87_timings = x87_timings_8087;
break;
case FPU_287:
x87_timings = x87_timings_287;
break;
case FPU_287XL:
case FPU_387:
x87_timings = x87_timings_387;
break;
default:
x87_timings = x87_timings_486;
break;
}
}
void cpu_CPUID()
{
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_i486DX:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x756e6547;
EDX = 0x49656e69;
ECX = 0x6c65746e;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU; /*FPU*/
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_iDX4:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x756e6547;
EDX = 0x49656e69;
ECX = 0x6c65746e;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_VME;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Am486SX:
if (!EAX)
{
EAX = 1;
EBX = 0x68747541;
ECX = 0x444D4163;
EDX = 0x69746E65;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = EDX = 0; /*No FPU*/
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Am486DX:
if (!EAX)
{
EAX = 1;
EBX = 0x68747541;
ECX = 0x444D4163;
EDX = 0x69746E65;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU; /*FPU*/
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_WINCHIP:
if (!EAX)
{
EAX = 1;
if (msr.fcr2 & (1 << 14))
{
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
EDX = msr.fcr2 >> 32;
}
else
{
EBX = 0x746e6543; /*CentaurHauls*/
ECX = 0x736c7561;
EDX = 0x48727561;
}
}
else if (EAX == 1)
{
EAX = 0x540;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_WINCHIP2:
switch (EAX)
{
case 0:
EAX = 1;
if (msr.fcr2 & (1 << 14))
{
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
EDX = msr.fcr2 >> 32;
}
else
{
EBX = 0x746e6543; /*CentaurHauls*/
ECX = 0x736c7561;
EDX = 0x48727561;
}
break;
case 1:
EAX = 0x580;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000005;
break;
case 0x80000001:
EAX = 0x580;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
if (cpu_has_feature(CPU_FEATURE_3DNOW))
EDX |= CPUID_3DNOW;
break;
case 0x80000002: /*Processor name string*/
EAX = 0x20544449; /*IDT WinChip 2-3D*/
EBX = 0x436e6957;
ECX = 0x20706968;
EDX = 0x44332d32;
break;
case 0x80000005: /*Cache information*/
EBX = 0x08800880; /*TLBs*/
ECX = 0x20040120; /*L1 data cache*/
EDX = 0x20020120; /*L1 instruction cache*/
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
case CPU_PENTIUM:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x756e6547;
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_CMPXCHG8B;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_PENTIUMMMX:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x756e6547;
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_CMPXCHG8B | CPUID_MMX;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Cx6x86:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x69727943;
EDX = 0x736e4978;
ECX = 0x64616574;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Cx6x86L:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x69727943;
EDX = 0x736e4978;
ECX = 0x64616574;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_CMPXCHG8B;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_CxGX1:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x69727943;
EDX = 0x736e4978;
ECX = 0x64616574;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Cx6x86MX:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x69727943;
EDX = 0x736e4978;
ECX = 0x64616574;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_K6:
switch (EAX)
{
case 0:
EAX = 1;
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_CMPXCHG8B | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000005;
break;
case 0x80000001:
EAX = CPUID+0x100;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | 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 = 0x00000073; /*s*/
EBX = 0x00000000;
ECX = 0x00000000;
EDX = 0x00000000;
break;
case 0x80000005: /*Cache information*/
EBX = 0x02800140; /*TLBs*/
ECX = 0x20020220; /*L1 data cache*/
EDX = 0x20020220; /*L1 instruction cache*/
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
case CPU_K6_2:
switch (EAX)
{
case 0:
EAX = 1;
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_CMPXCHG8B | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000005;
break;
case 0x80000001:
EAX = CPUID+0x100;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW;
break;
case 0x80000002: /*Processor name string*/
EAX = 0x2d444d41; /*AMD-K6(tm) 3D pr*/
EBX = 0x7428364b;
ECX = 0x3320296d;
EDX = 0x72702044;
break;
case 0x80000003: /*Processor name string*/
EAX = 0x7365636f; /*ocessor*/
EBX = 0x00726f73;
ECX = 0x00000000;
EDX = 0x00000000;
break;
case 0x80000005: /*Cache information*/
EBX = 0x02800140; /*TLBs*/
ECX = 0x20020220; /*L1 data cache*/
EDX = 0x20020220; /*L1 instruction cache*/
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
case CPU_K6_3:
switch (EAX)
{
case 0:
EAX = 1;
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_CMPXCHG8B | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000006;
break;
case 0x80000001:
EAX = CPUID+0x100;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW;
break;
case 0x80000002: /*Processor name string*/
EAX = 0x2d444d41; /*AMD-K6(tm) 3D+ P*/
EBX = 0x7428364b;
ECX = 0x3320296d;
EDX = 0x50202b44;
break;
case 0x80000003: /*Processor name string*/
EAX = 0x65636f72; /*rocessor*/
EBX = 0x726f7373;
ECX = 0x00000000;
EDX = 0x00000000;
break;
case 0x80000005: /*Cache information*/
EBX = 0x02800140; /*TLBs*/
ECX = 0x20020220; /*L1 data cache*/
EDX = 0x20020220; /*L1 instruction cache*/
break;
case 0x80000006: /*L2 Cache information*/
ECX = 0x01004220;
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
case CPU_K6_2P:
case CPU_K6_3P:
switch (EAX)
{
case 0:
EAX = 1;
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_CMPXCHG8B | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000007;
break;
case 0x80000001:
EAX = CPUID+0x100;
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW;
break;
case 0x80000002: /*Processor name string*/
EAX = 0x2d444d41; /*AMD-K6(tm)-III P*/
EBX = 0x7428364b;
ECX = 0x492d296d;
EDX = 0x50204949;
break;
case 0x80000003: /*Processor name string*/
EAX = 0x65636f72; /*rocessor*/
EBX = 0x726f7373;
ECX = 0x00000000;
EDX = 0x00000000;
break;
case 0x80000005: /*Cache information*/
EBX = 0x02800140; /*TLBs*/
ECX = 0x20020220; /*L1 data cache*/
EDX = 0x20020220; /*L1 instruction cache*/
break;
case 0x80000006: /*L2 Cache information*/
if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_K6_3P)
ECX = 0x01004220;
else
ECX = 0x00804220;
break;
case 0x80000007: /*PowerNow information*/
EDX = 7;
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
case CPU_PENTIUMPRO:
if (!EAX)
{
EAX = 0x00000002;
EBX = 0x756e6547;
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_CMPXCHG8B | CPUID_CMOV | CPUID_SEP;
}
else if (EAX == 2)
{
EAX = 0x03020101;
EBX = 0;
ECX = 0;
EDX = 0x06040a42;
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_PENTIUM_2:
case CPU_CELERON:
case CPU_CELERON_A:
if (!EAX)
{
EAX = 0x00000002;
EBX = 0x756e6547;
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_CMPXCHG8B | CPUID_CMOV | CPUID_MMX | CPUID_SEP;
}
else if (EAX == 2)
{
EAX = 0x03020101;
EBX = 0;
ECX = 0;
if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUM_2)
EDX = 0x08040c43; /*512kb L2 cache*/
else if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_CELERON)
EDX = 0x08040c40; /*No L2 cache*/
else
EDX = 0x08040c41; /*128kb L2 cache*/
}
else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_CYRIX_III:
switch (EAX)
{
case 0:
EAX = 1;
EBX = 0x746e6543; /*CentaurHauls*/
ECX = 0x736c7561;
EDX = 0x48727561;
break;
case 1:
EAX = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000006;
break;
case 0x80000001:
EAX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
if (cpu_has_feature(CPU_FEATURE_3DNOW))
EDX |= CPUID_3DNOW;
break;
case 0x80000002: /*Processor name string*/
if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model >= 0x670)
{
EAX = 0x20414956; /*VIA Samuel 2*/
EBX = 0x756d6153;
ECX = 0x32206c65;
EDX = 0x00000000;
}
else
{
EAX = 0x20414956; /*VIA SamuelM*/
EBX = 0x756d6153;
ECX = 0x004d6c65;
EDX = 0x00000000;
}
break;
case 0x80000005: /*Cache information*/
EBX = 0x08800880; /*TLBs*/
ECX = 0x40040120; /*L1 data cache*/
EDX = 0x40020120; /*L1 instruction cache*/
break;
case 0x80000006: /*L2 Cache information*/
if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model >= 0x670)
ECX = 0x40040120; /*L2 cache*/
else
ECX = 0;
EAX = EBX = EDX = 0;
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
}
}
void cpu_RDMSR()
{
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_WINCHIP:
case CPU_WINCHIP2:
case CPU_CYRIX_III:
EAX = EDX = 0;
switch (ECX)
{
case 0x02:
EAX = msr.tr1;
break;
case 0x0e:
EAX = msr.tr12;
break;
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
case 0x11:
EAX = msr.cesr;
break;
case 0x107:
EAX = msr.fcr;
break;
case 0x108:
EAX = msr.fcr2 & 0xffffffff;
EDX = msr.fcr2 >> 32;
break;
case 0x10a:
EAX = cpu_multi & 3;
break;
}
break;
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
EAX = EDX = 0;
switch (ECX)
{
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
}
break;
case CPU_Cx6x86:
case CPU_Cx6x86L:
case CPU_CxGX1:
case CPU_Cx6x86MX:
switch (ECX)
{
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
}
break;
case CPU_K6:
case CPU_K6_2:
case CPU_K6_3:
case CPU_K6_2P:
case CPU_K6_3P:
EAX = EDX = 0;
switch (ECX)
{
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
}
break;
case CPU_PENTIUMPRO:
case CPU_PENTIUM_2:
case CPU_CELERON:
case CPU_CELERON_A:
EAX = EDX = 0;
switch (ECX)
{
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
case 0x174:
EAX = sysenter_cs;
EDX = 0;
break;
case 0x175:
EAX = sysenter_esp;
EDX = 0;
break;
case 0x176:
EAX = sysenter_eip;
EDX = 0;
break;
}
break;
}
}
void cpu_WRMSR()
{
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_WINCHIP:
case CPU_WINCHIP2:
case CPU_CYRIX_III:
switch (ECX)
{
case 0x02:
msr.tr1 = EAX & 2;
break;
case 0x0e:
msr.tr12 = EAX & 0x228;
break;
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
break;
case 0x11:
msr.cesr = EAX & 0xff00ff;
break;
case 0x107:
msr.fcr = EAX;
if (EAX & (1 << 9))
cpu_features |= CPU_FEATURE_MMX;
else
cpu_features &= ~CPU_FEATURE_MMX;
if (EAX & (1 << 1))
cpu_features |= CPU_FEATURE_CX8;
else
cpu_features &= ~CPU_FEATURE_CX8;
if ((EAX & (1 << 20)) && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_WINCHIP2)
cpu_features |= CPU_FEATURE_3DNOW;
else
cpu_features &= ~CPU_FEATURE_3DNOW;
if (EAX & (1 << 29))
CPUID = 0;
else
CPUID = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model;
break;
case 0x108:
msr.fcr2 = EAX | ((uint64_t)EDX << 32);
break;
case 0x109:
msr.fcr3 = EAX | ((uint64_t)EDX << 32);
break;
}
break;
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
switch (ECX)
{
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
break;
}
break;
case CPU_Cx6x86:
case CPU_Cx6x86L:
case CPU_CxGX1:
case CPU_Cx6x86MX:
switch (ECX)
{
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
break;
}
break;
case CPU_K6:
case CPU_K6_2:
case CPU_K6_3:
case CPU_K6_2P:
case CPU_K6_3P:
switch (ECX)
{
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
break;
}
break;
case CPU_PENTIUMPRO:
case CPU_PENTIUM_2:
case CPU_CELERON:
case CPU_CELERON_A:
switch (ECX)
{
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
break;
case 0x174:
sysenter_cs = EAX & 0xffff;
break;
case 0x175:
sysenter_esp = EAX;
break;
case 0x176:
sysenter_eip = EAX;
break;
}
break;
}
}
static int cyrix_addr;
void cyrix_write(uint16_t addr, uint8_t val, void *priv)
{
if (!(addr & 1))
cyrix_addr = val;
else switch (cyrix_addr)
{
case 0xc0: /*CCR0*/
ccr0 = val;
break;
case 0xc1: /*CCR1*/
ccr1 = val;
break;
case 0xc2: /*CCR2*/
ccr2 = val;
break;
case 0xc3: /*CCR3*/
ccr3 = val;
break;
case 0xe8: /*CCR4*/
if ((ccr3 & 0xf0) == 0x10)
{
ccr4 = val;
if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_Cx6x86)
{
if (val & 0x80)
CPUID = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model;
else
CPUID = 0;
}
}
break;
case 0xe9: /*CCR5*/
if ((ccr3 & 0xf0) == 0x10)
ccr5 = val;
break;
case 0xea: /*CCR6*/
if ((ccr3 & 0xf0) == 0x10)
ccr6 = val;
break;
}
}
uint8_t cyrix_read(uint16_t addr, void *priv)
{
if (addr & 1)
{
switch (cyrix_addr)
{
case 0xc0: return ccr0;
case 0xc1: return ccr1;
case 0xc2: return ccr2;
case 0xc3: return ccr3;
case 0xe8: return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff;
case 0xe9: return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff;
case 0xea: return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff;
case 0xfe: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id & 0xff;
case 0xff: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id >> 8;
}
if (cyrix_addr == 0x20 && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_Cx5x86) return 0xff;
}
return 0xff;
}
void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f)
{
x86_opcodes = opcodes;
x86_opcodes_0f = opcodes_0f;
x86_dynarec_opcodes = dynarec_opcodes;
x86_dynarec_opcodes_0f = dynarec_opcodes_0f;
}
void cpu_update_waitstates()
{
cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
if (is486)
cpu_prefetch_width = 16;
else
cpu_prefetch_width = cpu_16bitbus ? 2 : 4;
if (cpu_cache_int_enabled)
{
/* Disable prefetch emulation */
cpu_prefetch_cycles = 0;
}
else if (cpu_waitstates && (cpu_s->cpu_type >= CPU_286 && cpu_s->cpu_type <= CPU_386DX))
{
/* Waitstates override */
cpu_prefetch_cycles = cpu_waitstates+1;
cpu_cycles_read = cpu_waitstates+1;
cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1);
cpu_cycles_write = cpu_waitstates+1;
cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1);
}
else if (cpu_cache_ext_enabled)
{
/* Use cache timings */
cpu_prefetch_cycles = cpu_s->cache_read_cycles;
cpu_cycles_read = cpu_s->cache_read_cycles;
cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_read_cycles;
cpu_cycles_write = cpu_s->cache_write_cycles;
cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_write_cycles;
}
else
{
/* Use memory timings */
cpu_prefetch_cycles = cpu_s->mem_read_cycles;
cpu_cycles_read = cpu_s->mem_read_cycles;
cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_read_cycles;
cpu_cycles_write = cpu_s->mem_write_cycles;
cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles;
}
if (is486)
cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16;
cpu_mem_prefetch_cycles = cpu_prefetch_cycles;
if (cpu_s->rspeed <= 8000000)
cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles;
}
void cpu_set_turbo(int turbo)
{
if (cpu_turbo != turbo)
{
cpu_turbo = turbo;
cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
if (cpu_s->cpu_type >= CPU_286)
{
if (cpu_turbo)
setpitclock(cpu_turbo_speed);
else
setpitclock(cpu_nonturbo_speed);
}
else
setpitclock(14318184.0);
}
}
int cpu_get_speed()
{
if (cpu_turbo)
return cpu_turbo_speed;
return cpu_nonturbo_speed;
}