diff --git a/src/cpu.c b/src/cpu.c index 07e46b0..7d6c1a2 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -6,6 +6,7 @@ #include "mem.h" #include "pci.h" #include "codegen.h" +#include "x87_timings.h" int fpu_type; uint32_t cpu_features; @@ -1007,6 +1008,29 @@ void cpu_set() 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() diff --git a/src/cpu.h b/src/cpu.h index 1cb4cf8..69d7cc5 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -66,6 +66,7 @@ enum FPU_NONE, FPU_8087, FPU_287, + FPU_287XL, FPU_387, FPU_BUILTIN }; diff --git a/src/cpu_tables.c b/src/cpu_tables.c index 84863d4..aa19596 100644 --- a/src/cpu_tables.c +++ b/src/cpu_tables.c @@ -35,8 +35,9 @@ FPU fpus_8088[] = }; FPU fpus_80286[] = { - {"None", "none", FPU_NONE}, - {"287", "287", FPU_287}, + {"None", "none", FPU_NONE}, + {"287", "287", FPU_287}, + {"287XL", "287xl", FPU_287XL}, {NULL, NULL, 0} }; FPU fpus_80386[] = diff --git a/src/x87_ops.h b/src/x87_ops.h index 53ffc23..225d56c 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -1,5 +1,6 @@ #include #include +#include "x87_timings.h" #define fplog 0 diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h index f52abe8..cf8d1ae 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -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) \ { \ optype t; \ @@ -12,7 +12,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ if ((cpu_state.npxc >> 10) & 3) \ fesetround(FE_TONEAREST); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ - CLOCK_CYCLES(8); \ + CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \ return 0; \ } \ 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; \ cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ - CLOCK_CYCLES(4); \ + CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \ return 0; \ } \ 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 |= x87_compare(ST(0), (double)use_var); \ x87_pop(); \ - CLOCK_CYCLES(4); \ + CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \ return 0; \ } \ 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; \ x87_div(ST(0), ST(0), use_var); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ - CLOCK_CYCLES(73); \ + CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \ return 0; \ } \ 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; \ x87_div(ST(0), use_var, ST(0)); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ - CLOCK_CYCLES(73); \ + CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \ return 0; \ } \ 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; \ ST(0) *= use_var; \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ - CLOCK_CYCLES(11); \ + CLOCK_CYCLES(x87_timings.fmul ## cycle_postfix); \ return 0; \ } \ 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; \ ST(0) -= use_var; \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ - CLOCK_CYCLES(8); \ + CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \ return 0; \ } \ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ @@ -97,20 +97,20 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) = use_var - ST(0); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ - CLOCK_CYCLES(8); \ + CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \ return 0; \ } -opFPU(s, x87_ts, 16, t.i, geteal, t.s) -opFPU(s, x87_ts, 32, t.i, geteal, t.s) -opFPU(d, x87_td, 16, t.i, geteaq, t.d) -opFPU(d, x87_td, 32, t.i, geteaq, t.d) +opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32) +opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) +opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64) +opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) -opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t) -opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t) -opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t) -opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t) +opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t, _i16) +opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t, _i16) +opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t, _i32) +opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t, _i32) @@ -122,7 +122,7 @@ static int opFADD(uint32_t fetchdat) if (fplog) pclog("FADD\n"); ST(0) = ST(0) + ST(fetchdat & 7); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFADDr(uint32_t fetchdat) @@ -132,7 +132,7 @@ static int opFADDr(uint32_t fetchdat) if (fplog) pclog("FADD\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFADDP(uint32_t fetchdat) @@ -143,7 +143,7 @@ static int opFADDP(uint32_t fetchdat) ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } @@ -155,7 +155,7 @@ static int opFCOM(uint32_t fetchdat) cpu_state.npxs &= ~(C0|C2|C3); if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3; else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fadd); return 0; } @@ -167,7 +167,7 @@ static int opFCOMP(uint32_t fetchdat) cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); x87_pop(); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fadd); return 0; } @@ -184,7 +184,7 @@ static int opFCOMPP(uint32_t fetchdat) x87_pop(); x87_pop(); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFUCOMPP(uint32_t fetchdat) @@ -196,7 +196,7 @@ static int opFUCOMPP(uint32_t fetchdat) cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); x87_pop(); x87_pop(); - CLOCK_CYCLES(5); + CLOCK_CYCLES(x87_timings.fucom); return 0; } @@ -209,7 +209,7 @@ static int opFCOMI(uint32_t fetchdat) cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fcom); return 0; } static int opFCOMIP(uint32_t fetchdat) @@ -222,7 +222,7 @@ static int opFCOMIP(uint32_t fetchdat) if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; x87_pop(); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fcom); return 0; } @@ -233,7 +233,7 @@ static int opFDIV(uint32_t fetchdat) if (fplog) pclog("FDIV\n"); x87_div(ST(0), ST(0), ST(fetchdat & 7)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(73); + CLOCK_CYCLES(x87_timings.fdiv); return 0; } static int opFDIVr(uint32_t fetchdat) @@ -243,7 +243,7 @@ static int opFDIVr(uint32_t fetchdat) if (fplog) pclog("FDIV\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; - CLOCK_CYCLES(73); + CLOCK_CYCLES(x87_timings.fdiv); return 0; } static int opFDIVP(uint32_t fetchdat) @@ -254,7 +254,7 @@ static int opFDIVP(uint32_t fetchdat) x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(73); + CLOCK_CYCLES(x87_timings.fdiv); return 0; } @@ -265,7 +265,7 @@ static int opFDIVR(uint32_t fetchdat) if (fplog) pclog("FDIVR\n"); x87_div(ST(0), ST(fetchdat&7), ST(0)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(73); + CLOCK_CYCLES(x87_timings.fdiv); return 0; } static int opFDIVRr(uint32_t fetchdat) @@ -275,7 +275,7 @@ static int opFDIVRr(uint32_t fetchdat) if (fplog) pclog("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; - CLOCK_CYCLES(73); + CLOCK_CYCLES(x87_timings.fdiv); return 0; } static int opFDIVRP(uint32_t fetchdat) @@ -286,7 +286,7 @@ static int opFDIVRP(uint32_t fetchdat) x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(73); + CLOCK_CYCLES(x87_timings.fdiv); return 0; } @@ -297,7 +297,7 @@ static int opFMUL(uint32_t fetchdat) if (fplog) pclog("FMUL\n"); ST(0) = ST(0) * ST(fetchdat & 7); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(16); + CLOCK_CYCLES(x87_timings.fmul); return 0; } static int opFMULr(uint32_t fetchdat) @@ -307,7 +307,7 @@ static int opFMULr(uint32_t fetchdat) if (fplog) pclog("FMUL\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; - CLOCK_CYCLES(16); + CLOCK_CYCLES(x87_timings.fmul); return 0; } static int opFMULP(uint32_t fetchdat) @@ -318,7 +318,7 @@ static int opFMULP(uint32_t fetchdat) ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(16); + CLOCK_CYCLES(x87_timings.fmul); return 0; } @@ -329,7 +329,7 @@ static int opFSUB(uint32_t fetchdat) if (fplog) pclog("FSUB\n"); ST(0) = ST(0) - ST(fetchdat & 7); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFSUBr(uint32_t fetchdat) @@ -339,7 +339,7 @@ static int opFSUBr(uint32_t fetchdat) if (fplog) pclog("FSUB\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFSUBP(uint32_t fetchdat) @@ -350,7 +350,7 @@ static int opFSUBP(uint32_t fetchdat) ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } @@ -361,7 +361,7 @@ static int opFSUBR(uint32_t fetchdat) if (fplog) pclog("FSUBR\n"); ST(0) = ST(fetchdat & 7) - ST(0); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFSUBRr(uint32_t fetchdat) @@ -371,7 +371,7 @@ static int opFSUBRr(uint32_t fetchdat) if (fplog) pclog("FSUBR\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } static int opFSUBRP(uint32_t fetchdat) @@ -382,7 +382,7 @@ static int opFSUBRP(uint32_t fetchdat) ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fadd); return 0; } @@ -393,7 +393,7 @@ static int opFUCOM(uint32_t fetchdat) if (fplog) pclog("FUCOM\n"); cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fucom); return 0; } @@ -405,7 +405,7 @@ static int opFUCOMP(uint32_t fetchdat) cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); x87_pop(); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fucom); return 0; } @@ -418,7 +418,7 @@ static int opFUCOMI(uint32_t fetchdat) cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG); if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fucom); return 0; } static int opFUCOMIP(uint32_t fetchdat) @@ -431,6 +431,6 @@ static int opFUCOMIP(uint32_t fetchdat) if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG; else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG; x87_pop(); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fucom); return 0; } diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h index 96c18e6..6c61b7f 100644 --- a/src/x87_ops_loadstore.h +++ b/src/x87_ops_loadstore.h @@ -8,7 +8,7 @@ static int opFILDiw_a16(uint32_t fetchdat) temp = geteaw(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", (double)temp); x87_push((double)temp); - CLOCK_CYCLES(13); + CLOCK_CYCLES(x87_timings.fild_16); return 0; } static int opFILDiw_a32(uint32_t fetchdat) @@ -21,7 +21,7 @@ static int opFILDiw_a32(uint32_t fetchdat) temp = geteaw(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", (double)temp); x87_push((double)temp); - CLOCK_CYCLES(13); + CLOCK_CYCLES(x87_timings.fild_16); return 0; } @@ -36,7 +36,7 @@ static int opFISTiw_a16(uint32_t fetchdat) /* if (temp64 > 32767 || temp64 < -32768) fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); - CLOCK_CYCLES(29); + CLOCK_CYCLES(x87_timings.fist_16); return cpu_state.abrt; } static int opFISTiw_a32(uint32_t fetchdat) @@ -50,7 +50,7 @@ static int opFISTiw_a32(uint32_t fetchdat) /* if (temp64 > 32767 || temp64 < -32768) fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); - CLOCK_CYCLES(29); + CLOCK_CYCLES(x87_timings.fist_16); return cpu_state.abrt; } @@ -66,7 +66,7 @@ static int opFISTPiw_a16(uint32_t fetchdat) fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(29); + CLOCK_CYCLES(x87_timings.fist_16); return 0; } static int opFISTPiw_a32(uint32_t fetchdat) @@ -81,7 +81,7 @@ static int opFISTPiw_a32(uint32_t fetchdat) fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(29); + CLOCK_CYCLES(x87_timings.fist_16); return 0; } @@ -98,7 +98,7 @@ static int opFILDiq_a16(uint32_t fetchdat) cpu_state.MM[cpu_state.TOP&7].q = temp64; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; - CLOCK_CYCLES(10); + CLOCK_CYCLES(x87_timings.fild_64); return 0; } static int opFILDiq_a32(uint32_t fetchdat) @@ -114,7 +114,7 @@ static int opFILDiq_a32(uint32_t fetchdat) cpu_state.MM[cpu_state.TOP&7].q = temp64; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; - CLOCK_CYCLES(10); + CLOCK_CYCLES(x87_timings.fild_64); return 0; } @@ -143,6 +143,7 @@ static int FBSTP_a16(uint32_t fetchdat) if (ST(0) < 0.0) tempc |= 0x80; writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1; x87_pop(); + CLOCK_CYCLES(x87_timings.fbstp); return 0; } static int FBSTP_a32(uint32_t fetchdat) @@ -170,6 +171,7 @@ static int FBSTP_a32(uint32_t fetchdat) if (ST(0) < 0.0) tempc |= 0x80; writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1; x87_pop(); + CLOCK_CYCLES(x87_timings.fbstp); return 0; } @@ -186,7 +188,7 @@ static int FISTPiq_a16(uint32_t fetchdat) temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(29); + CLOCK_CYCLES(x87_timings.fist_64); return 0; } static int FISTPiq_a32(uint32_t fetchdat) @@ -202,7 +204,7 @@ static int FISTPiq_a32(uint32_t fetchdat) temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(29); + CLOCK_CYCLES(x87_timings.fist_64); return 0; } @@ -216,7 +218,7 @@ static int opFILDil_a16(uint32_t fetchdat) templ = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); x87_push((double)templ); - CLOCK_CYCLES(9); + CLOCK_CYCLES(x87_timings.fild_32); return 0; } static int opFILDil_a32(uint32_t fetchdat) @@ -229,7 +231,7 @@ static int opFILDil_a32(uint32_t fetchdat) templ = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); x87_push((double)templ); - CLOCK_CYCLES(9); + CLOCK_CYCLES(x87_timings.fild_32); return 0; } @@ -244,7 +246,7 @@ static int opFISTil_a16(uint32_t fetchdat) /* if (temp64 > 2147483647 || temp64 < -2147483647) fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); - CLOCK_CYCLES(28); + CLOCK_CYCLES(x87_timings.fist_32); return cpu_state.abrt; } static int opFISTil_a32(uint32_t fetchdat) @@ -258,7 +260,7 @@ static int opFISTil_a32(uint32_t fetchdat) /* if (temp64 > 2147483647 || temp64 < -2147483647) fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); - CLOCK_CYCLES(28); + CLOCK_CYCLES(x87_timings.fist_32); return cpu_state.abrt; } @@ -274,7 +276,7 @@ static int opFISTPil_a16(uint32_t fetchdat) fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(28); + CLOCK_CYCLES(x87_timings.fist_32); return 0; } static int opFISTPil_a32(uint32_t fetchdat) @@ -289,7 +291,7 @@ static int opFISTPil_a32(uint32_t fetchdat) fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(28); + CLOCK_CYCLES(x87_timings.fist_32); return 0; } @@ -303,7 +305,7 @@ static int opFLDe_a16(uint32_t fetchdat) t=x87_ld80(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t); x87_push(t); - CLOCK_CYCLES(6); + CLOCK_CYCLES(x87_timings.fld_80); return 0; } static int opFLDe_a32(uint32_t fetchdat) @@ -316,7 +318,7 @@ static int opFLDe_a32(uint32_t fetchdat) t=x87_ld80(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t); x87_push(t); - CLOCK_CYCLES(6); + CLOCK_CYCLES(x87_timings.fld_80); return 0; } @@ -328,7 +330,7 @@ static int opFSTPe_a16(uint32_t fetchdat) if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(6); + CLOCK_CYCLES(x87_timings.fst_80); return 0; } static int opFSTPe_a32(uint32_t fetchdat) @@ -339,7 +341,7 @@ static int opFSTPe_a32(uint32_t fetchdat) if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(6); + CLOCK_CYCLES(x87_timings.fst_80); return 0; } @@ -353,7 +355,7 @@ static int opFLDd_a16(uint32_t fetchdat) t.i = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t.d); x87_push(t.d); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fld_64); return 0; } static int opFLDd_a32(uint32_t fetchdat) @@ -366,7 +368,7 @@ static int opFLDd_a32(uint32_t fetchdat) t.i = geteaq(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", t.d); x87_push(t.d); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fld_64); return 0; } @@ -379,7 +381,7 @@ static int opFSTd_a16(uint32_t fetchdat) if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fst_64); return cpu_state.abrt; } static int opFSTd_a32(uint32_t fetchdat) @@ -391,7 +393,7 @@ static int opFSTd_a32(uint32_t fetchdat) if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fst_64); return cpu_state.abrt; } @@ -406,7 +408,7 @@ static int opFSTPd_a16(uint32_t fetchdat) t.d = ST(0); seteaq(t.i); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fst_64); return 0; } static int opFSTPd_a32(uint32_t fetchdat) @@ -420,7 +422,7 @@ static int opFSTPd_a32(uint32_t fetchdat) t.d = ST(0); seteaq(t.i); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fst_64); return 0; } @@ -434,7 +436,7 @@ static int opFLDs_a16(uint32_t fetchdat) ts.i = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", ts.s); x87_push((double)ts.s); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fld_32); return 0; } static int opFLDs_a32(uint32_t fetchdat) @@ -447,7 +449,7 @@ static int opFLDs_a32(uint32_t fetchdat) ts.i = geteal(); if (cpu_state.abrt) return 1; if (fplog) pclog(" %f\n", ts.s); x87_push((double)ts.s); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fld_32); return 0; } @@ -460,7 +462,7 @@ static int opFSTs_a16(uint32_t fetchdat) if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); - CLOCK_CYCLES(7); + CLOCK_CYCLES(x87_timings.fst_32); return cpu_state.abrt; } static int opFSTs_a32(uint32_t fetchdat) @@ -472,7 +474,7 @@ static int opFSTs_a32(uint32_t fetchdat) if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); - CLOCK_CYCLES(7); + CLOCK_CYCLES(x87_timings.fst_32); return cpu_state.abrt; } @@ -486,7 +488,7 @@ static int opFSTPs_a16(uint32_t fetchdat) ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(7); + CLOCK_CYCLES(x87_timings.fst_32); return 0; } static int opFSTPs_a32(uint32_t fetchdat) @@ -499,6 +501,6 @@ static int opFSTPs_a32(uint32_t fetchdat) ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; x87_pop(); - CLOCK_CYCLES(7); + CLOCK_CYCLES(x87_timings.fst_32); return 0; } diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 0cae387..a5fc002 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -4,7 +4,7 @@ static int opFSTSW_AX(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSTSW\n"); AX = cpu_state.npxs; - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fstcw_sw); return 0; } @@ -14,7 +14,7 @@ static int opFNOP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fnop); return 0; } @@ -23,7 +23,7 @@ static int opFCLEX(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; cpu_state.npxs &= 0xff00; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fclex); return 0; } @@ -37,7 +37,7 @@ static int opFINIT(uint32_t fetchdat) *(uint64_t *)cpu_state.tag = 0; cpu_state.TOP = 0; cpu_state.ismmx = 0; - CLOCK_CYCLES(17); + CLOCK_CYCLES(x87_timings.finit); CPU_BLOCK_END(); return 0; } @@ -49,7 +49,7 @@ static int opFFREE(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FFREE\n"); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY; - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.ffree); return 0; } @@ -60,7 +60,7 @@ static int opFST(uint32_t fetchdat) if (fplog) pclog("FST\n"); ST(fetchdat & 7) = ST(0); 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; } @@ -72,7 +72,7 @@ static int opFSTP(uint32_t fetchdat) ST(fetchdat & 7) = ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; x87_pop(); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fst); return 0; } @@ -120,7 +120,7 @@ static int FSTOR() !cpu_state.TOP && (*(uint64_t *)cpu_state.tag == 0x0101010101010101ull)) cpu_state.ismmx = 1; - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES(x87_timings.frstor); if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, cpu_state.eaaddr, cpu_state.ismmx, cpu_state.TOP, x87_gettag()); return cpu_state.abrt; } @@ -283,7 +283,7 @@ static int FSAVE() cpu_state.TOP = 0; cpu_state.ismmx = 0; - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES(x87_timings.fsave); return cpu_state.abrt; } static int opFSAVE_a16(uint32_t fetchdat) @@ -310,7 +310,7 @@ static int opFSTSW_a16(uint32_t fetchdat) SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fstcw_sw); return cpu_state.abrt; } static int opFSTSW_a32(uint32_t fetchdat) @@ -320,7 +320,7 @@ static int opFSTSW_a32(uint32_t fetchdat) SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fstcw_sw); return cpu_state.abrt; } @@ -338,7 +338,7 @@ static int opFLD(uint32_t fetchdat) x87_push(ST(fetchdat&7)); cpu_state.tag[cpu_state.TOP&7] = old_tag; cpu_state.MM[cpu_state.TOP&7].q = old_i64; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fld); return 0; } @@ -360,7 +360,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 + fetchdat) & 7].q = old_i64; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fxch); return 0; } @@ -371,7 +371,7 @@ static int opFCHS(uint32_t fetchdat) if (fplog) pclog("FCHS\n"); ST(0) = -ST(0); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(6); + CLOCK_CYCLES(x87_timings.fchs); return 0; } @@ -382,7 +382,7 @@ static int opFABS(uint32_t fetchdat) if (fplog) pclog("FABS %f\n", ST(0)); ST(0) = fabs(ST(0)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fabs); return 0; } @@ -394,7 +394,7 @@ static int opFTST(uint32_t fetchdat) cpu_state.npxs &= ~(C0|C2|C3); if (ST(0) == 0.0) cpu_state.npxs |= C3; else if (ST(0) < 0.0) cpu_state.npxs |= C0; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.ftst); return 0; } @@ -408,7 +408,7 @@ static int opFXAM(uint32_t fetchdat) else if (ST(0) == 0.0) cpu_state.npxs |= C3; else cpu_state.npxs |= C2; if (ST(0) < 0.0) cpu_state.npxs |= C1; - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fxam); return 0; } @@ -418,7 +418,7 @@ static int opFLD1(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLD1\n"); x87_push(1.0); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fld_z1); return 0; } @@ -428,7 +428,7 @@ static int opFLDL2T(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLDL2T\n"); x87_push(3.3219280948873623); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fld_const); return 0; } @@ -438,7 +438,7 @@ static int opFLDL2E(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLDL2E\n"); x87_push(1.4426950408889634); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fld_const); return 0; } @@ -448,7 +448,7 @@ static int opFLDPI(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLDPI\n"); x87_push(3.141592653589793); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fld_const); return 0; } @@ -458,7 +458,7 @@ static int opFLDEG2(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLDEG2\n"); x87_push(0.3010299956639812); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fld_const); return 0; } @@ -468,7 +468,7 @@ static int opFLDLN2(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FLDLN2\n"); x87_push_u64(0x3fe62e42fefa39f0ull); - CLOCK_CYCLES(8); + CLOCK_CYCLES(x87_timings.fld_const); return 0; } @@ -479,7 +479,7 @@ static int opFLDZ(uint32_t fetchdat) if (fplog) pclog("FLDZ\n"); x87_push(0.0); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fld_z1); return 0; } @@ -490,7 +490,7 @@ static int opF2XM1(uint32_t fetchdat) if (fplog) pclog("F2XM1\n"); ST(0) = pow(2.0, ST(0)) - 1.0; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(200); + CLOCK_CYCLES(x87_timings.f2xm1); return 0; } @@ -502,7 +502,7 @@ static int opFYL2X(uint32_t fetchdat) ST(1) = ST(1) * (log(ST(0)) / log(2.0)); cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(250); + CLOCK_CYCLES(x87_timings.fyl2x); return 0; } @@ -514,7 +514,7 @@ static int opFYL2XP1(uint32_t fetchdat) ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0)); cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(250); + CLOCK_CYCLES(x87_timings.fyl2xp1); return 0; } @@ -527,7 +527,7 @@ static int opFPTAN(uint32_t fetchdat) cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; x87_push(1.0); cpu_state.npxs &= ~C2; - CLOCK_CYCLES(235); + CLOCK_CYCLES(x87_timings.fptan); return 0; } @@ -539,7 +539,7 @@ static int opFPATAN(uint32_t fetchdat) ST(1) = atan2(ST(1), ST(0)); cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; x87_pop(); - CLOCK_CYCLES(250); + CLOCK_CYCLES(x87_timings.fpatan); return 0; } @@ -549,7 +549,7 @@ static int opFDECSTP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDECSTP\n"); cpu_state.TOP--; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fincdecstp); return 0; } @@ -559,7 +559,7 @@ static int opFINCSTP(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FDECSTP\n"); cpu_state.TOP++; - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fincdecstp); return 0; } @@ -577,7 +577,7 @@ static int opFPREM(uint32_t fetchdat) if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; if (temp64 & 1) cpu_state.npxs|=C1; - CLOCK_CYCLES(100); + CLOCK_CYCLES(x87_timings.fprem); return 0; } static int opFPREM1(uint32_t fetchdat) @@ -594,7 +594,7 @@ static int opFPREM1(uint32_t fetchdat) if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; if (temp64 & 1) cpu_state.npxs|=C1; - CLOCK_CYCLES(100); + CLOCK_CYCLES(x87_timings.fprem1); return 0; } @@ -605,7 +605,7 @@ static int opFSQRT(uint32_t fetchdat) if (fplog) pclog("FSQRT\n"); ST(0) = sqrt(ST(0)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(83); + CLOCK_CYCLES(x87_timings.fsqrt); return 0; } @@ -620,7 +620,7 @@ static int opFSINCOS(uint32_t fetchdat) cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; x87_push(cos(td)); cpu_state.npxs &= ~C2; - CLOCK_CYCLES(330); + CLOCK_CYCLES(x87_timings.fsincos); return 0; } @@ -632,7 +632,7 @@ static int opFRNDINT(uint32_t fetchdat) ST(0) = (double)x87_fround(ST(0)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; if (fplog) pclog("%g\n", ST(0)); - CLOCK_CYCLES(21); + CLOCK_CYCLES(x87_timings.frndint); return 0; } @@ -645,7 +645,7 @@ static int opFSCALE(uint32_t fetchdat) temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; - CLOCK_CYCLES(30); + CLOCK_CYCLES(x87_timings.fscale); return 0; } @@ -657,7 +657,7 @@ static int opFSIN(uint32_t fetchdat) ST(0) = sin(ST(0)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; cpu_state.npxs &= ~C2; - CLOCK_CYCLES(300); + CLOCK_CYCLES(x87_timings.fsin_cos); return 0; } @@ -669,7 +669,7 @@ static int opFCOS(uint32_t fetchdat) ST(0) = cos(ST(0)); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; cpu_state.npxs &= ~C2; - CLOCK_CYCLES(300); + CLOCK_CYCLES(x87_timings.fsin_cos); return 0; } @@ -697,7 +697,7 @@ static int FLDENV() cpu_state.TOP = (cpu_state.npxs >> 11) & 7; break; } - CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + CLOCK_CYCLES(x87_timings.fldenv); return cpu_state.abrt; } @@ -729,7 +729,7 @@ static int opFLDCW_a16(uint32_t fetchdat) if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fldcw); return 0; } static int opFLDCW_a32(uint32_t fetchdat) @@ -743,7 +743,7 @@ static int opFLDCW_a32(uint32_t fetchdat) if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); - CLOCK_CYCLES(4); + CLOCK_CYCLES(x87_timings.fldcw); return 0; } @@ -787,7 +787,7 @@ static int FSTENV() writememl(easeg,cpu_state.eaaddr+24,x87_op_seg); break; } - CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + CLOCK_CYCLES(x87_timings.fstenv); return cpu_state.abrt; } @@ -815,7 +815,7 @@ static int opFSTCW_a16(uint32_t fetchdat) SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw(cpu_state.npxc); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fstcw_sw); return cpu_state.abrt; } static int opFSTCW_a32(uint32_t fetchdat) @@ -825,7 +825,7 @@ static int opFSTCW_a32(uint32_t fetchdat) SEG_CHECK_WRITE(cpu_state.ea_seg); if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw(cpu_state.npxc); - CLOCK_CYCLES(3); + CLOCK_CYCLES(x87_timings.fstcw_sw); return cpu_state.abrt; }