Merge pull request #809 from nerd73/master

Preliminary port of PCem's FPU timing emulation
This commit is contained in:
OBattler
2020-06-15 17:12:08 +02:00
committed by GitHub
12 changed files with 1124 additions and 600 deletions

View File

@@ -528,6 +528,9 @@ load_machine(void)
cpu = config_get_int(cat, "cpu", 0); cpu = config_get_int(cat, "cpu", 0);
cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0);
p = (char *)config_get_string(cat, "fpu", "none");
fpu_type = fpu_get_type(machine, cpu_manufacturer, cpu, p);
mem_size = config_get_int(cat, "mem_size", 4096); mem_size = config_get_int(cat, "mem_size", 4096);
#if 0 #if 0
@@ -541,8 +544,6 @@ load_machine(void)
cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0);
enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0);
p = config_get_string(cat, "time_sync", NULL); p = config_get_string(cat, "time_sync", NULL);
if (p != NULL) { if (p != NULL) {
if (!strcmp(p, "disabled")) if (!strcmp(p, "disabled"))

View File

@@ -59,6 +59,7 @@
#ifdef USE_DYNAREC #ifdef USE_DYNAREC
# include "codegen.h" # include "codegen.h"
#endif #endif
#include "x87_timings.h"
/*#define ENABLE_CPU_LOG 1*/ /*#define ENABLE_CPU_LOG 1*/
@@ -171,7 +172,7 @@ int is286,
is_am486, is_pentium, is_k5, is_k6, is_p6; is_am486, is_pentium, is_k5, is_k6, is_p6;
int hasfpu; int hasfpu;
int fpu_type;
uint64_t tsc = 0; uint64_t tsc = 0;
msr_t msr; msr_t msr;
@@ -211,7 +212,6 @@ uint64_t ecx404_msr = 0;
uint64_t ecx408_msr = 0; uint64_t ecx408_msr = 0;
uint64_t ecx40c_msr = 0; uint64_t ecx40c_msr = 0;
uint64_t ecx410_msr = 0; uint64_t ecx410_msr = 0;
uint64_t ecx570_msr = 0; uint64_t ecx570_msr = 0;
uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */
@@ -296,6 +296,54 @@ cpu_set_edx(void)
EDX = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].edx_reset; EDX = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].edx_reset;
} }
int fpu_get_type(int machine, int cpu_manufacturer, int cpu, const char *internal_name)
{
CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].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 machine, int cpu_manufacturer, int cpu, int type)
{
CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].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 machine, int cpu_manufacturer, int cpu, int c)
{
CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu];
const FPU *fpus = cpu_s->fpus;
return fpus[c].name;
}
int fpu_get_type_from_index(int machine, int cpu_manufacturer, int cpu, int c)
{
CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu];
const FPU *fpus = cpu_s->fpus;
return fpus[c].type;
}
void void
cpu_set(void) cpu_set(void)
@@ -343,7 +391,7 @@ cpu_set(void)
(cpu_s->cpu_type == CPU_PENTIUM2D); (cpu_s->cpu_type == CPU_PENTIUM2D);
/* The Samuel 2 datasheet claims it's Celeron-compatible. */ /* The Samuel 2 datasheet claims it's Celeron-compatible. */
is_p6 |= (cpu_s->cpu_type == CPU_CYRIX3S); is_p6 |= (cpu_s->cpu_type == CPU_CYRIX3S);
hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); hasfpu = (fpu_type != FPU_NONE);
hascache = (cpu_s->cpu_type >= CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); hascache = (cpu_s->cpu_type >= CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL);
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
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_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);
@@ -362,11 +410,7 @@ cpu_set(void)
cpu_dmulti = cpu_s->multi; cpu_dmulti = cpu_s->multi;
ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0;
if ((cpu_s->cpu_type == CPU_8088) || (cpu_s->cpu_type == CPU_8086) ||
(cpu_s->cpu_type == CPU_286) || (cpu_s->cpu_type == CPU_386SX) ||
(cpu_s->cpu_type == CPU_386DX) || (cpu_s->cpu_type == CPU_i486SX)) {
hasfpu = !!enable_external_fpu;
}
cpu_update_waitstates(); cpu_update_waitstates();
@@ -509,7 +553,7 @@ cpu_set(void)
#else #else
x86_setopcodes(ops_286, ops_286_0f); x86_setopcodes(ops_286, ops_286_0f);
#endif #endif
if (enable_external_fpu) if (fpu_type == FPU_287)
{ {
#ifdef USE_DYNAREC #ifdef USE_DYNAREC
x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16;
@@ -617,6 +661,39 @@ cpu_set(void)
x86_setopcodes(ops_386, ops_486_0f); x86_setopcodes(ops_386, ops_486_0f);
#endif #endif
case CPU_386DX: case CPU_386DX:
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_db_a16 = dynarec_ops_fpu_287_db_a16;
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_dd_a16 = dynarec_ops_fpu_287_dd_a16;
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_df_a16 = dynarec_ops_fpu_287_df_a16;
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_a32 = ops_fpu_287_db_a32;
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_a32 = ops_fpu_287_dd_a32;
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_a32 = ops_fpu_287_df_a32;
}
timing_rr = 2; /*register dest - register src*/ timing_rr = 2; /*register dest - register src*/
timing_rm = 6; /*register dest - memory src*/ timing_rm = 6; /*register dest - memory src*/
timing_mr = 7; /*memory dest - register src*/ timing_mr = 7; /*memory dest - register src*/
@@ -1619,9 +1696,30 @@ cpu_set(void)
default: default:
fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); 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;
}
} }
char * char *
cpu_current_pc(char *bufp) cpu_current_pc(char *bufp)
{ {

View File

@@ -20,6 +20,18 @@
*/ */
#ifndef EMU_CPU_H #ifndef EMU_CPU_H
# define EMU_CPU_H # define EMU_CPU_H
extern int fpu_type;
enum {
FPU_NONE,
FPU_8087,
FPU_287,
FPU_287XL,
FPU_387,
FPU_BUILTIN
};
enum { enum {
CPU_8088, /* 808x class CPUs */ CPU_8088, /* 808x class CPUs */
CPU_8086, CPU_8086,
@@ -91,10 +103,16 @@ enum {
#define CPU_REQUIRES_DYNAREC 2 #define CPU_REQUIRES_DYNAREC 2
#define CPU_ALTERNATE_XTAL 4 #define CPU_ALTERNATE_XTAL 4
typedef struct {
const char *name;
const char *internal_name;
const int type;
} FPU;
typedef struct { typedef struct {
const char *name; const char *name;
int cpu_type; int cpu_type;
const FPU *fpus;
int rspeed; int rspeed;
double multi; double multi;
uint32_t edx_reset; uint32_t edx_reset;
@@ -375,6 +393,7 @@ extern int cpu_16bitbus, cpu_64bitbus;
extern int cpu_busspeed, cpu_pci_speed; extern int cpu_busspeed, cpu_pci_speed;
extern int cpu_multi; extern int cpu_multi;
extern double cpu_dmulti; extern double cpu_dmulti;
extern double fpu_multi;
extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment
penalties when crossing 8-byte boundaries*/ penalties when crossing 8-byte boundaries*/
@@ -573,5 +592,9 @@ extern int sysexit(uint32_t fetchdat);
extern int syscall(uint32_t fetchdat); extern int syscall(uint32_t fetchdat);
extern int sysret(uint32_t fetchdat); extern int sysret(uint32_t fetchdat);
int fpu_get_type(int machine, int cpu_manufacturer, int cpu, const char *internal_name);
const char *fpu_get_internal_name(int machine, int cpu_manufacturer, int cpu, int type);
const char *fpu_get_name_from_index(int machine, int cpu_manufacturer, int cpu, int c);
int fpu_get_type_from_index(int machine, int cpu_manufacturer, int cpu, int c);
#endif /*EMU_CPU_H*/ #endif /*EMU_CPU_H*/

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@
*/ */
#include <math.h> #include <math.h>
#include <fenv.h> #include <fenv.h>
#include "x87_timings.h"
#ifdef _MSC_VER #ifdef _MSC_VER
# include <intrin.h> # include <intrin.h>
#endif #endif

View File

@@ -1,4 +1,4 @@
#define opFPU(name, optype, a_size, load_var, get, use_var) \ #define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \
static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
{ \ { \
optype t; \ optype t; \
@@ -12,7 +12,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
if ((cpu_state.npxc >> 10) & 3) \ if ((cpu_state.npxc >> 10) & 3) \
fesetround(FE_TONEAREST); \ fesetround(FE_TONEAREST); \
FP_TAG_VALID; \ FP_TAG_VALID; \
CLOCK_CYCLES(8); \ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -24,7 +24,7 @@ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
CLOCK_CYCLES(4); \ CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -37,7 +37,7 @@ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
x87_pop(); \ x87_pop(); \
CLOCK_CYCLES(4); \ CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -49,7 +49,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_div(ST(0), ST(0), use_var); \ x87_div(ST(0), ST(0), use_var); \
FP_TAG_VALID; \ FP_TAG_VALID; \
CLOCK_CYCLES(73); \ CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -61,7 +61,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_div(ST(0), use_var, ST(0)); \ x87_div(ST(0), use_var, ST(0)); \
FP_TAG_VALID; \ FP_TAG_VALID; \
CLOCK_CYCLES(73); \ CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -73,7 +73,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) *= use_var; \ ST(0) *= use_var; \
FP_TAG_VALID; \ FP_TAG_VALID; \
CLOCK_CYCLES(11); \ CLOCK_CYCLES(x87_timings.fmul ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -85,7 +85,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) -= use_var; \ ST(0) -= use_var; \
FP_TAG_VALID; \ FP_TAG_VALID; \
CLOCK_CYCLES(8); \ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \ return 0; \
} \ } \
static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -97,27 +97,27 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) = use_var - ST(0); \ ST(0) = use_var - ST(0); \
FP_TAG_VALID; \ FP_TAG_VALID; \
CLOCK_CYCLES(8); \ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \ return 0; \
} }
opFPU(s, x87_ts, 16, t.i, geteal, t.s) opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32)
#ifndef FPU_8087 #ifndef FPU_8087
opFPU(s, x87_ts, 32, t.i, geteal, t.s) opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32)
#endif #endif
opFPU(d, x87_td, 16, t.i, geteaq, t.d) opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64)
#ifndef FPU_8087 #ifndef FPU_8087
opFPU(d, x87_td, 32, t.i, geteaq, t.d) opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64)
#endif #endif
opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t) opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t, _i16)
#ifndef FPU_8087 #ifndef FPU_8087
opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t) opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t, _i16)
#endif #endif
opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t) opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t, _i32)
#ifndef FPU_8087 #ifndef FPU_8087
opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t) opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t, _i32)
#endif #endif
@@ -127,7 +127,7 @@ static int opFADD(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(0) + ST(fetchdat & 7); ST(0) = ST(0) + ST(fetchdat & 7);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
static int opFADDr(uint32_t fetchdat) static int opFADDr(uint32_t fetchdat)
@@ -136,7 +136,7 @@ static int opFADDr(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
FP_TAG_VALID_F; FP_TAG_VALID_F;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
static int opFADDP(uint32_t fetchdat) static int opFADDP(uint32_t fetchdat)
@@ -146,7 +146,7 @@ static int opFADDP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
FP_TAG_VALID_F; FP_TAG_VALID_F;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
@@ -157,7 +157,7 @@ static int opFCOM(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3; if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0; else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fcom);
return 0; return 0;
} }
@@ -168,7 +168,7 @@ static int opFCOMP(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7));
x87_pop(); x87_pop();
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fcom);
return 0; return 0;
} }
@@ -187,7 +187,7 @@ static int opFCOMPP(uint32_t fetchdat)
x87_pop(); x87_pop();
x87_pop(); x87_pop();
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fcom);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -199,7 +199,7 @@ static int opFUCOMPP(uint32_t fetchdat)
cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); cpu_state.npxs |= x87_ucompare(ST(0), ST(1));
x87_pop(); x87_pop();
x87_pop(); x87_pop();
CLOCK_CYCLES(5); CLOCK_CYCLES(x87_timings.fucom);
return 0; return 0;
} }
@@ -211,7 +211,7 @@ static int opFCOMI(uint32_t fetchdat)
cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fcom);
return 0; return 0;
} }
static int opFCOMIP(uint32_t fetchdat) static int opFCOMIP(uint32_t fetchdat)
@@ -223,7 +223,7 @@ static int opFCOMIP(uint32_t fetchdat)
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
x87_pop(); x87_pop();
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fcom);
return 0; return 0;
} }
#endif #endif
@@ -234,7 +234,7 @@ static int opFDIV(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
x87_div(ST(0), ST(0), ST(fetchdat & 7)); x87_div(ST(0), ST(0), ST(fetchdat & 7));
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(73); CLOCK_CYCLES(x87_timings.fdiv);
return 0; return 0;
} }
static int opFDIVr(uint32_t fetchdat) static int opFDIVr(uint32_t fetchdat)
@@ -243,7 +243,7 @@ static int opFDIVr(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
FP_TAG_VALID_F; FP_TAG_VALID_F;
CLOCK_CYCLES(73); CLOCK_CYCLES(x87_timings.fdiv);
return 0; return 0;
} }
static int opFDIVP(uint32_t fetchdat) static int opFDIVP(uint32_t fetchdat)
@@ -253,7 +253,7 @@ static int opFDIVP(uint32_t fetchdat)
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
FP_TAG_VALID_F; FP_TAG_VALID_F;
x87_pop(); x87_pop();
CLOCK_CYCLES(73); CLOCK_CYCLES(x87_timings.fdiv);
return 0; return 0;
} }
@@ -263,7 +263,7 @@ static int opFDIVR(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
x87_div(ST(0), ST(fetchdat&7), ST(0)); x87_div(ST(0), ST(fetchdat&7), ST(0));
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(73); CLOCK_CYCLES(x87_timings.fdiv);
return 0; return 0;
} }
static int opFDIVRr(uint32_t fetchdat) static int opFDIVRr(uint32_t fetchdat)
@@ -272,7 +272,7 @@ static int opFDIVRr(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
FP_TAG_VALID_F; FP_TAG_VALID_F;
CLOCK_CYCLES(73); CLOCK_CYCLES(x87_timings.fdiv);
return 0; return 0;
} }
static int opFDIVRP(uint32_t fetchdat) static int opFDIVRP(uint32_t fetchdat)
@@ -282,7 +282,7 @@ static int opFDIVRP(uint32_t fetchdat)
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
FP_TAG_VALID_F; FP_TAG_VALID_F;
x87_pop(); x87_pop();
CLOCK_CYCLES(73); CLOCK_CYCLES(x87_timings.fdiv);
return 0; return 0;
} }
@@ -292,7 +292,7 @@ static int opFMUL(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(0) * ST(fetchdat & 7); ST(0) = ST(0) * ST(fetchdat & 7);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(16); CLOCK_CYCLES(x87_timings.fmul);
return 0; return 0;
} }
static int opFMULr(uint32_t fetchdat) static int opFMULr(uint32_t fetchdat)
@@ -301,7 +301,7 @@ static int opFMULr(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
FP_TAG_VALID_F; FP_TAG_VALID_F;
CLOCK_CYCLES(16); CLOCK_CYCLES(x87_timings.fmul);
return 0; return 0;
} }
static int opFMULP(uint32_t fetchdat) static int opFMULP(uint32_t fetchdat)
@@ -311,7 +311,7 @@ static int opFMULP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
FP_TAG_VALID_F; FP_TAG_VALID_F;
x87_pop(); x87_pop();
CLOCK_CYCLES(16); CLOCK_CYCLES(x87_timings.fmul);
return 0; return 0;
} }
@@ -321,7 +321,7 @@ static int opFSUB(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(0) - ST(fetchdat & 7); ST(0) = ST(0) - ST(fetchdat & 7);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
static int opFSUBr(uint32_t fetchdat) static int opFSUBr(uint32_t fetchdat)
@@ -330,7 +330,7 @@ static int opFSUBr(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
FP_TAG_VALID_F; FP_TAG_VALID_F;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
static int opFSUBP(uint32_t fetchdat) static int opFSUBP(uint32_t fetchdat)
@@ -340,7 +340,7 @@ static int opFSUBP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
FP_TAG_VALID_F; FP_TAG_VALID_F;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
@@ -350,7 +350,7 @@ static int opFSUBR(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(fetchdat & 7) - ST(0); ST(0) = ST(fetchdat & 7) - ST(0);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
static int opFSUBRr(uint32_t fetchdat) static int opFSUBRr(uint32_t fetchdat)
@@ -359,7 +359,7 @@ static int opFSUBRr(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
FP_TAG_VALID_F; FP_TAG_VALID_F;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
static int opFSUBRP(uint32_t fetchdat) static int opFSUBRP(uint32_t fetchdat)
@@ -369,7 +369,7 @@ static int opFSUBRP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
FP_TAG_VALID_F; FP_TAG_VALID_F;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fadd);
return 0; return 0;
} }
@@ -380,7 +380,7 @@ static int opFUCOM(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fucom);
return 0; return 0;
} }
@@ -391,7 +391,7 @@ static int opFUCOMP(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
x87_pop(); x87_pop();
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fucom);
return 0; return 0;
} }
@@ -403,7 +403,7 @@ static int opFUCOMI(uint32_t fetchdat)
cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fucom);
return 0; return 0;
} }
static int opFUCOMIP(uint32_t fetchdat) static int opFUCOMIP(uint32_t fetchdat)
@@ -415,7 +415,7 @@ static int opFUCOMIP(uint32_t fetchdat)
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
x87_pop(); x87_pop();
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fucom);
return 0; return 0;
} }
#endif #endif

View File

@@ -23,7 +23,7 @@ static int opFILDiw_a16(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1; temp = geteaw(); if (cpu_state.abrt) return 1;
x87_push((double)temp); x87_push((double)temp);
CLOCK_CYCLES(13); CLOCK_CYCLES(x87_timings.fild_16);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -35,7 +35,7 @@ static int opFILDiw_a32(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1; temp = geteaw(); if (cpu_state.abrt) return 1;
x87_push((double)temp); x87_push((double)temp);
CLOCK_CYCLES(13); CLOCK_CYCLES(x87_timings.fild_16);
return 0; return 0;
} }
#endif #endif
@@ -48,7 +48,7 @@ static int opFISTiw_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64); seteaw((int16_t)temp64);
CLOCK_CYCLES(29); CLOCK_CYCLES(x87_timings.fist_16);
return cpu_state.abrt; return cpu_state.abrt;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -60,7 +60,7 @@ static int opFISTiw_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64); seteaw((int16_t)temp64);
CLOCK_CYCLES(29); CLOCK_CYCLES(x87_timings.fist_16);
return cpu_state.abrt; return cpu_state.abrt;
} }
#endif #endif
@@ -74,7 +74,7 @@ static int opFISTPiw_a16(uint32_t fetchdat)
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(29); CLOCK_CYCLES(x87_timings.fist_16);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -87,7 +87,7 @@ static int opFISTPiw_a32(uint32_t fetchdat)
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(29); CLOCK_CYCLES(x87_timings.fist_16);
return 0; return 0;
} }
#endif #endif
@@ -103,7 +103,7 @@ static int opFILDiq_a16(uint32_t fetchdat)
cpu_state.MM[cpu_state.TOP&7].q = temp64; cpu_state.MM[cpu_state.TOP&7].q = temp64;
FP_TAG_DEFAULT; FP_TAG_DEFAULT;
CLOCK_CYCLES(10); CLOCK_CYCLES(x87_timings.fild_64);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -118,7 +118,7 @@ static int opFILDiq_a32(uint32_t fetchdat)
cpu_state.MM[cpu_state.TOP&7].q = temp64; cpu_state.MM[cpu_state.TOP&7].q = temp64;
FP_TAG_DEFAULT; FP_TAG_DEFAULT;
CLOCK_CYCLES(10); CLOCK_CYCLES(x87_timings.fild_64);
return 0; return 0;
} }
#endif #endif
@@ -147,6 +147,7 @@ static int FBSTP_a16(uint32_t fetchdat)
if (ST(0) < 0.0) tempc |= 0x80; if (ST(0) < 0.0) tempc |= 0x80;
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1; writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(x87_timings.fbstp);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -174,6 +175,7 @@ static int FBSTP_a32(uint32_t fetchdat)
if (ST(0) < 0.0) tempc |= 0x80; if (ST(0) < 0.0) tempc |= 0x80;
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1; writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(x87_timings.fbstp);
return 0; return 0;
} }
#endif #endif
@@ -190,7 +192,7 @@ static int FISTPiq_a16(uint32_t fetchdat)
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteaq(temp64); if (cpu_state.abrt) return 1; seteaq(temp64); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(29); CLOCK_CYCLES(x87_timings.fist_64);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -206,7 +208,7 @@ static int FISTPiq_a32(uint32_t fetchdat)
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteaq(temp64); if (cpu_state.abrt) return 1; seteaq(temp64); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(29); CLOCK_CYCLES(x87_timings.fist_64);
return 0; return 0;
} }
#endif #endif
@@ -219,7 +221,7 @@ static int opFILDil_a16(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
templ = geteal(); if (cpu_state.abrt) return 1; templ = geteal(); if (cpu_state.abrt) return 1;
x87_push((double)templ); x87_push((double)templ);
CLOCK_CYCLES(9); CLOCK_CYCLES(x87_timings.fild_32);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -231,7 +233,7 @@ static int opFILDil_a32(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
templ = geteal(); if (cpu_state.abrt) return 1; templ = geteal(); if (cpu_state.abrt) return 1;
x87_push((double)templ); x87_push((double)templ);
CLOCK_CYCLES(9); CLOCK_CYCLES(x87_timings.fild_32);
return 0; return 0;
} }
#endif #endif
@@ -244,7 +246,7 @@ static int opFISTil_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteal((int32_t)temp64); seteal((int32_t)temp64);
CLOCK_CYCLES(28); CLOCK_CYCLES(x87_timings.fist_32);
return cpu_state.abrt; return cpu_state.abrt;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -256,7 +258,7 @@ static int opFISTil_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteal((int32_t)temp64); seteal((int32_t)temp64);
CLOCK_CYCLES(28); CLOCK_CYCLES(x87_timings.fist_32);
return cpu_state.abrt; return cpu_state.abrt;
} }
#endif #endif
@@ -270,7 +272,7 @@ static int opFISTPil_a16(uint32_t fetchdat)
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteal((int32_t)temp64); if (cpu_state.abrt) return 1; seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(28); CLOCK_CYCLES(x87_timings.fist_32);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -283,7 +285,7 @@ static int opFISTPil_a32(uint32_t fetchdat)
temp64 = x87_fround(ST(0)); temp64 = x87_fround(ST(0));
seteal((int32_t)temp64); if (cpu_state.abrt) return 1; seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(28); CLOCK_CYCLES(x87_timings.fist_32);
return 0; return 0;
} }
#endif #endif
@@ -296,7 +298,7 @@ static int opFLDe_a16(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
t=x87_ld80(); if (cpu_state.abrt) return 1; t=x87_ld80(); if (cpu_state.abrt) return 1;
x87_push(t); x87_push(t);
CLOCK_CYCLES(6); CLOCK_CYCLES(x87_timings.fld_80);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -308,7 +310,7 @@ static int opFLDe_a32(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
t=x87_ld80(); if (cpu_state.abrt) return 1; t=x87_ld80(); if (cpu_state.abrt) return 1;
x87_push(t); x87_push(t);
CLOCK_CYCLES(6); CLOCK_CYCLES(x87_timings.fld_80);
return 0; return 0;
} }
#endif #endif
@@ -320,7 +322,7 @@ static int opFSTPe_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_st80(ST(0)); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(6); CLOCK_CYCLES(x87_timings.fld_80);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -331,7 +333,7 @@ static int opFSTPe_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_st80(ST(0)); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(6); CLOCK_CYCLES(x87_timings.fld_80);
return 0; return 0;
} }
#endif #endif
@@ -344,7 +346,7 @@ static int opFLDd_a16(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
t.i = geteaq(); if (cpu_state.abrt) return 1; t.i = geteaq(); if (cpu_state.abrt) return 1;
x87_push(t.d); x87_push(t.d);
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fld_64);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -356,7 +358,7 @@ static int opFLDd_a32(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
t.i = geteaq(); if (cpu_state.abrt) return 1; t.i = geteaq(); if (cpu_state.abrt) return 1;
x87_push(t.d); x87_push(t.d);
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fld_64);
return 0; return 0;
} }
#endif #endif
@@ -369,7 +371,7 @@ static int opFSTd_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
t.d = ST(0); t.d = ST(0);
seteaq(t.i); seteaq(t.i);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fst_64);
return cpu_state.abrt; return cpu_state.abrt;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -381,7 +383,7 @@ static int opFSTd_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
t.d = ST(0); t.d = ST(0);
seteaq(t.i); seteaq(t.i);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fst_64);
return cpu_state.abrt; return cpu_state.abrt;
} }
#endif #endif
@@ -395,7 +397,7 @@ static int opFSTPd_a16(uint32_t fetchdat)
t.d = ST(0); t.d = ST(0);
seteaq(t.i); if (cpu_state.abrt) return 1; seteaq(t.i); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fst_64);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -408,7 +410,7 @@ static int opFSTPd_a32(uint32_t fetchdat)
t.d = ST(0); t.d = ST(0);
seteaq(t.i); if (cpu_state.abrt) return 1; seteaq(t.i); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fst_64);
return 0; return 0;
} }
#endif #endif
@@ -421,7 +423,7 @@ static int opFLDs_a16(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
ts.i = geteal(); if (cpu_state.abrt) return 1; ts.i = geteal(); if (cpu_state.abrt) return 1;
x87_push((double)ts.s); x87_push((double)ts.s);
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fld_32);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -433,7 +435,7 @@ static int opFLDs_a32(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
ts.i = geteal(); if (cpu_state.abrt) return 1; ts.i = geteal(); if (cpu_state.abrt) return 1;
x87_push((double)ts.s); x87_push((double)ts.s);
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fld_32);
return 0; return 0;
} }
#endif #endif
@@ -446,7 +448,7 @@ static int opFSTs_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
ts.s = (float)ST(0); ts.s = (float)ST(0);
seteal(ts.i); seteal(ts.i);
CLOCK_CYCLES(7); CLOCK_CYCLES(x87_timings.fst_32);
return cpu_state.abrt; return cpu_state.abrt;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -458,7 +460,7 @@ static int opFSTs_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
ts.s = (float)ST(0); ts.s = (float)ST(0);
seteal(ts.i); seteal(ts.i);
CLOCK_CYCLES(7); CLOCK_CYCLES(x87_timings.fst_32);
return cpu_state.abrt; return cpu_state.abrt;
} }
#endif #endif
@@ -472,7 +474,7 @@ static int opFSTPs_a16(uint32_t fetchdat)
ts.s = (float)ST(0); ts.s = (float)ST(0);
seteal(ts.i); if (cpu_state.abrt) return 1; seteal(ts.i); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(7); CLOCK_CYCLES(x87_timings.fst_32);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -485,7 +487,7 @@ static int opFSTPs_a32(uint32_t fetchdat)
ts.s = (float)ST(0); ts.s = (float)ST(0);
seteal(ts.i); if (cpu_state.abrt) return 1; seteal(ts.i); if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(7); CLOCK_CYCLES(x87_timings.fst_32);
return 0; return 0;
} }
#endif #endif

View File

@@ -15,7 +15,7 @@ static int opFSTSW_AX(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
AX = cpu_state.npxs; AX = cpu_state.npxs;
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fstcw_sw);
return 0; return 0;
} }
#endif #endif
@@ -25,7 +25,7 @@ static int opFNOP(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fnop);
return 0; return 0;
} }
@@ -34,7 +34,7 @@ static int opFCLEX(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
cpu_state.npxs &= 0xff00; cpu_state.npxs &= 0xff00;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fnop);
return 0; return 0;
} }
@@ -58,7 +58,7 @@ static int opFINIT(uint32_t fetchdat)
#endif #endif
cpu_state.TOP = 0; cpu_state.TOP = 0;
cpu_state.ismmx = 0; cpu_state.ismmx = 0;
CLOCK_CYCLES(17); CLOCK_CYCLES(x87_timings.finit);
CPU_BLOCK_END(); CPU_BLOCK_END();
return 0; return 0;
} }
@@ -73,7 +73,7 @@ static int opFFREE(uint32_t fetchdat)
#else #else
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3;
#endif #endif
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.ffree);
return 0; return 0;
} }
@@ -83,7 +83,7 @@ static int opFFREEP(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; if (cpu_state.abrt) return 1; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; if (cpu_state.abrt) return 1;
x87_pop(); x87_pop();
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.ffree);
return 0; return 0;
} }
@@ -93,7 +93,7 @@ static int opFST(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0); ST(fetchdat & 7) = ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fst);
return 0; return 0;
} }
@@ -104,7 +104,7 @@ static int opFSTP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(0); ST(fetchdat & 7) = ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
x87_pop(); x87_pop();
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fst);
return 0; return 0;
} }
@@ -160,7 +160,7 @@ static int FSTOR()
#endif #endif
cpu_state.ismmx = 1; cpu_state.ismmx = 1;
CLOCK_CYCLES((cr0 & 1) ? 34 : 44); CLOCK_CYCLES(x87_timings.frstor);
return cpu_state.abrt; return cpu_state.abrt;
} }
static int opFSTOR_a16(uint32_t fetchdat) static int opFSTOR_a16(uint32_t fetchdat)
@@ -330,7 +330,7 @@ static int FSAVE()
cpu_state.TOP = 0; cpu_state.TOP = 0;
cpu_state.ismmx = 0; cpu_state.ismmx = 0;
CLOCK_CYCLES((cr0 & 1) ? 56 : 67); CLOCK_CYCLES(x87_timings.fsave);
return cpu_state.abrt; return cpu_state.abrt;
} }
static int opFSAVE_a16(uint32_t fetchdat) static int opFSAVE_a16(uint32_t fetchdat)
@@ -358,7 +358,7 @@ static int opFSTSW_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat); fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt; return cpu_state.abrt;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -368,7 +368,7 @@ static int opFSTSW_a32(uint32_t fetchdat)
fetch_ea_32(fetchdat); fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt; return cpu_state.abrt;
} }
#endif #endif
@@ -386,7 +386,7 @@ static int opFLD(uint32_t fetchdat)
x87_push(ST(fetchdat&7)); x87_push(ST(fetchdat&7));
cpu_state.tag[cpu_state.TOP&7] = old_tag; cpu_state.tag[cpu_state.TOP&7] = old_tag;
cpu_state.MM[cpu_state.TOP&7].q = old_i64; cpu_state.MM[cpu_state.TOP&7].q = old_i64;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fld);
return 0; return 0;
} }
@@ -407,7 +407,7 @@ static int opFXCH(uint32_t fetchdat)
cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64; cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fxch);
return 0; return 0;
} }
@@ -417,7 +417,7 @@ static int opFCHS(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = -ST(0); ST(0) = -ST(0);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(6); CLOCK_CYCLES(x87_timings.fchs);
return 0; return 0;
} }
@@ -427,7 +427,7 @@ static int opFABS(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = fabs(ST(0)); ST(0) = fabs(ST(0));
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fabs);
return 0; return 0;
} }
@@ -438,7 +438,7 @@ static int opFTST(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == 0.0) cpu_state.npxs |= C3; if (ST(0) == 0.0) cpu_state.npxs |= C3;
else if (ST(0) < 0.0) cpu_state.npxs |= C0; else if (ST(0) < 0.0) cpu_state.npxs |= C0;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.ftst);
return 0; return 0;
} }
@@ -455,7 +455,7 @@ static int opFXAM(uint32_t fetchdat)
else if (ST(0) == 0.0) cpu_state.npxs |= C3; else if (ST(0) == 0.0) cpu_state.npxs |= C3;
else cpu_state.npxs |= C2; else cpu_state.npxs |= C2;
if (ST(0) < 0.0) cpu_state.npxs |= C1; if (ST(0) < 0.0) cpu_state.npxs |= C1;
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fxam);
return 0; return 0;
} }
@@ -464,7 +464,7 @@ static int opFLD1(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push(1.0); x87_push(1.0);
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fld_z1);
return 0; return 0;
} }
@@ -473,7 +473,7 @@ static int opFLDL2T(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push(3.3219280948873623); x87_push(3.3219280948873623);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fld_const);
return 0; return 0;
} }
@@ -482,7 +482,7 @@ static int opFLDL2E(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push(1.4426950408889634); x87_push(1.4426950408889634);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fld_const);
return 0; return 0;
} }
@@ -491,7 +491,7 @@ static int opFLDPI(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push(3.141592653589793); x87_push(3.141592653589793);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fld_const);
return 0; return 0;
} }
@@ -500,7 +500,7 @@ static int opFLDEG2(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push(0.3010299956639812); x87_push(0.3010299956639812);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fld_const);
return 0; return 0;
} }
@@ -509,7 +509,7 @@ static int opFLDLN2(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push_u64(0x3fe62e42fefa39f0ull); x87_push_u64(0x3fe62e42fefa39f0ull);
CLOCK_CYCLES(8); CLOCK_CYCLES(x87_timings.fld_const);
return 0; return 0;
} }
@@ -519,7 +519,7 @@ static int opFLDZ(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
x87_push(0.0); x87_push(0.0);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fld_z1);
return 0; return 0;
} }
@@ -529,7 +529,7 @@ static int opF2XM1(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = pow(2.0, ST(0)) - 1.0; ST(0) = pow(2.0, ST(0)) - 1.0;
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(200); CLOCK_CYCLES(x87_timings.f2xm1);
return 0; return 0;
} }
@@ -540,7 +540,7 @@ static int opFYL2X(uint32_t fetchdat)
ST(1) = ST(1) * (log(ST(0)) / log(2.0)); ST(1) = ST(1) * (log(ST(0)) / log(2.0));
FP_TAG_VALID_N; FP_TAG_VALID_N;
x87_pop(); x87_pop();
CLOCK_CYCLES(250); CLOCK_CYCLES(x87_timings.fyl2x);
return 0; return 0;
} }
@@ -551,7 +551,7 @@ static int opFYL2XP1(uint32_t fetchdat)
ST(1) = ST(1) * (log1p(ST(0)) / log(2.0)); ST(1) = ST(1) * (log1p(ST(0)) / log(2.0));
FP_TAG_VALID_N; FP_TAG_VALID_N;
x87_pop(); x87_pop();
CLOCK_CYCLES(250); CLOCK_CYCLES(x87_timings.fyl2xp1);
return 0; return 0;
} }
@@ -563,7 +563,7 @@ static int opFPTAN(uint32_t fetchdat)
FP_TAG_VALID; FP_TAG_VALID;
x87_push(1.0); x87_push(1.0);
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(235); CLOCK_CYCLES(x87_timings.fptan);
return 0; return 0;
} }
@@ -574,7 +574,7 @@ static int opFPATAN(uint32_t fetchdat)
ST(1) = atan2(ST(1), ST(0)); ST(1) = atan2(ST(1), ST(0));
FP_TAG_VALID_N; FP_TAG_VALID_N;
x87_pop(); x87_pop();
CLOCK_CYCLES(250); CLOCK_CYCLES(x87_timings.fpatan);
return 0; return 0;
} }
@@ -587,7 +587,7 @@ static int opFDECSTP(uint32_t fetchdat)
#else #else
cpu_state.TOP = (cpu_state.TOP - 1) & 7; cpu_state.TOP = (cpu_state.TOP - 1) & 7;
#endif #endif
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fincdecstp);
return 0; return 0;
} }
@@ -600,7 +600,7 @@ static int opFINCSTP(uint32_t fetchdat)
#else #else
cpu_state.TOP = (cpu_state.TOP + 1) & 7; cpu_state.TOP = (cpu_state.TOP + 1) & 7;
#endif #endif
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fincdecstp);
return 0; return 0;
} }
@@ -616,7 +616,7 @@ static int opFPREM(uint32_t fetchdat)
if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3; if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1; if (temp64 & 1) cpu_state.npxs|=C1;
CLOCK_CYCLES(100); CLOCK_CYCLES(x87_timings.fprem);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -632,7 +632,7 @@ static int opFPREM1(uint32_t fetchdat)
if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3; if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1; if (temp64 & 1) cpu_state.npxs|=C1;
CLOCK_CYCLES(100); CLOCK_CYCLES(x87_timings.fprem1);
return 0; return 0;
} }
#endif #endif
@@ -643,7 +643,7 @@ static int opFSQRT(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = sqrt(ST(0)); ST(0) = sqrt(ST(0));
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(83); CLOCK_CYCLES(x87_timings.fsqrt);
return 0; return 0;
} }
@@ -658,7 +658,7 @@ static int opFSINCOS(uint32_t fetchdat)
FP_TAG_VALID; FP_TAG_VALID;
x87_push(cos(td)); x87_push(cos(td));
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(330); CLOCK_CYCLES(x87_timings.fsincos);
return 0; return 0;
} }
#endif #endif
@@ -669,7 +669,7 @@ static int opFRNDINT(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
ST(0) = (double)x87_fround(ST(0)); ST(0) = (double)x87_fround(ST(0));
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(21); CLOCK_CYCLES(x87_timings.frndint);
return 0; return 0;
} }
@@ -681,7 +681,7 @@ static int opFSCALE(uint32_t fetchdat)
temp64 = (int64_t)ST(1); temp64 = (int64_t)ST(1);
ST(0) = ST(0) * pow(2.0, (double)temp64); ST(0) = ST(0) * pow(2.0, (double)temp64);
FP_TAG_VALID; FP_TAG_VALID;
CLOCK_CYCLES(30); CLOCK_CYCLES(x87_timings.fscale);
return 0; return 0;
} }
@@ -693,7 +693,7 @@ static int opFSIN(uint32_t fetchdat)
ST(0) = sin(ST(0)); ST(0) = sin(ST(0));
FP_TAG_VALID; FP_TAG_VALID;
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(300); CLOCK_CYCLES(x87_timings.fsin_cos);
return 0; return 0;
} }
@@ -704,7 +704,7 @@ static int opFCOS(uint32_t fetchdat)
ST(0) = cos(ST(0)); ST(0) = cos(ST(0));
FP_TAG_VALID; FP_TAG_VALID;
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(300); CLOCK_CYCLES(x87_timings.fsin_cos);
return 0; return 0;
} }
#endif #endif
@@ -732,7 +732,7 @@ static int FLDENV()
cpu_state.TOP = (cpu_state.npxs >> 11) & 7; cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
break; break;
} }
CLOCK_CYCLES((cr0 & 1) ? 34 : 44); CLOCK_CYCLES(x87_timings.fldenv);
return cpu_state.abrt; return cpu_state.abrt;
} }
@@ -765,7 +765,7 @@ static int opFLDCW_a16(uint32_t fetchdat)
if (cpu_state.abrt) return 1; if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw; cpu_state.npxc = tempw;
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fldcw);
return 0; return 0;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -779,7 +779,7 @@ static int opFLDCW_a32(uint32_t fetchdat)
if (cpu_state.abrt) return 1; if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw; cpu_state.npxc = tempw;
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
CLOCK_CYCLES(4); CLOCK_CYCLES(x87_timings.fldcw);
return 0; return 0;
} }
#endif #endif
@@ -823,7 +823,7 @@ static int FSTENV()
writememl(easeg,cpu_state.eaaddr+24,x87_op_seg); writememl(easeg,cpu_state.eaaddr+24,x87_op_seg);
break; break;
} }
CLOCK_CYCLES((cr0 & 1) ? 56 : 67); CLOCK_CYCLES(x87_timings.fstenv);
return cpu_state.abrt; return cpu_state.abrt;
} }
@@ -852,7 +852,7 @@ static int opFSTCW_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat); fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(cpu_state.npxc); seteaw(cpu_state.npxc);
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt; return cpu_state.abrt;
} }
#ifndef FPU_8087 #ifndef FPU_8087
@@ -862,7 +862,7 @@ static int opFSTCW_a32(uint32_t fetchdat)
fetch_ea_32(fetchdat); fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(cpu_state.npxc); seteaw(cpu_state.npxc);
CLOCK_CYCLES(3); CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt; return cpu_state.abrt;
} }
#endif #endif

315
src/cpu/x87_timings.c Normal file
View File

@@ -0,0 +1,315 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/machine.h>
#include "x87_timings.h"
x87_timings_t x87_timings;
const x87_timings_t x87_timings_8087 =
{
.f2xm1 = (310 + 630) / 2,
.fabs = (10 + 17) / 2,
.fadd = (70 + 100) / 2,
.fadd_32 = (90 + 120) / 2,
.fadd_64 = (95 + 125) / 2,
.fbld = (290 + 310) / 2,
.fbstp = (520 + 540) / 2,
.fchs = (10 + 17) / 2,
.fclex = (2 + 8) / 2,
.fcom = (40 + 50) / 2,
.fcom_32 = (60 + 70) / 2,
.fcom_64 = (65 + 75) / 2,
.fcos = 0, /*387+*/
.fincdecstp = (6 + 12) / 2,
.fdisi_eni = (6 + 12) / 2,
.fdiv = (193 + 203) / 2,
.fdiv_32 = (215 + 225) / 2,
.fdiv_64 = (220 + 230) / 2,
.ffree = (9 + 16) / 2,
.fadd_i16 = (102 + 137) / 2,
.fadd_i32 = (108 + 143) / 2,
.fcom_i16 = (72 + 86) / 2,
.fcom_i32 = (78 + 91) / 2,
.fdiv_i16 = (224 + 238) / 2,
.fdiv_i32 = (230 + 243) / 2,
.fild_16 = (46 + 54) / 2,
.fild_32 = (50 + 60) / 2,
.fild_64 = (60 + 68) / 2,
.fmul_i16 = (124 + 138) / 2,
.fmul_i32 = (130 + 144) / 2,
.finit = (2 + 8) / 2,
.fist_16 = (80 + 90) / 2,
.fist_32 = (82 + 92) / 2,
.fist_64 = (94 + 105) / 2,
.fld = (17 + 22) / 2,
.fld_32 = (38 + 56) / 2,
.fld_64 = (40 + 60) / 2,
.fld_80 = (53 + 65) / 2,
.fld_z1 = (11 + 21) / 2,
.fld_const = (15 + 24) / 2,
.fldcw = (7 + 14) / 2,
.fldenv = (35 + 45) / 2,
.fmul = (90 + 145) / 2,
.fmul_32 = (110 + 125) / 2,
.fmul_64 = (154 + 168) / 2,
.fnop = (10 + 16) / 2,
.fpatan = (250 + 800) / 2,
.fprem = (15 + 190) / 2,
.fprem1 = 0, /*387+*/
.fptan = (30 + 540) / 2,
.frndint = (16 + 50) / 2,
.frstor = (197 + 207) / 2,
.fsave = (197 + 207) / 2,
.fscale = (32 + 38) / 2,
.fsetpm = 0, /*287+*/
.fsin_cos = 0, /*387+*/
.fsincos = 0, /*387+*/
.fsqrt = (180 + 186) / 2,
.fst = (15 + 22) / 2,
.fst_32 = (84 + 90) / 2,
.fst_64 = (96 + 104) / 2,
.fst_80 = (52 + 58) / 2,
.fstcw_sw = (12 + 18) / 2,
.fstenv = (40 + 50) / 2,
.ftst = (38 + 48) / 2,
.fucom = 0, /*387+*/
.fwait = 4,
.fxam = (12 + 23) / 2,
.fxch = (10 + 15) / 2,
.fxtract = (27 + 55) / 2,
.fyl2x = (900 + 1100) / 2,
.fyl2xp1 = (700 + 1000) / 2
};
/*Mostly the same as 8087*/
const x87_timings_t x87_timings_287 =
{
.f2xm1 = (310 + 630) / 2,
.fabs = (10 + 17) / 2,
.fadd = (70 + 100) / 2,
.fadd_32 = (90 + 120) / 2,
.fadd_64 = (95 + 125) / 2,
.fbld = (290 + 310) / 2,
.fbstp = (520 + 540) / 2,
.fchs = (10 + 17) / 2,
.fclex = (2 + 8) / 2,
.fcom = (40 + 50) / 2,
.fcom_32 = (60 + 70) / 2,
.fcom_64 = (65 + 75) / 2,
.fcos = 0, /*387+*/
.fincdecstp = (6 + 12) / 2,
.fdisi_eni = 2,
.fdiv = (193 + 203) / 2,
.fdiv_32 = (215 + 225) / 2,
.fdiv_64 = (220 + 230) / 2,
.ffree = (9 + 16) / 2,
.fadd_i16 = (102 + 137) / 2,
.fadd_i32 = (108 + 143) / 2,
.fcom_i16 = (72 + 86) / 2,
.fcom_i32 = (78 + 91) / 2,
.fdiv_i16 = (224 + 238) / 2,
.fdiv_i32 = (230 + 243) / 2,
.fild_16 = (46 + 54) / 2,
.fild_32 = (50 + 60) / 2,
.fild_64 = (60 + 68) / 2,
.fmul_i16 = (124 + 138) / 2,
.fmul_i32 = (130 + 144) / 2,
.finit = (2 + 8) / 2,
.fist_16 = (80 + 90) / 2,
.fist_32 = (82 + 92) / 2,
.fist_64 = (94 + 105) / 2,
.fld = (17 + 22) / 2,
.fld_32 = (38 + 56) / 2,
.fld_64 = (40 + 60) / 2,
.fld_80 = (53 + 65) / 2,
.fld_z1 = (11 + 21) / 2,
.fld_const = (15 + 24) / 2,
.fldcw = (7 + 14) / 2,
.fldenv = (35 + 45) / 2,
.fmul = (90 + 145) / 2,
.fmul_32 = (110 + 125) / 2,
.fmul_64 = (154 + 168) / 2,
.fnop = (10 + 16) / 2,
.fpatan = (250 + 800) / 2,
.fprem = (15 + 190) / 2,
.fprem1 = 0, /*387+*/
.fptan = (30 + 540) / 2,
.frndint = (16 + 50) / 2,
.frstor = (197 + 207) / 2,
.fsave = (197 + 207) / 2,
.fscale = (32 + 38) / 2,
.fsetpm = (2 + 8) / 2, /*287+*/
.fsin_cos = 0, /*387+*/
.fsincos = 0, /*387+*/
.fsqrt = (180 + 186) / 2,
.fst = (15 + 22) / 2,
.fst_32 = (84 + 90) / 2,
.fst_64 = (96 + 104) / 2,
.fst_80 = (52 + 58) / 2,
.fstcw_sw = (12 + 18) / 2,
.fstenv = (40 + 50) / 2,
.ftst = (38 + 48) / 2,
.fucom = 0, /*387+*/
.fwait = 3,
.fxam = (12 + 23) / 2,
.fxch = (10 + 15) / 2,
.fxtract = (27 + 55) / 2,
.fyl2x = (900 + 1100) / 2,
.fyl2xp1 = (700 + 1000) / 2
};
const x87_timings_t x87_timings_387 =
{
.f2xm1 = (211 + 476) / 2,
.fabs = 22,
.fadd = (23 + 34) / 2,
.fadd_32 = (24 + 32) / 2,
.fadd_64 = (29 + 37) / 2,
.fbld = (266 + 275) / 2,
.fbstp = (512 + 534) / 2,
.fchs = (24 + 25) / 2,
.fclex = 11,
.fcom = 24,
.fcom_32 = 26,
.fcom_64 = 31,
.fcos = (122 + 772) / 2,
.fincdecstp = 22,
.fdisi_eni = 2,
.fdiv = (88 + 91) / 2,
.fdiv_32 = 89,
.fdiv_64 = 94,
.ffree = 18,
.fadd_i16 = (71 + 85) / 2,
.fadd_i32 = (57 + 72) / 2,
.fcom_i16 = (71 + 75) / 2,
.fcom_i32 = (56 + 63) / 2,
.fdiv_i16 = (136 + 140) / 2,
.fdiv_i32 = (120 + 127) / 2,
.fild_16 = (61 + 65) / 2,
.fild_32 = (45 + 52) / 2,
.fild_64 = (56 + 67) / 2,
.fmul_i16 = (76 + 87) / 2,
.fmul_i32 = (61 + 82) / 2,
.finit = 33,
.fist_16 = (82 + 95) / 2,
.fist_32 = (79 + 93) / 2,
.fist_64 = (80 + 97) / 2,
.fld = 14,
.fld_32 = 20,
.fld_64 = 25,
.fld_80 = 44,
.fld_z1 = (20 + 24) / 2,
.fld_const = 40,
.fldcw = 19,
.fldenv = 71,
.fmul = (29 + 57) / 2,
.fmul_32 = (27 + 35) / 2,
.fmul_64 = (32 + 57) / 2,
.fnop = 12,
.fpatan = (314 + 487) / 2,
.fprem = (74 + 155) / 2,
.fprem1 = (95 + 185) / 2,
.fptan = (191 + 497) / 2,
.frndint = (66 + 80) / 2,
.frstor = 308,
.fsave = 375,
.fscale = (67 + 86) / 2,
.fsetpm = 12,
.fsin_cos = (122 + 771) / 2,
.fsincos = (194 + 809) / 2,
.fsqrt = (122 + 129) / 2,
.fst = 11,
.fst_32 = 44,
.fst_64 = 45,
.fst_80 = 53,
.fstcw_sw = 15,
.fstenv = 103,
.ftst = 28,
.fucom = 24,
.fwait = 6,
.fxam = (30 + 38) / 2,
.fxch = 18,
.fxtract = (70 + 76) / 2,
.fyl2x = (120 + 538) / 2,
.fyl2xp1 = (257 + 547) / 2
};
const x87_timings_t x87_timings_486 =
{
.f2xm1 = (140 + 270) / 2,
.fabs = 3,
.fadd = (8 + 20) / 2,
.fadd_32 = (8 + 20) / 2,
.fadd_64 = (8 + 20) / 2,
.fbld = (70 + 103) / 2,
.fbstp = (172 + 176) / 2,
.fchs = 6,
.fclex = 7,
.fcom = 4,
.fcom_32 = 4,
.fcom_64 = 4,
.fcos = (257 + 354) / 2,
.fincdecstp = 3,
.fdisi_eni = 3,
.fdiv = 73,
.fdiv_32 = 73,
.fdiv_64 = 73,
.ffree = 3,
.fadd_i16 = (20 + 35) / 2,
.fadd_i32 = (19 + 32) / 2,
.fcom_i16 = (16 + 20) / 2,
.fcom_i32 = (15 + 17) / 2,
.fdiv_i16 = (85 + 89) / 2,
.fdiv_i32 = (84 + 86) / 2,
.fild_16 = (13 + 16) / 2,
.fild_32 = (9 + 12) / 2,
.fild_64 = (10 + 18) / 2,
.fmul_i16 = (23 + 27) / 2,
.fmul_i32 = (22 + 24) / 2,
.finit = 17,
.fist_16 = (29 + 34) / 2,
.fist_32 = (28 + 34) / 2,
.fist_64 = (29 + 34) / 2,
.fld = 4,
.fld_32 = 3,
.fld_64 = 3,
.fld_80 = 6,
.fld_z1 = 4,
.fld_const = 8,
.fldcw = 4,
.fldenv = 34,
.fmul = 16,
.fmul_32 = 11,
.fmul_64 = 14,
.fnop = 3,
.fpatan = (218 + 303) / 2,
.fprem = (70 + 138) / 2,
.fprem1 = (72 + 167) / 2,
.fptan = (200 + 273) / 2,
.frndint = (21 + 30) / 2,
.frstor = 120,
.fsave = 143,
.fscale = (30 + 32) / 2,
.fsetpm = 3,
.fsin_cos = (257 + 354) / 2,
.fsincos = (292 + 365) / 2,
.fsqrt = (83 + 87) / 2,
.fst = 3,
.fst_32 = 7,
.fst_64 = 8,
.fst_80 = 6,
.fstcw_sw = 3,
.fstenv = 56,
.ftst = 4,
.fucom = 4,
.fwait = (1 + 3) / 2,
.fxam = 8,
.fxch = 4,
.fxtract = (16 + 20) / 2,
.fyl2x = (196 + 329) / 2,
.fyl2xp1 = (171 + 326) / 2
};

56
src/cpu/x87_timings.h Normal file
View File

@@ -0,0 +1,56 @@
typedef struct
{
int f2xm1;
int fabs;
int fadd, fadd_32, fadd_64;
int fbld;
int fbstp;
int fchs;
int fclex;
int fcom, fcom_32, fcom_64;
int fcos;
int fincdecstp;
int fdisi_eni;
int fdiv, fdiv_32, fdiv_64;
int ffree;
int fadd_i16, fadd_i32;
int fcom_i16, fcom_i32;
int fdiv_i16, fdiv_i32;
int fild_16, fild_32, fild_64;
int fmul_i16, fmul_i32;
int finit;
int fist_16, fist_32, fist_64;
int fld, fld_32, fld_64, fld_80;
int fld_z1, fld_const;
int fldcw;
int fldenv;
int fmul, fmul_32, fmul_64;
int fnop;
int fpatan;
int fprem, fprem1;
int fptan;
int frndint;
int frstor;
int fsave;
int fscale;
int fsetpm;
int fsin_cos, fsincos;
int fsqrt;
int fst, fst_32, fst_64, fst_80;
int fstcw_sw;
int fstenv;
int ftst;
int fucom;
int fwait;
int fxam;
int fxch;
int fxtract;
int fyl2x, fyl2xp1;
} x87_timings_t;
extern const x87_timings_t x87_timings_8087;
extern const x87_timings_t x87_timings_287;
extern const x87_timings_t x87_timings_387;
extern const x87_timings_t x87_timings_486;
extern x87_timings_t x87_timings;

View File

@@ -370,8 +370,6 @@ BEGIN
12,12 12,12
LTEXT "MB",IDT_1705,123,64,10,10 LTEXT "MB",IDT_1705,123,64,10,10
LTEXT "Memory:",IDT_1706,7,64,30,10 LTEXT "Memory:",IDT_1706,7,64,30,10
CONTROL "Enable FPU",IDC_CHECK_FPU,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,7,81,113,10
GROUPBOX "Time synchronization",IDC_TIME_SYNC,7,96,100,56 GROUPBOX "Time synchronization",IDC_TIME_SYNC,7,96,100,56
CONTROL "Disabled",IDC_RADIO_TS_DISABLED,"Button", CONTROL "Disabled",IDC_RADIO_TS_DISABLED,"Button",
BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,14,108,84,10 BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,14,108,84,10

View File

@@ -556,7 +556,7 @@ MEMOBJ := intel_flash.o mem.o rom.o spd.o sst_flash.o
CPUOBJ := cpu.o cpu_table.o \ CPUOBJ := cpu.o cpu_table.o \
808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o $(CGTOBJ) \ 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o $(CGTOBJ) \
x86seg.o x87.o \ x86seg.o x87.o x87_timings.o \
$(DYNARECOBJ) $(DYNARECOBJ)
CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \ CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \