Redid the x87 merger, now the x87 interpreter is basically the same across both recompilers, and there's several newly introduced bugs less.

This commit is contained in:
OBattler
2020-04-10 14:07:25 +02:00
parent a60634b3a1
commit f29f6de245
11 changed files with 166 additions and 323 deletions

View File

@@ -27,3 +27,10 @@ void codegen_timing_set(codegen_timing_t *timing)
} }
int codegen_in_recompile; int codegen_in_recompile;
/* This is for compatibility with new x87 code. */
void codegen_set_rounding_mode(int mode)
{
/* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10);
}

View File

@@ -4182,7 +4182,7 @@ static inline void FP_FCHS()
addbyte(0x64); addbyte(0x64);
addbyte(0x05); addbyte(0x05);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/
addbyte(0x0f); addbyte(0x0f);
addbyte(0x11); addbyte(0x11);
@@ -4435,7 +4435,7 @@ static inline void FP_OP_REG(int op, int dst, int src)
addbyte(0x64); addbyte(0x64);
addbyte(0x05); addbyte(0x05);
addbyte((uint8_t)cpu_state_offset(tag)); addbyte((uint8_t)cpu_state_offset(tag));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
if (op == FPU_DIVR || op == FPU_SUBR) if (op == FPU_DIVR || op == FPU_SUBR)
{ {
addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/
@@ -4528,7 +4528,7 @@ static inline void FP_OP_MEM(int op)
addbyte(0x64); addbyte(0x64);
addbyte(0x05); addbyte(0x05);
addbyte((uint8_t)cpu_state_offset(tag)); addbyte((uint8_t)cpu_state_offset(tag));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
switch (op) switch (op)
{ {

View File

@@ -2686,7 +2686,7 @@ static inline void FP_OP_S(int op)
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xd8); /*FADD [ESP]*/ addbyte(0xd8); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2710,7 +2710,7 @@ static inline void FP_OP_S(int op)
addbyte(0x64); addbyte(0x64);
addbyte(0x1d); addbyte(0x1d);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xd8); /*FADD [ESP]*/ addbyte(0xd8); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2743,7 +2743,7 @@ static inline void FP_OP_D(int op)
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdc); /*FADD [ESP]*/ addbyte(0xdc); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2783,7 +2783,7 @@ static inline void FP_OP_D(int op)
addbyte(0x64); addbyte(0x64);
addbyte(0x1d); addbyte(0x1d);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdc); /*FADD [ESP]*/ addbyte(0xdc); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2813,7 +2813,7 @@ static inline void FP_OP_IW(int op)
addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xde); /*FADD [ESP]*/ addbyte(0xde); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2837,7 +2837,7 @@ static inline void FP_OP_IW(int op)
addbyte(0x64); addbyte(0x64);
addbyte(0x1d); addbyte(0x1d);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xde); /*FADD [ESP]*/ addbyte(0xde); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2860,7 +2860,7 @@ static inline void FP_OP_IL(int op)
addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xda); /*FADD [ESP]*/ addbyte(0xda); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2884,7 +2884,7 @@ static inline void FP_OP_IL(int op)
addbyte(0x64); addbyte(0x64);
addbyte(0x1d); addbyte(0x1d);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xda); /*FADD [ESP]*/ addbyte(0xda); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2912,7 +2912,7 @@ static inline void FP_OP_IQ(int op)
addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdc); /*FADD [ESP]*/ addbyte(0xdc); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -2940,7 +2940,7 @@ static inline void FP_OP_IQ(int op)
addbyte(0x64); addbyte(0x64);
addbyte(0x1d); addbyte(0x1d);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdc); /*FADD [ESP]*/ addbyte(0xdc); /*FADD [ESP]*/
addbyte(0x04 | op); addbyte(0x04 | op);
addbyte(0x24); addbyte(0x24);
@@ -3243,7 +3243,7 @@ static inline void FP_OP_REG(int op, int dst, int src)
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); addbyte((uint8_t)cpu_state_offset(tag[(cpu_state.TOP + dst) & 7]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdd); /*FSTP ST[dst][EBP]*/ addbyte(0xdd); /*FSTP ST[dst][EBP]*/
addbyte(0x5d); addbyte(0x5d);
addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); addbyte((uint8_t)cpu_state_offset(ST[(cpu_state.TOP + dst) & 7]));
@@ -3275,7 +3275,7 @@ static inline void FP_OP_REG(int op, int dst, int src)
addbyte(0x64); addbyte(0x64);
addbyte(0x1d); addbyte(0x1d);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdc); /*FADD ST[EAX*8]*/ addbyte(0xdc); /*FADD ST[EAX*8]*/
addbyte(0x44 | op); addbyte(0x44 | op);
addbyte(0xc5); addbyte(0xc5);
@@ -3295,7 +3295,7 @@ static inline void FP_OP_REG(int op, int dst, int src)
addbyte(0x64); addbyte(0x64);
addbyte(0x05); addbyte(0x05);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdc); /*FADD ST[EBX*8]*/ addbyte(0xdc); /*FADD ST[EBX*8]*/
addbyte(0x44 | op); addbyte(0x44 | op);
addbyte(0xdd); addbyte(0xdd);
@@ -3411,7 +3411,7 @@ static inline void FP_FCHS()
addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/
addbyte(0x65); addbyte(0x65);
addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(tag[cpu_state.TOP]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xdd); /*FSTP ST[dst][EBP]*/ addbyte(0xdd); /*FSTP ST[dst][EBP]*/
addbyte(0x5d); addbyte(0x5d);
addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP])); addbyte((uint8_t)cpu_state_offset(ST[cpu_state.TOP]));
@@ -3430,7 +3430,7 @@ static inline void FP_FCHS()
addbyte(0x64); addbyte(0x64);
addbyte(0x05); addbyte(0x05);
addbyte((uint8_t)cpu_state_offset(tag[0])); addbyte((uint8_t)cpu_state_offset(tag[0]));
addbyte(~TAG_UINT64); addbyte(TAG_NOT_UINT64);
addbyte(0xd9); /*FCHS*/ addbyte(0xd9); /*FCHS*/
addbyte(0xe0); addbyte(0xe0);
addbyte(0xdd); /*FSTP ST[EAX*8]*/ addbyte(0xdd); /*FSTP ST[EAX*8]*/

View File

@@ -1497,7 +1497,7 @@ void codegen_block_start_recompile(codeblock_t *block)
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1; cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1;
block->TOP = cpu_state.TOP; block->TOP = cpu_state.TOP & 7;
block->was_recompiled = 1; block->was_recompiled = 1;
codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS); codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);

View File

@@ -1663,9 +1663,9 @@ syscall(uint32_t fetchdat)
{ {
uint16_t seg_data[4]; uint16_t seg_data[4];
// #ifdef ENABLE_386_COMMON_LOG #ifdef ENABLE_386_COMMON_LOG
pclog("SYSCALL called\n"); x386_common_log("SYSCALL called\n");
// #endif #endif
if (!(cr0 & 1)) { if (!(cr0 & 1)) {
x86gpf("SYSCALL: CPU not in protected mode", 0); x86gpf("SYSCALL: CPU not in protected mode", 0);
@@ -1723,9 +1723,9 @@ sysret(uint32_t fetchdat)
{ {
uint16_t seg_data[4]; uint16_t seg_data[4];
// #ifdef ENABLE_386_COMMON_LOG #ifdef ENABLE_386_COMMON_LOG
pclog("SYSRET called\n"); x386_common_log("SYSRET called\n");
// #endif #endif
if (!AMD_SYSRET_SB) { if (!AMD_SYSRET_SB) {
x86gpf("SYSRET: CS MSR is zero", 0); x86gpf("SYSRET: CS MSR is zero", 0);

View File

@@ -37,7 +37,6 @@ fpu_log(const char *fmt, ...)
#endif #endif
#ifdef USE_NEW_DYNAREC
#define X87_TAG_VALID 0 #define X87_TAG_VALID 0
#define X87_TAG_ZERO 1 #define X87_TAG_ZERO 1
#define X87_TAG_INVALID 2 #define X87_TAG_INVALID 2
@@ -79,35 +78,6 @@ void x87_settag(uint16_t new_tag)
cpu_state.tag[c] = TAG_VALID; cpu_state.tag[c] = TAG_VALID;
} }
} }
#else
uint16_t x87_gettag()
{
uint16_t ret = 0;
int c;
for (c = 0; c < 8; c++)
{
if (cpu_state.tag[c] & TAG_UINT64)
ret |= 2 << (c*2);
else
ret |= (cpu_state.tag[c] << (c*2));
}
return ret;
}
void x87_settag(uint16_t new_tag)
{
cpu_state.tag[0] = new_tag & 3;
cpu_state.tag[1] = (new_tag >> 2) & 3;
cpu_state.tag[2] = (new_tag >> 4) & 3;
cpu_state.tag[3] = (new_tag >> 6) & 3;
cpu_state.tag[4] = (new_tag >> 8) & 3;
cpu_state.tag[5] = (new_tag >> 10) & 3;
cpu_state.tag[6] = (new_tag >> 12) & 3;
cpu_state.tag[7] = (new_tag >> 14) & 3;
}
#endif
#ifdef ENABLE_808X_LOG #ifdef ENABLE_808X_LOG

View File

@@ -6,53 +6,38 @@
uint32_t x87_pc_off,x87_op_off; uint32_t x87_pc_off,x87_op_off;
uint16_t x87_pc_seg,x87_op_seg; uint16_t x87_pc_seg,x87_op_seg;
static inline void x87_set_mmx() static __inline void x87_set_mmx()
{ {
#ifdef USE_NEW_DYNAREC
cpu_state.TOP = 0;
*(uint64_t *)cpu_state.tag = 0x0101010101010101ull;
cpu_state.ismmx = 1;
#else
uint64_t *p; uint64_t *p;
cpu_state.TOP = 0; cpu_state.TOP = 0;
p = (uint64_t *)cpu_state.tag; p = (uint64_t *)cpu_state.tag;
*p = 0; *p = 0x0101010101010101ull;
cpu_state.ismmx = 1; cpu_state.ismmx = 1;
#endif
} }
static inline void x87_emms() static __inline void x87_emms()
{ {
#ifdef USE_NEW_DYNAREC
*(uint64_t *)cpu_state.tag = 0;
cpu_state.ismmx = 0;
#else
uint64_t *p; uint64_t *p;
p = (uint64_t *)cpu_state.tag; p = (uint64_t *)cpu_state.tag;
*p = 0; *p = 0;
cpu_state.ismmx = 0; cpu_state.ismmx = 0;
#endif
} }
uint16_t x87_gettag(); uint16_t x87_gettag();
void x87_settag(uint16_t new_tag); void x87_settag(uint16_t new_tag);
#ifdef USE_NEW_DYNAREC
#define TAG_EMPTY 0 #define TAG_EMPTY 0
#define TAG_VALID (1 << 0) #define TAG_VALID (1 << 0)
/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ /*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/
#define TAG_UINT64 (1 << 7) #define TAG_UINT64 (1 << 7)
/*Old dynarec stuff.*/
#define TAG_NOT_UINT64 0x7f
#define X87_ROUNDING_NEAREST 0 #define X87_ROUNDING_NEAREST 0
#define X87_ROUNDING_DOWN 1 #define X87_ROUNDING_DOWN 1
#define X87_ROUNDING_UP 2 #define X87_ROUNDING_UP 2
#define X87_ROUNDING_CHOP 3 #define X87_ROUNDING_CHOP 3
void codegen_set_rounding_mode(int mode); void codegen_set_rounding_mode(int mode);
#else
#define TAG_EMPTY 3
#define TAG_VALID (1 << 0)
/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/
#define TAG_UINT64 (1 << 2)
#endif

View File

@@ -8,7 +8,7 @@
* *
* x87 FPU instructions core. * x87 FPU instructions core.
* *
* * Version: @(#)x87_ops.h 1.0.8 2019/06/11
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk> * Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -25,7 +25,6 @@
#ifdef _MSC_VER #ifdef _MSC_VER
# include <intrin.h> # include <intrin.h>
#endif #endif
// #include "x87_timings.h"
#ifdef ENABLE_FPU_LOG #ifdef ENABLE_FPU_LOG
extern void fpu_log(const char *fmt, ...); extern void fpu_log(const char *fmt, ...);
@@ -39,6 +38,11 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ
#define ST(x) cpu_state.ST[((cpu_state.TOP+(x))&7)] #define ST(x) cpu_state.ST[((cpu_state.TOP+(x))&7)]
#define C0 (1<<8)
#define C1 (1<<9)
#define C2 (1<<10)
#define C3 (1<<14)
#define STATUS_ZERODIVIDE 4 #define STATUS_ZERODIVIDE 4
#ifdef FPU_8087 #ifdef FPU_8087
@@ -90,13 +94,11 @@ static __inline void x87_push(double i)
{ {
#ifdef USE_NEW_DYNAREC #ifdef USE_NEW_DYNAREC
cpu_state.TOP--; cpu_state.TOP--;
cpu_state.ST[cpu_state.TOP&7] = i;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
#else #else
cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.TOP=(cpu_state.TOP-1)&7;
cpu_state.ST[cpu_state.TOP] = i;
cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0;
#endif #endif
cpu_state.ST[cpu_state.TOP&7] = i;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
} }
static __inline void x87_push_u64(uint64_t i) static __inline void x87_push_u64(uint64_t i)
@@ -111,60 +113,32 @@ static __inline void x87_push_u64(uint64_t i)
#ifdef USE_NEW_DYNAREC #ifdef USE_NEW_DYNAREC
cpu_state.TOP--; cpu_state.TOP--;
cpu_state.ST[cpu_state.TOP&7] = td.d;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
#else #else
cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.TOP=(cpu_state.TOP-1)&7;
cpu_state.ST[cpu_state.TOP] = td.d;
cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0;
#endif #endif
cpu_state.ST[cpu_state.TOP&7] = td.d;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
} }
static __inline double x87_pop() static __inline double x87_pop()
{ {
#ifdef USE_NEW_DYNAREC
double t = cpu_state.ST[cpu_state.TOP&7]; double t = cpu_state.ST[cpu_state.TOP&7];
cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY;
#ifdef USE_NEW_DYNAREC
cpu_state.TOP++; cpu_state.TOP++;
return t;
#else #else
double t = cpu_state.ST[cpu_state.TOP];
cpu_state.tag[cpu_state.TOP&7] = 3;
cpu_state.TOP=(cpu_state.TOP+1)&7; cpu_state.TOP=(cpu_state.TOP+1)&7;
return t;
#endif #endif
return t;
} }
static int old_round = FE_TONEAREST;
static __inline void x87_round_save(void)
{
old_round = fegetround();
}
static __inline void x87_round_set(void)
{
old_round = fegetround();
fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]);
}
static __inline void x87_round_restore(void)
{
fesetround(old_round);
}
#ifdef PCEM_CODE
static __inline int64_t x87_fround(double b) static __inline int64_t x87_fround(double b)
{ {
#ifdef PCEM_CODE
int64_t a, c; int64_t a, c;
#endif
switch ((cpu_state.npxc >> 10) & 3) switch ((cpu_state.npxc >> 10) & 3)
{ {
case 0: /*Nearest*/ case 0: /*Nearest*/
#ifdef PCEM_CODE
a = (int64_t)floor(b); a = (int64_t)floor(b);
c = (int64_t)floor(b + 1.0); c = (int64_t)floor(b + 1.0);
if ((b - a) < (c - b)) if ((b - a) < (c - b))
@@ -173,35 +147,16 @@ static __inline int64_t x87_fround(double b)
return c; return c;
else else
return (a & 1) ? c : a; return (a & 1) ? c : a;
#else
return (int64_t)round(b);
#endif
case 1: /*Down*/ case 1: /*Down*/
return (int64_t)floor(b); return (int64_t)floor(b);
case 2: /*Up*/ case 2: /*Up*/
return (int64_t)ceil(b); return (int64_t)ceil(b);
case 3: /*Chop*/ case 3: /*Chop*/
#ifdef PCEM_CODE
return (int64_t)b; return (int64_t)b;
#else
return (int64_t)trunc(b);
#endif
} }
return 0; return 0LL;
} }
#else
static __inline int64_t x87_fround(double b)
{
int64_t ret;
x87_round_set();
ret = (int64_t) rint(b);
x87_round_restore();
return ret;
}
#endif
#define BIAS80 16383 #define BIAS80 16383
#define BIAS64 1023 #define BIAS64 1023
@@ -212,7 +167,6 @@ static __inline double x87_ld80()
int64_t exp64final; int64_t exp64final;
int64_t mant64; int64_t mant64;
int64_t sign; int64_t sign;
struct { struct {
int16_t begin; int16_t begin;
union union
@@ -221,7 +175,6 @@ static __inline double x87_ld80()
uint64_t ll; uint64_t ll;
} eind; } eind;
} test; } test;
test.eind.ll = readmeml(easeg,cpu_state.eaaddr); test.eind.ll = readmeml(easeg,cpu_state.eaaddr);
test.eind.ll |= (uint64_t)readmeml(easeg,cpu_state.eaaddr+4)<<32; test.eind.ll |= (uint64_t)readmeml(easeg,cpu_state.eaaddr+4)<<32;
test.begin = readmemw(easeg,cpu_state.eaaddr+8); test.begin = readmemw(easeg,cpu_state.eaaddr+8);
@@ -310,7 +263,6 @@ static __inline void x87_ld_frstor(int reg)
cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr);
cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8);
#ifdef USE_NEW_DYNAREC
if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64)) if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64))
{ {
cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; cpu_state.ST[reg] = (double)cpu_state.MM[reg].q;
@@ -320,15 +272,6 @@ static __inline void x87_ld_frstor(int reg)
cpu_state.tag[reg] &= ~TAG_UINT64; cpu_state.tag[reg] &= ~TAG_UINT64;
cpu_state.ST[reg] = x87_ld80(); cpu_state.ST[reg] = x87_ld80();
} }
#else
if (cpu_state.MM_w4[reg] == 0x5555 && cpu_state.tag[reg] == 2)
{
cpu_state.tag[reg] = TAG_UINT64;
cpu_state.ST[reg] = (double)cpu_state.MM[reg].q;
}
else
cpu_state.ST[reg] = x87_ld80();
#endif
} }
static __inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) static __inline void x87_ldmmx(MMX_REG *r, uint16_t *w4)
@@ -411,7 +354,7 @@ static __inline uint16_t x87_compare(double a, double b)
static __inline uint16_t x87_ucompare(double a, double b) static __inline uint16_t x87_ucompare(double a, double b)
{ {
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_AMD64 || defined __amd64__ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__
uint32_t result; uint32_t result;
#ifndef _MSC_VER #ifndef _MSC_VER
@@ -483,56 +426,6 @@ typedef union
} while (0) } while (0)
#endif #endif
#ifdef USE_NEW_DYNAREC
#define FP_CHECKTOP64 cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64
#define FP_TAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
#define FP_FTAG() cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
#define FP_LSTAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
#define FP_LSQ() cpu_state.MM[cpu_state.TOP&7].q = temp64;
#define FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP&7].q;
#define FP_NTAG() cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
#ifdef USE_NEW_DYNAREC
#define FP_NNPXC() codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#else
#define FP_NNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
#endif
#define FP_TOP(x) (x & 7)
#define FP_DTAG 0ULL
#define FP_CTAG 0x0101010101010101ull
#define FP_EMPTY TAG_EMPTY
#ifdef USE_NEW_DYNAREC
#define FP_RNPXC() codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
#else
#define FP_RNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
#endif
#define FP_ZTAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
#define FP_DECTOP() cpu_state.TOP--;
#define FP_INCTOP() cpu_state.TOP++;
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)))
#define FP_686
#endif
#else
#define FP_CHECKTOP64 cpu_state.tag[cpu_state.TOP] & TAG_UINT64
#define FP_TAG() cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
#define FP_FTAG() cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
#define FP_LSTAG() cpu_state.tag[cpu_state.TOP] |= TAG_UINT64;
#define FP_LSQ() cpu_state.MM[cpu_state.TOP].q = temp64;
#define FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP].q;
#define FP_NTAG() cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64;
#define FP_NNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
#define FP_TOP(x) (x)
#define FP_DTAG 0x0303030303030303ll
#define FP_CTAG 0ULL
#define FP_EMPTY 3
#define FP_RNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
#define FP_ZTAG() cpu_state.tag[cpu_state.TOP&7] = 1;
#define FP_DECTOP() cpu_state.TOP = (cpu_state.TOP - 1) & 7
#define FP_INCTOP() cpu_state.TOP = (cpu_state.TOP + 1) & 7
#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
#define FP_686
#endif
#endif
#include "x87_ops_arith.h" #include "x87_ops_arith.h"
#include "x87_ops_misc.h" #include "x87_ops_misc.h"
#include "x87_ops_loadstore.h" #include "x87_ops_loadstore.h"
@@ -1171,7 +1064,7 @@ const OpFn OP_TABLE(fpu_da_a32)[256] =
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
}; };
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) #if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
const OpFn OP_TABLE(fpu_686_da_a16)[256] = const OpFn OP_TABLE(fpu_686_da_a16)[256] =
{ {
opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16,
@@ -1404,7 +1297,7 @@ const OpFn OP_TABLE(fpu_db_a32)[256] =
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
}; };
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) #if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
const OpFn OP_TABLE(fpu_686_db_a16)[256] = const OpFn OP_TABLE(fpu_686_db_a16)[256] =
{ {
opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16,
@@ -1977,7 +1870,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] =
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
}; };
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) #if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
const OpFn OP_TABLE(fpu_686_df_a16)[256] = const OpFn OP_TABLE(fpu_686_df_a16)[256] =
{ {
opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16,

View File

@@ -6,10 +6,12 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
fetch_ea_ ## a_size(fetchdat); \ fetch_ea_ ## a_size(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_round_set(); \ if ((cpu_state.npxc >> 10) & 3) \
fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \
ST(0) += use_var; \ ST(0) += use_var; \
x87_round_restore(); \ if ((cpu_state.npxc >> 10) & 3) \
FP_TAG(); \ fesetround(FE_TONEAREST); \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
CLOCK_CYCLES(8); \ CLOCK_CYCLES(8); \
return 0; \ return 0; \
} \ } \
@@ -45,10 +47,8 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \
fetch_ea_ ## a_size(fetchdat); \ fetch_ea_ ## a_size(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_round_set(); \
x87_div(ST(0), ST(0), use_var); \ x87_div(ST(0), ST(0), use_var); \
x87_round_restore(); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
FP_TAG(); \
CLOCK_CYCLES(73); \ CLOCK_CYCLES(73); \
return 0; \ return 0; \
} \ } \
@@ -59,10 +59,8 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \
fetch_ea_ ## a_size(fetchdat); \ fetch_ea_ ## a_size(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_round_set(); \
x87_div(ST(0), use_var, ST(0)); \ x87_div(ST(0), use_var, ST(0)); \
x87_round_restore(); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
FP_TAG(); \
CLOCK_CYCLES(73); \ CLOCK_CYCLES(73); \
return 0; \ return 0; \
} \ } \
@@ -73,10 +71,8 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \
fetch_ea_ ## a_size(fetchdat); \ fetch_ea_ ## a_size(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_round_set(); \
ST(0) *= use_var; \ ST(0) *= use_var; \
x87_round_restore(); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
FP_TAG(); \
CLOCK_CYCLES(11); \ CLOCK_CYCLES(11); \
return 0; \ return 0; \
} \ } \
@@ -87,10 +83,8 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \
fetch_ea_ ## a_size(fetchdat); \ fetch_ea_ ## a_size(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_round_set(); \
ST(0) -= use_var; \ ST(0) -= use_var; \
x87_round_restore(); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
FP_TAG(); \
CLOCK_CYCLES(8); \ CLOCK_CYCLES(8); \
return 0; \ return 0; \
} \ } \
@@ -101,10 +95,8 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \
fetch_ea_ ## a_size(fetchdat); \ fetch_ea_ ## a_size(fetchdat); \
SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \ load_var = get(); if (cpu_state.abrt) return 1; \
x87_round_set(); \
ST(0) = use_var - ST(0); \ ST(0) = use_var - ST(0); \
x87_round_restore(); \ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
FP_TAG(); \
CLOCK_CYCLES(8); \ CLOCK_CYCLES(8); \
return 0; \ return 0; \
} }
@@ -129,14 +121,12 @@ opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t)
#endif #endif
static int opFADD(uint32_t fetchdat) static int opFADD(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(0) + ST(fetchdat & 7); ST(0) = ST(0) + ST(fetchdat & 7);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
} }
@@ -145,7 +135,7 @@ static int opFADDr(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
} }
@@ -154,7 +144,7 @@ static int opFADDP(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
@@ -213,7 +203,7 @@ static int opFUCOMPP(uint32_t fetchdat)
return 0; return 0;
} }
#ifdef FP_686 #if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
static int opFCOMI(uint32_t fetchdat) static int opFCOMI(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
@@ -245,7 +235,7 @@ static int opFDIV(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(73); CLOCK_CYCLES(73);
return 0; return 0;
} }
@@ -254,7 +244,7 @@ static int opFDIVr(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
CLOCK_CYCLES(73); CLOCK_CYCLES(73);
return 0; return 0;
} }
@@ -263,7 +253,7 @@ static int opFDIVP(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(73); CLOCK_CYCLES(73);
return 0; return 0;
@@ -274,7 +264,7 @@ static int opFDIVR(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(73); CLOCK_CYCLES(73);
return 0; return 0;
} }
@@ -283,7 +273,7 @@ static int opFDIVRr(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
CLOCK_CYCLES(73); CLOCK_CYCLES(73);
return 0; return 0;
} }
@@ -292,7 +282,7 @@ static int opFDIVRP(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(73); CLOCK_CYCLES(73);
return 0; return 0;
@@ -303,7 +293,7 @@ static int opFMUL(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(0) * ST(fetchdat & 7); ST(0) = ST(0) * ST(fetchdat & 7);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(16); CLOCK_CYCLES(16);
return 0; return 0;
} }
@@ -312,7 +302,7 @@ static int opFMULr(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
CLOCK_CYCLES(16); CLOCK_CYCLES(16);
return 0; return 0;
} }
@@ -321,7 +311,7 @@ static int opFMULP(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(16); CLOCK_CYCLES(16);
return 0; return 0;
@@ -332,7 +322,7 @@ static int opFSUB(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(0) - ST(fetchdat & 7); ST(0) = ST(0) - ST(fetchdat & 7);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
} }
@@ -341,7 +331,7 @@ static int opFSUBr(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
} }
@@ -350,7 +340,7 @@ static int opFSUBP(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
@@ -361,7 +351,7 @@ static int opFSUBR(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = ST(fetchdat & 7) - ST(0); ST(0) = ST(fetchdat & 7) - ST(0);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
} }
@@ -370,7 +360,7 @@ static int opFSUBRr(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
} }
@@ -379,7 +369,7 @@ static int opFSUBRP(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
FP_FTAG(); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(8); CLOCK_CYCLES(8);
return 0; return 0;
@@ -407,7 +397,7 @@ static int opFUCOMP(uint32_t fetchdat)
return 0; return 0;
} }
#ifdef FP_686 #if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
static int opFUCOMI(uint32_t fetchdat) static int opFUCOMI(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();

View File

@@ -8,7 +8,7 @@
* *
* x87 FPU instructions core. * x87 FPU instructions core.
* *
* * Version: @(#)x87_ops_loadstore.h 1.0.2 2019/06/11
* *
* Author: Sarah Walker, <http://pcem-emulator.co.uk/> * Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -101,8 +101,8 @@ static int opFILDiq_a16(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
temp64 = geteaq(); if (cpu_state.abrt) return 1; temp64 = geteaq(); if (cpu_state.abrt) return 1;
x87_push((double)temp64); x87_push((double)temp64);
FP_LSQ(); cpu_state.MM[cpu_state.TOP&7].q = temp64;
FP_LSTAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
CLOCK_CYCLES(10); CLOCK_CYCLES(10);
return 0; return 0;
@@ -116,8 +116,8 @@ static int opFILDiq_a32(uint32_t fetchdat)
SEG_CHECK_READ(cpu_state.ea_seg); SEG_CHECK_READ(cpu_state.ea_seg);
temp64 = geteaq(); if (cpu_state.abrt) return 1; temp64 = geteaq(); if (cpu_state.abrt) return 1;
x87_push((double)temp64); x87_push((double)temp64);
FP_LSQ(); cpu_state.MM[cpu_state.TOP&7].q = temp64;
FP_LSTAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
CLOCK_CYCLES(10); CLOCK_CYCLES(10);
return 0; return 0;
@@ -185,8 +185,8 @@ static int FISTPiq_a16(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
fetch_ea_16(fetchdat); fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
if (FP_CHECKTOP64) if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64)
FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP&7].q;
else else
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;
@@ -201,8 +201,8 @@ static int FISTPiq_a32(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
fetch_ea_32(fetchdat); fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg); SEG_CHECK_WRITE(cpu_state.ea_seg);
if (FP_CHECKTOP64) if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64)
FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP&7].q;
else else
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;

View File

@@ -48,10 +48,10 @@ static int opFINIT(uint32_t fetchdat)
#else #else
cpu_state.npxc = 0x37F; cpu_state.npxc = 0x37F;
#endif #endif
FP_RNPXC(); codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
cpu_state.npxs = 0; cpu_state.npxs = 0;
p = (uint64_t *)cpu_state.tag; p = (uint64_t *)cpu_state.tag;
*p = FP_DTAG; *p = 0;
cpu_state.TOP = 0; cpu_state.TOP = 0;
cpu_state.ismmx = 0; cpu_state.ismmx = 0;
CLOCK_CYCLES(17); CLOCK_CYCLES(17);
@@ -64,7 +64,7 @@ static int opFFREE(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY;
CLOCK_CYCLES(3); CLOCK_CYCLES(3);
return 0; return 0;
} }
@@ -73,7 +73,7 @@ static int opFFREEP(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; 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(3);
return 0; return 0;
@@ -112,7 +112,7 @@ static int FSTOR()
case 0x000: /*16-bit real mode*/ case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/ case 0x001: /*16-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
FP_NNPXC(); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7; cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@@ -121,7 +121,7 @@ static int FSTOR()
case 0x100: /*32-bit real mode*/ case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/ case 0x101: /*32-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
FP_NNPXC(); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7; cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@@ -143,7 +143,7 @@ static int FSTOR()
p = (uint64_t *) cpu_state.tag; p = (uint64_t *) cpu_state.tag;
if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff && if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff &&
cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff && cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff &&
!cpu_state.TOP && (*p == FP_CTAG)) !cpu_state.TOP && (*p == 0x0101010101010101ull))
cpu_state.ismmx = 1; cpu_state.ismmx = 1;
CLOCK_CYCLES((cr0 & 1) ? 34 : 44); CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
@@ -173,7 +173,7 @@ static int FSAVE()
uint64_t *p; uint64_t *p;
FP_ENTER(); FP_ENTER();
cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (FP_TOP(cpu_state.TOP) << 11); cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11);
switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
{ {
@@ -305,10 +305,10 @@ static int FSAVE()
} }
cpu_state.npxc = 0x37F; cpu_state.npxc = 0x37F;
FP_RNPXC(); codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
cpu_state.npxs = 0; cpu_state.npxs = 0;
p = (uint64_t *)cpu_state.tag; p = (uint64_t *)cpu_state.tag;
*p = FP_DTAG; *p = 0;
cpu_state.TOP = 0; cpu_state.TOP = 0;
cpu_state.ismmx = 0; cpu_state.ismmx = 0;
@@ -339,7 +339,7 @@ static int opFSTSW_a16(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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) | (FP_TOP(cpu_state.TOP) << 11)); seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
CLOCK_CYCLES(3); CLOCK_CYCLES(3);
return cpu_state.abrt; return cpu_state.abrt;
} }
@@ -349,7 +349,7 @@ static int opFSTSW_a32(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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) | (FP_TOP(cpu_state.TOP) << 11)); seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
CLOCK_CYCLES(3); CLOCK_CYCLES(3);
return cpu_state.abrt; return cpu_state.abrt;
} }
@@ -366,8 +366,8 @@ static int opFLD(uint32_t fetchdat)
old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7];
old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
x87_push(ST(fetchdat&7)); x87_push(ST(fetchdat&7));
cpu_state.tag[FP_TOP(cpu_state.TOP)] = old_tag; cpu_state.tag[cpu_state.TOP&7] = old_tag;
cpu_state.MM[FP_TOP(cpu_state.TOP)].q = old_i64; cpu_state.MM[cpu_state.TOP&7].q = old_i64;
CLOCK_CYCLES(4); CLOCK_CYCLES(4);
return 0; return 0;
} }
@@ -382,11 +382,11 @@ static int opFXCH(uint32_t fetchdat)
td = ST(0); td = ST(0);
ST(0) = ST(fetchdat&7); ST(0) = ST(fetchdat&7);
ST(fetchdat&7) = td; ST(fetchdat&7) = td;
old_tag = cpu_state.tag[FP_TOP(cpu_state.TOP)]; old_tag = cpu_state.tag[cpu_state.TOP&7];
cpu_state.tag[FP_TOP(cpu_state.TOP)] = 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 + fetchdat) & 7] = old_tag; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag;
old_i64 = cpu_state.MM[FP_TOP(cpu_state.TOP)].q; old_i64 = cpu_state.MM[cpu_state.TOP&7].q;
cpu_state.MM[FP_TOP(cpu_state.TOP)].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(4);
@@ -398,7 +398,7 @@ static int opFCHS(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = -ST(0); ST(0) = -ST(0);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(6); CLOCK_CYCLES(6);
return 0; return 0;
} }
@@ -408,7 +408,7 @@ static int opFABS(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = fabs(ST(0)); ST(0) = fabs(ST(0));
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(3); CLOCK_CYCLES(3);
return 0; return 0;
} }
@@ -429,7 +429,7 @@ static int opFXAM(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
cpu_state.npxs &= ~(C0|C1|C2|C3); cpu_state.npxs &= ~(C0|C1|C2|C3);
if (cpu_state.tag[cpu_state.TOP&7] == FP_EMPTY) cpu_state.npxs |= (C0|C3); if (cpu_state.tag[cpu_state.TOP&7] == TAG_EMPTY) cpu_state.npxs |= (C0|C3);
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;
@@ -496,7 +496,7 @@ static int opFLDZ(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
x87_push(0.0); x87_push(0.0);
FP_ZTAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(4); CLOCK_CYCLES(4);
return 0; return 0;
} }
@@ -506,7 +506,7 @@ static int opF2XM1(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
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(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(200); CLOCK_CYCLES(200);
return 0; return 0;
} }
@@ -516,7 +516,7 @@ static int opFYL2X(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(1) = ST(1) * (log(ST(0)) / log(2.0)); ST(1) = ST(1) * (log(ST(0)) / log(2.0));
FP_NTAG(); cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(250); CLOCK_CYCLES(250);
return 0; return 0;
@@ -526,8 +526,8 @@ static int opFYL2XP1(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0)); ST(1) = ST(1) * (log1p(ST(0)) / log(2.0));
FP_NTAG(); cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(250); CLOCK_CYCLES(250);
return 0; return 0;
@@ -538,7 +538,7 @@ static int opFPTAN(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = tan(ST(0)); ST(0) = tan(ST(0));
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
x87_push(1.0); x87_push(1.0);
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(235); CLOCK_CYCLES(235);
@@ -550,7 +550,7 @@ static int opFPATAN(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(1) = atan2(ST(1), ST(0)); ST(1) = atan2(ST(1), ST(0));
FP_NTAG(); cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop(); x87_pop();
CLOCK_CYCLES(250); CLOCK_CYCLES(250);
return 0; return 0;
@@ -560,7 +560,11 @@ static int opFDECSTP(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
FP_DECTOP(); #ifdef USE_NEW_DYNAREC
cpu_state.TOP--;
#else
cpu_state.TOP = (cpu_state.TOP - 1) & 7;
#endif
CLOCK_CYCLES(4); CLOCK_CYCLES(4);
return 0; return 0;
} }
@@ -569,7 +573,11 @@ static int opFINCSTP(uint32_t fetchdat)
{ {
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
FP_INCTOP(); #ifdef USE_NEW_DYNAREC
cpu_state.TOP++;
#else
cpu_state.TOP = (cpu_state.TOP + 1) & 7;
#endif
CLOCK_CYCLES(4); CLOCK_CYCLES(4);
return 0; return 0;
} }
@@ -581,7 +589,7 @@ static int opFPREM(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
temp64 = (int64_t)(ST(0) / ST(1)); temp64 = (int64_t)(ST(0) / ST(1));
ST(0) = ST(0) - (ST(1) * (double)temp64); ST(0) = ST(0) - (ST(1) * (double)temp64);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~(C0|C1|C2|C3); cpu_state.npxs &= ~(C0|C1|C2|C3);
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;
@@ -597,7 +605,7 @@ static int opFPREM1(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
temp64 = (int64_t)(ST(0) / ST(1)); temp64 = (int64_t)(ST(0) / ST(1));
ST(0) = ST(0) - (ST(1) * (double)temp64); ST(0) = ST(0) - (ST(1) * (double)temp64);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~(C0|C1|C2|C3); cpu_state.npxs &= ~(C0|C1|C2|C3);
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;
@@ -612,7 +620,7 @@ static int opFSQRT(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = sqrt(ST(0)); ST(0) = sqrt(ST(0));
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(83); CLOCK_CYCLES(83);
return 0; return 0;
} }
@@ -625,7 +633,7 @@ static int opFSINCOS(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
td = ST(0); td = ST(0);
ST(0) = sin(td); ST(0) = sin(td);
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
x87_push(cos(td)); x87_push(cos(td));
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(330); CLOCK_CYCLES(330);
@@ -635,18 +643,10 @@ static int opFSINCOS(uint32_t fetchdat)
static int opFRNDINT(uint32_t fetchdat) static int opFRNDINT(uint32_t fetchdat)
{ {
double rounded;
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
rounded = (double) x87_fround(ST(0)); ST(0) = (double)x87_fround(ST(0));
#ifndef PCEM_CODE cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
if (rounded > ST(0))
cpu_state.npxs |= C1;
else
cpu_state.npxs &= ~C1;
#endif
ST(0) = rounded;
FP_TAG();
CLOCK_CYCLES(21); CLOCK_CYCLES(21);
return 0; return 0;
} }
@@ -658,7 +658,7 @@ static int opFSCALE(uint32_t fetchdat)
cpu_state.pc++; cpu_state.pc++;
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(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
CLOCK_CYCLES(30); CLOCK_CYCLES(30);
return 0; return 0;
} }
@@ -669,7 +669,7 @@ static int opFSIN(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = sin(ST(0)); ST(0) = sin(ST(0));
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(300); CLOCK_CYCLES(300);
return 0; return 0;
@@ -680,7 +680,7 @@ static int opFCOS(uint32_t fetchdat)
FP_ENTER(); FP_ENTER();
cpu_state.pc++; cpu_state.pc++;
ST(0) = cos(ST(0)); ST(0) = cos(ST(0));
FP_TAG(); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~C2; cpu_state.npxs &= ~C2;
CLOCK_CYCLES(300); CLOCK_CYCLES(300);
return 0; return 0;
@@ -696,7 +696,7 @@ static int FLDENV()
case 0x000: /*16-bit real mode*/ case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/ case 0x001: /*16-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
FP_NNPXC(); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7; cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@@ -704,7 +704,7 @@ static int FLDENV()
case 0x100: /*32-bit real mode*/ case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/ case 0x101: /*32-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
FP_NNPXC(); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7; cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@@ -742,7 +742,7 @@ static int opFLDCW_a16(uint32_t fetchdat)
tempw = geteaw(); tempw = geteaw();
if (cpu_state.abrt) return 1; if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw; cpu_state.npxc = tempw;
FP_NNPXC(); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
CLOCK_CYCLES(4); CLOCK_CYCLES(4);
return 0; return 0;
} }
@@ -756,7 +756,7 @@ static int opFLDCW_a32(uint32_t fetchdat)
tempw = geteaw(); tempw = geteaw();
if (cpu_state.abrt) return 1; if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw; cpu_state.npxc = tempw;
FP_NNPXC(); codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
CLOCK_CYCLES(4); CLOCK_CYCLES(4);
return 0; return 0;
} }
@@ -845,8 +845,7 @@ static int opFSTCW_a32(uint32_t fetchdat)
} }
#endif #endif
#ifndef FPU_8087 #if !defined(FPU_8087) && defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))
#ifdef FP_686
#define opFCMOV(condition) \ #define opFCMOV(condition) \
static int opFCMOV ## condition(uint32_t fetchdat) \ static int opFCMOV ## condition(uint32_t fetchdat) \
{ \ { \
@@ -854,8 +853,8 @@ static int opFSTCW_a32(uint32_t fetchdat)
cpu_state.pc++; \ cpu_state.pc++; \
if (cond_ ## condition) \ if (cond_ ## condition) \
{ \ { \
cpu_state.tag[FP_TOP(cpu_state.TOP)] = 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.MM[FP_TOP(cpu_state.TOP)].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; \
ST(0) = ST(fetchdat & 7); \ ST(0) = ST(fetchdat & 7); \
} \ } \
CLOCK_CYCLES(4); \ CLOCK_CYCLES(4); \
@@ -874,4 +873,3 @@ opFCMOV(NE)
opFCMOV(NBE) opFCMOV(NBE)
opFCMOV(NU) opFCMOV(NU)
#endif #endif
#endif