From 52a27a9256d91ee3195713dd4eb293e5e12be8b2 Mon Sep 17 00:00:00 2001 From: TomW Date: Mon, 18 May 2015 20:33:33 +0100 Subject: [PATCH] FPU copy should now work. --- src/codegen_ops_x86.h | 73 ++++++++++++++++++++++++++ src/x87.c | 15 +++++- src/x87.h | 4 ++ src/x87_ops.h | 33 ++++++++++++ src/x87_ops_arith.h | 24 +++++++++ src/x87_ops_loadstore.h | 16 +++++- src/x87_ops_misc.h | 111 +++++++++++++++++++++++++--------------- 7 files changed, 232 insertions(+), 44 deletions(-) diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 9109cb5..00b5c33 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -1275,6 +1275,14 @@ static void FP_FLD(int reg) addbyte(0x83); /*AND EBX, 7*/ addbyte(0xe3); addbyte(0x07); + addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ + addbyte(0x14); + addbyte(0xc5); + addlong((uintptr_t)ST_i64); + addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ + addbyte(0x0c); + addbyte(0xc5); + addlong(((uintptr_t)ST_i64) + 4); addbyte(0x8a); /*MOV AL, [tag+EAX]*/ addbyte(0x80); addlong((uintptr_t)tag); @@ -1285,6 +1293,14 @@ static void FP_FLD(int reg) addbyte(0x88); /*MOV [tag+EBX], AL*/ addbyte(0x83); addlong((uintptr_t)tag); + addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ + addbyte(0x14); + addbyte(0xdd); + addlong((uintptr_t)ST_i64); + addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ + addbyte(0x0c); + addbyte(0xdd); + addlong(((uintptr_t)ST_i64) + 4); addbyte(0x89); /*MOV [TOP], EBX*/ addbyte(0x1d); @@ -1351,6 +1367,51 @@ static void FP_FXCH(int reg) addbyte(0x1c); addbyte(0xc5); addlong((uintptr_t)ST); + addbyte(0xbe); /*MOVL ESI, tag*/ + addlong((uintptr_t)tag); + addbyte(0x8a); /*MOV CL, tag[EAX]*/ + addbyte(0x0c); + addbyte(0x06); + addbyte(0x8a); /*MOV DL, tag[EBX]*/ + addbyte(0x14); + addbyte(0x1e); + addbyte(0x88); /*MOV tag[EBX], CL*/ + addbyte(0x0c); + addbyte(0x1e); + addbyte(0x88); /*MOV tag[EAX], DL*/ + addbyte(0x14); + addbyte(0x06); + addbyte(0xbe); /*MOVL ESI, ST_int64*/ + addlong((uintptr_t)ST_i64); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ + addbyte(0x0c); + addbyte(0xc6); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ + addbyte(0x14); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ + addbyte(0x0c); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ + addbyte(0x14); + addbyte(0xc6); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ + addbyte(0x4c); + addbyte(0xc6); + addbyte(0x04); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ + addbyte(0x54); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ + addbyte(0x4c); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ + addbyte(0x54); + addbyte(0xc6); + addbyte(0x04); + reg = reg; //#endif #if 0 addbyte(0xbe); /*MOVL ESI, ST*/ @@ -1633,6 +1694,10 @@ static void FP_OP_S(int op) addbyte(0x04); addbyte(0xdd); addlong((uintptr_t)ST); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0xa3); + addlong((uintptr_t)tag); + addbyte(~TAG_UINT64); addbyte(0xd8); /*FADD [ESP]*/ addbyte(0x04 | op); addbyte(0x24); @@ -1665,6 +1730,10 @@ static void FP_OP_REG(int op, int dst, int src) addbyte(0xdd); /*FLD ST[EBX*8]*/ addbyte(0x04); addbyte(0xde); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0xa3); + addlong((uintptr_t)tag); + addbyte(~TAG_UINT64); addbyte(0xdc); /*FADD ST[EAX*8]*/ addbyte(0x04 | op); addbyte(0xc6); @@ -1677,6 +1746,10 @@ static void FP_OP_REG(int op, int dst, int src) addbyte(0xdd); /*FLD [ESI+EAX*8]*/ addbyte(0x04); addbyte(0xc6); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0xa0); + addlong((uintptr_t)tag); + addbyte(~TAG_UINT64); addbyte(0xdc); /*FADD ST[EBX*8]*/ addbyte(0x04 | op); addbyte(0xde); diff --git a/src/x87.c b/src/x87.c index 2f853f8..8843472 100644 --- a/src/x87.c +++ b/src/x87.c @@ -20,6 +20,7 @@ #include "386_common.h" double ST[8]; +uint64_t ST_i64[8]; MMX_REG MM[8]; int ismmx; uint16_t npxs,npxc; @@ -29,8 +30,18 @@ int TOP; uint16_t x87_gettag() { - return tag[0] | (tag[1] << 2) | (tag[2] << 4) | (tag[3] << 6) | - (tag[4] << 8) | (tag[5] << 10) | (tag[6] << 12) | (tag[7] << 14); + uint16_t ret = 0; + int c; + + for (c = 0; c < 8; c++) + { + if (tag[c] & TAG_UINT64) + ret |= 2 << (c*2); + else + ret |= (tag[c] << (c*2)); + } + + return ret; } void x87_settag(uint16_t new_tag) diff --git a/src/x87.h b/src/x87.h index d2cc027..96c1f78 100644 --- a/src/x87.h +++ b/src/x87.h @@ -6,6 +6,7 @@ extern uint16_t npxs, npxc; extern uint8_t tag[8]; extern int ismmx; extern double ST[8]; +extern uint64_t ST_i64[8]; typedef union MMX_REG { @@ -26,3 +27,6 @@ static inline void x87_emms(); uint16_t x87_gettag(); void x87_settag(uint16_t new_tag); + +/*Hack for FPU copy. If set then ST_i64 contains the 64-bit integer loaded by FILD*/ +#define TAG_UINT64 (1 << 2) diff --git a/src/x87_ops.h b/src/x87_ops.h index 2681c63..dce2d11 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -149,6 +149,39 @@ static inline void x87_st80(double d) writememw(easeg,eaaddr+8,test.begin); } +static inline void x87_st_fsave(int reg) +{ + reg = (TOP + reg) & 7; + + if (tag[reg] & TAG_UINT64) + { + writememl(easeg, eaaddr, ST_i64[reg] & 0xffffffff); + writememl(easeg, eaaddr + 4, ST_i64[reg] >> 32); + writememw(easeg, eaaddr + 8, 0x5555); + } + else + x87_st80(ST[reg]); +} + +static inline void x87_ld_frstor(int reg) +{ + uint16_t temp; + + reg = (TOP + reg) & 7; + + temp = readmemw(easeg, eaaddr + 8); + + if (temp == 0x5555 && tag[reg] == 2) + { + tag[reg] = TAG_UINT64; + ST_i64[reg] = readmeml(easeg, eaaddr); + ST_i64[reg] |= ((uint64_t)readmeml(easeg, eaaddr + 4) << 32); + ST[reg] = (double)ST_i64[reg]; + } + else + ST[reg] = x87_ld80(); +} + static inline void x87_ldmmx(MMX_REG *r) { r->l[0] = readmeml(easeg, eaaddr); diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h index f9394cf..7536040 100644 --- a/src/x87_ops_arith.h +++ b/src/x87_ops_arith.h @@ -6,6 +6,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ fetch_ea_ ## a_size(fetchdat); \ load_var = get(); if (abrt) return 1; \ ST(0) += use_var; \ + tag[TOP] &= ~TAG_UINT64; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -39,6 +40,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ fetch_ea_ ## a_size(fetchdat); \ load_var = get(); if (abrt) return 1; \ x87_div(ST(0), ST(0), use_var); \ + tag[TOP] &= ~TAG_UINT64; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -49,6 +51,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ fetch_ea_ ## a_size(fetchdat); \ load_var = get(); if (abrt) return 1; \ x87_div(ST(0), use_var, ST(0)); \ + tag[TOP] &= ~TAG_UINT64; \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -59,6 +62,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ fetch_ea_ ## a_size(fetchdat); \ load_var = get(); if (abrt) return 1; \ ST(0) *= use_var; \ + tag[TOP] &= ~TAG_UINT64; \ CLOCK_CYCLES(11); \ return 0; \ } \ @@ -69,6 +73,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ fetch_ea_ ## a_size(fetchdat); \ load_var = get(); if (abrt) return 1; \ ST(0) -= use_var; \ + tag[TOP] &= ~TAG_UINT64; \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -79,6 +84,7 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ fetch_ea_ ## a_size(fetchdat); \ load_var = get(); if (abrt) return 1; \ ST(0) = use_var - ST(0); \ + tag[TOP] &= ~TAG_UINT64; \ CLOCK_CYCLES(8); \ return 0; \ } @@ -103,6 +109,7 @@ static int opFADD(uint32_t fetchdat) pc++; if (fplog) pclog("FADD\n"); ST(0) = ST(0) + ST(fetchdat & 7); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(8); return 0; } @@ -112,6 +119,7 @@ static int opFADDr(uint32_t fetchdat) pc++; if (fplog) pclog("FADD\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(8); return 0; } @@ -121,6 +129,7 @@ static int opFADDP(uint32_t fetchdat) pc++; if (fplog) pclog("FADDP\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(8); return 0; @@ -185,6 +194,7 @@ static int opFDIV(uint32_t fetchdat) pc++; if (fplog) pclog("FDIV\n"); x87_div(ST(0), ST(0), ST(fetchdat & 7)); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(73); return 0; } @@ -194,6 +204,7 @@ static int opFDIVr(uint32_t fetchdat) pc++; if (fplog) pclog("FDIV\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(73); return 0; } @@ -203,6 +214,7 @@ static int opFDIVP(uint32_t fetchdat) pc++; if (fplog) pclog("FDIVP\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(73); return 0; @@ -214,6 +226,7 @@ static int opFDIVR(uint32_t fetchdat) pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(0), ST(fetchdat&7), ST(0)); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(73); return 0; } @@ -223,6 +236,7 @@ static int opFDIVRr(uint32_t fetchdat) pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(73); return 0; } @@ -232,6 +246,7 @@ static int opFDIVRP(uint32_t fetchdat) pc++; if (fplog) pclog("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(73); return 0; @@ -243,6 +258,7 @@ static int opFMUL(uint32_t fetchdat) pc++; if (fplog) pclog("FMUL\n"); ST(0) = ST(0) * ST(fetchdat & 7); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(16); return 0; } @@ -252,6 +268,7 @@ static int opFMULr(uint32_t fetchdat) pc++; if (fplog) pclog("FMUL\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(16); return 0; } @@ -261,6 +278,7 @@ static int opFMULP(uint32_t fetchdat) pc++; if (fplog) pclog("FMULP\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(16); return 0; @@ -272,6 +290,7 @@ static int opFSUB(uint32_t fetchdat) pc++; if (fplog) pclog("FSUB\n"); ST(0) = ST(0) - ST(fetchdat & 7); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(8); return 0; } @@ -281,6 +300,7 @@ static int opFSUBr(uint32_t fetchdat) pc++; if (fplog) pclog("FSUB\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(8); return 0; } @@ -290,6 +310,7 @@ static int opFSUBP(uint32_t fetchdat) pc++; if (fplog) pclog("FSUBP\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(8); return 0; @@ -301,6 +322,7 @@ static int opFSUBR(uint32_t fetchdat) pc++; if (fplog) pclog("FSUBR\n"); ST(0) = ST(fetchdat & 7) - ST(0); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(8); return 0; } @@ -310,6 +332,7 @@ static int opFSUBRr(uint32_t fetchdat) pc++; if (fplog) pclog("FSUBR\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(8); return 0; } @@ -319,6 +342,7 @@ static int opFSUBRP(uint32_t fetchdat) pc++; if (fplog) pclog("FSUBRP\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); + tag[(TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(8); return 0; diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h index b4bdb3d..b6eaa11 100644 --- a/src/x87_ops_loadstore.h +++ b/src/x87_ops_loadstore.h @@ -88,6 +88,9 @@ static int opFILDiq_a16(uint32_t fetchdat) temp64 = geteaq(); if (abrt) return 1; if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4)); x87_push((double)temp64); + ST_i64[TOP] = temp64; + tag[TOP] |= TAG_UINT64; + CLOCK_CYCLES(10); return 0; } @@ -100,6 +103,9 @@ static int opFILDiq_a32(uint32_t fetchdat) temp64 = geteaq(); if (abrt) return 1; if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4)); x87_push((double)temp64); + ST_i64[TOP] = temp64; + tag[TOP] |= TAG_UINT64; + CLOCK_CYCLES(10); return 0; } @@ -163,7 +169,10 @@ static int FISTPiq_a16(uint32_t fetchdat) FP_ENTER(); fetch_ea_16(fetchdat); if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr); - temp64 = x87_fround(ST(0)); + if (tag[TOP] & TAG_UINT64) + temp64 = ST_i64[TOP]; + else + temp64 = x87_fround(ST(0)); seteaq(temp64); if (abrt) return 1; x87_pop(); CLOCK_CYCLES(29); @@ -175,7 +184,10 @@ static int FISTPiq_a32(uint32_t fetchdat) FP_ENTER(); fetch_ea_32(fetchdat); if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr); - temp64 = x87_fround(ST(0)); + if (tag[TOP] & TAG_UINT64) + temp64 = ST_i64[TOP]; + else + temp64 = x87_fround(ST(0)); seteaq(temp64); if (abrt) return 1; x87_pop(); CLOCK_CYCLES(29); diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index 6f099c1..96d6434 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -98,14 +98,15 @@ static int FSTOR() eaaddr += 28; break; } - x87_ldmmx(&MM[0]); ST(0)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[1]); ST(1)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[2]); ST(2)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[3]); ST(3)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[4]); ST(4)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[5]); ST(5)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[6]); ST(6)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[7]); ST(7)=x87_ld80(); + x87_ldmmx(&MM[0]); x87_ld_frstor(0); eaaddr += 10; + x87_ldmmx(&MM[1]); x87_ld_frstor(1); eaaddr += 10; + x87_ldmmx(&MM[2]); x87_ld_frstor(2); eaaddr += 10; + x87_ldmmx(&MM[3]); x87_ld_frstor(3); eaaddr += 10; + x87_ldmmx(&MM[4]); x87_ld_frstor(4); eaaddr += 10; + x87_ldmmx(&MM[5]); x87_ld_frstor(5); eaaddr += 10; + x87_ldmmx(&MM[6]); x87_ld_frstor(6); eaaddr += 10; + x87_ldmmx(&MM[7]); x87_ld_frstor(7); + ismmx = 0; /*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times something like this is needed*/ @@ -160,14 +161,14 @@ static int FSAVE() } else { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); + x87_st_fsave(0); eaaddr+=10; + x87_st_fsave(1); eaaddr+=10; + x87_st_fsave(2); eaaddr+=10; + x87_st_fsave(3); eaaddr+=10; + x87_st_fsave(4); eaaddr+=10; + x87_st_fsave(5); eaaddr+=10; + x87_st_fsave(6); eaaddr+=10; + x87_st_fsave(7); } break; case 0x001: /*16-bit protected mode*/ @@ -192,14 +193,14 @@ static int FSAVE() } else { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); + x87_st_fsave(0); eaaddr+=10; + x87_st_fsave(1); eaaddr+=10; + x87_st_fsave(2); eaaddr+=10; + x87_st_fsave(3); eaaddr+=10; + x87_st_fsave(4); eaaddr+=10; + x87_st_fsave(5); eaaddr+=10; + x87_st_fsave(6); eaaddr+=10; + x87_st_fsave(7); } break; case 0x100: /*32-bit real mode*/ @@ -223,14 +224,14 @@ static int FSAVE() } else { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); + x87_st_fsave(0); eaaddr+=10; + x87_st_fsave(1); eaaddr+=10; + x87_st_fsave(2); eaaddr+=10; + x87_st_fsave(3); eaaddr+=10; + x87_st_fsave(4); eaaddr+=10; + x87_st_fsave(5); eaaddr+=10; + x87_st_fsave(6); eaaddr+=10; + x87_st_fsave(7); } break; case 0x101: /*32-bit protected mode*/ @@ -255,14 +256,14 @@ static int FSAVE() } else { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); + x87_st_fsave(0); eaaddr+=10; + x87_st_fsave(1); eaaddr+=10; + x87_st_fsave(2); eaaddr+=10; + x87_st_fsave(3); eaaddr+=10; + x87_st_fsave(4); eaaddr+=10; + x87_st_fsave(5); eaaddr+=10; + x87_st_fsave(6); eaaddr+=10; + x87_st_fsave(7); } break; } @@ -306,10 +307,17 @@ static int opFSTSW_a32(uint32_t fetchdat) static int opFLD(uint32_t fetchdat) { + int old_tag; + uint64_t old_i64; + FP_ENTER(); pc++; if (fplog) pclog("FLD %f\n", ST(fetchdat & 7)); + old_tag = tag[(TOP + fetchdat) & 7]; + old_i64 = ST_i64[(TOP + fetchdat) & 7]; x87_push(ST(fetchdat&7)); + tag[TOP] = old_tag; + ST_i64[TOP] = old_i64; CLOCK_CYCLES(4); return 0; } @@ -317,12 +325,21 @@ static int opFLD(uint32_t fetchdat) static int opFXCH(uint32_t fetchdat) { double td; + uint8_t old_tag; + uint64_t old_i64; FP_ENTER(); pc++; if (fplog) pclog("FXCH\n"); td = ST(0); ST(0) = ST(fetchdat&7); ST(fetchdat&7) = td; + old_tag = tag[TOP]; + tag[TOP] = tag[(TOP + fetchdat) & 7]; + tag[(TOP + fetchdat) & 7] = old_tag; + old_i64 = ST_i64[TOP]; + ST_i64[TOP] = ST_i64[(TOP + fetchdat) & 7]; + ST_i64[(TOP + fetchdat) & 7] = old_i64; + CLOCK_CYCLES(4); return 0; } @@ -333,6 +350,7 @@ static int opFCHS(uint32_t fetchdat) pc++; if (fplog) pclog("FCHS\n"); ST(0) = -ST(0); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(6); return 0; } @@ -343,6 +361,7 @@ static int opFABS(uint32_t fetchdat) pc++; if (fplog) pclog("FABS %f\n", ST(0)); ST(0) = fabs(ST(0)); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(3); return 0; } @@ -450,6 +469,7 @@ static int opF2XM1(uint32_t fetchdat) pc++; if (fplog) pclog("F2XM1\n"); ST(0) = pow(2.0, ST(0)) - 1.0; + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(200); return 0; } @@ -460,6 +480,7 @@ static int opFYL2X(uint32_t fetchdat) pc++; if (fplog) pclog("FYL2X\n"); ST(1) = ST(1) * (log(ST(0)) / log(2.0)); + tag[(TOP + 1) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(250); return 0; @@ -471,6 +492,7 @@ static int opFYL2XP1(uint32_t fetchdat) pc++; if (fplog) pclog("FYL2XP1\n"); ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0)); + tag[(TOP + 1) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(250); return 0; @@ -482,6 +504,7 @@ static int opFPTAN(uint32_t fetchdat) pc++; if (fplog) pclog("FPTAN\n"); ST(0) = tan(ST(0)); + tag[TOP] &= ~TAG_UINT64; x87_push(1.0); npxs &= ~C2; CLOCK_CYCLES(235); @@ -494,6 +517,7 @@ static int opFPATAN(uint32_t fetchdat) pc++; if (fplog) pclog("FPATAN\n"); ST(1) = atan2(ST(1), ST(0)); + tag[(TOP + 1) & 7] &= ~TAG_UINT64; x87_pop(); CLOCK_CYCLES(250); return 0; @@ -527,6 +551,7 @@ static int opFPREM(uint32_t fetchdat) if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); + tag[TOP] &= ~TAG_UINT64; if (fplog) pclog("%f\n", ST(0)); npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) npxs|=C0; @@ -542,6 +567,7 @@ static int opFSQRT(uint32_t fetchdat) pc++; if (fplog) pclog("FSQRT\n"); ST(0) = sqrt(ST(0)); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(83); return 0; } @@ -554,6 +580,7 @@ static int opFSINCOS(uint32_t fetchdat) if (fplog) pclog("FSINCOS\n"); td = ST(0); ST(0) = sin(td); + tag[TOP] &= ~TAG_UINT64; x87_push(cos(td)); npxs &= ~C2; CLOCK_CYCLES(330); @@ -566,6 +593,7 @@ static int opFRNDINT(uint32_t fetchdat) pc++; if (fplog) pclog("FRNDINT %g ", ST(0)); ST(0) = (double)x87_fround(ST(0)); + tag[TOP] &= ~TAG_UINT64; if (fplog) pclog("%g\n", ST(0)); CLOCK_CYCLES(21); return 0; @@ -579,6 +607,7 @@ static int opFSCALE(uint32_t fetchdat) if (fplog) pclog("FSCALE\n"); temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); + tag[TOP] &= ~TAG_UINT64; CLOCK_CYCLES(30); return 0; } @@ -589,6 +618,7 @@ static int opFSIN(uint32_t fetchdat) pc++; if (fplog) pclog("FSIN\n"); ST(0) = sin(ST(0)); + tag[TOP] &= ~TAG_UINT64; npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -600,6 +630,7 @@ static int opFCOS(uint32_t fetchdat) pc++; if (fplog) pclog("FCOS\n"); ST(0) = cos(ST(0)); + tag[TOP] &= ~TAG_UINT64; npxs &= ~C2; CLOCK_CYCLES(300); return 0;