diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index c2ce3a4a..169c61ad 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: fpu.cpp,v 1.18 2004-03-29 18:03:02 qbix79 Exp $ */ +/* $Id: fpu.cpp,v 1.19 2004-04-01 08:57:33 qbix79 Exp $ */ #include "dosbox.h" #if C_FPU @@ -61,6 +61,20 @@ INLINE void FPU_SetCW(Bitu word) { fpu.ex_mask = word & 0x3f; } +static Bit16u FPU_GetTag(void){ + Bit16u tag=0; + for(Bitu i=0;i<8;i++) + tag |= ( (fpu.tags[i]&3) <<(2*i)); + return tag; +} + +static void FPU_SetTag(Bit16u tag) +{ + for(Bitu i=0;i<8;i++) + fpu.tags[i]= static_cast((tag >>(2*i))&3); +} + + INLINE Bitu FPU_GET_TOP(void){ @@ -234,12 +248,18 @@ void FPU_ESC1_EA(Bitu rm,PhysPt addr) { } FPU_FPOP(); break; - case 0x05: /*FLDCW */ + case 0x04: /* FLDENV */ + FPU_FLDENV(addr); + break; + case 0x05: /* FLDCW */ { Bit16u temp =mem_readw(addr); FPU_SetCW(temp); } break; + case 0x06: /* FSTENV */ + FPU_FSTENV(addr); + break; case 0x07: /* FNSTCW*/ mem_writew(addr,fpu.cw); break; @@ -432,10 +452,13 @@ void FPU_ESC3_EA(Bitu rm,PhysPt addr) { FPU_FPOP(); break; case 0x05: /* FLD 80 Bits Real */ - FPU_FLD80(addr); + { + Real64 val = FPU_FLD80(addr); + FPU_PUSH(val); + } break; case 0x07: /* FSTP 80 Bits Real */ - FPU_ST80(addr); + FPU_ST80(addr,TOP); FPU_FPOP(); break; default: @@ -461,7 +484,7 @@ void FPU_ESC3_Normal(Bitu rm) { break; case 0x04: //FNSETPM case 0x05: //FRSTPM - LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); +// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); FPU_FNOP(); break; default: @@ -543,6 +566,12 @@ void FPU_ESC5_EA(Bitu rm,PhysPt addr) { mem_writed(addr+4,fpu.regs[TOP].l.upper); FPU_FPOP(); break; + case 0x04: /* FSTOR */ + FPU_FSTOR(addr); + break; + case 0x06: /* FSAVE */ + FPU_FSAVE(addr); + break; case 0x07: /*FNSTSW NG DISAGREES ON THIS*/ FPU_SET_TOP(TOP); mem_writew(addr,fpu.sw); diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index 81a65c46..bc2a7e0c 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: fpu_instructions.h,v 1.16 2004-01-11 09:41:52 qbix79 Exp $ */ +/* $Id: fpu_instructions.h,v 1.17 2004-04-01 08:57:33 qbix79 Exp $ */ static void FPU_FINIT(void) { @@ -265,7 +265,7 @@ static void FPU_FBST(PhysPt addr) #define BIAS80 16383 #define BIAS64 1023 -static void FPU_FLD80(PhysPt addr) +static Real64 FPU_FLD80(PhysPt addr) { struct{ Bit16s begin; @@ -283,20 +283,21 @@ static void FPU_FLD80(PhysPt addr) Bit64s sign = (test.begin &0x8000)?1:0; FPU_Reg result; result.ll= (sign <<63)|(exp64final << 52)| mant64; - FPU_PUSH(result.d); + return result.d; + //mant64= test.mant80/2***64 * 2 **53 } -static void FPU_ST80(PhysPt addr) +static void FPU_ST80(PhysPt addr,Bitu reg) { struct{ Bit16s begin; FPU_Reg eind; } test; - Bit64s sign80= (fpu.regs[TOP].ll&LONGTYPE(0x8000000000000000))?1:0; - Bit64s exp80 = fpu.regs[TOP].ll&LONGTYPE(0x7ff0000000000000); + Bit64s sign80= (fpu.regs[reg].ll&LONGTYPE(0x8000000000000000))?1:0; + Bit64s exp80 = fpu.regs[reg].ll&LONGTYPE(0x7ff0000000000000); Bit64s exp80final= (exp80>>52) - BIAS64 + BIAS80; - Bit64s mant80 = fpu.regs[TOP].ll&LONGTYPE(0x000fffffffffffff); + Bit64s mant80 = fpu.regs[reg].ll&LONGTYPE(0x000fffffffffffff); Bit64s mant80final= (mant80 << 11) | LONGTYPE(0x8000000000000000); test.begin= (static_cast(sign80)<<15)| static_cast(exp80final); test.eind.ll=mant80final; @@ -320,3 +321,51 @@ static void FPU_FSCALE(void){ return; //2^x where x is chopped. } +static void FPU_FSTENV(PhysPt addr){ + if(!cpu.code.big) { + mem_writew(addr+0,static_cast(fpu.cw)); + mem_writew(addr+2,static_cast(fpu.sw)); + mem_writew(addr+4,static_cast(FPU_GetTag())); + } else { + mem_writed(addr+0,static_cast(fpu.cw)); + mem_writed(addr+4,static_cast(fpu.sw)); + mem_writed(addr+8,static_cast(FPU_GetTag())); + } +} + +static void FPU_FLDENV(PhysPt addr){ + Bit16u tag; + Bit32u tagbig; + Bitu cw; + if(!cpu.code.big) { + cw = mem_readw(addr+0); + fpu.sw = mem_readw(addr+2); + tag = mem_readw(addr+4); + } else { + cw = mem_readd(addr+0); + fpu.sw = mem_readd(addr+4); + tagbig = mem_readd(addr+8); + tag = static_cast(tagbig); + } + FPU_SetTag(tag); + FPU_SetCW(cw); +} + +static void FPU_FSAVE(PhysPt addr){ + FPU_FSTENV(addr); + Bitu start=(cpu.code.big?28:14); + for(Bitu i=0;i<8;i++){ + FPU_ST80(addr+start,i); + start+=10; + } +} + +static void FPU_FSTOR(PhysPt addr){ + FPU_FLDENV(addr); + Bitu start=(cpu.code.big?28:14); + for(Bitu i=0;i<8;i++){ + fpu.regs[i].d=FPU_FLD80(addr+start); + start+=10; + } +} +