From e2f947a1c1478779fb18a4092fce37977782a8bc Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Sat, 19 Jul 2003 05:54:10 +0000 Subject: [PATCH] Changed the TOP system. Added support for 80 bits loading and saving Added support BCD saving Added FPREM Adden FXAM Fixed bug when comparing zero to an nonzero number. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1138 --- src/fpu/fpu.cpp | 211 ++++++++++++++++++------------------- src/fpu/fpu_instructions.h | 160 ++++++++++++++++++++++------ src/fpu/fpu_types.h | 27 +++-- 3 files changed, 246 insertions(+), 152 deletions(-) diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index 636b2f45..66934324 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -27,6 +27,9 @@ typedef PhysPt EAPoint; +#define TOP fpu.top +#define ST(i) ( (fpu.top+ (i) ) & 7 ) + #define LoadMb(off) mem_readb(off) #define LoadMw(off) mem_readw(off) #define LoadMd(off) mem_readd(off) @@ -99,37 +102,39 @@ INLINE Bitu FPU_GET_C3(void){ #include "fpu_instructions.h" /* TODO : ESC6normal => esc4normal+pop or a define as well - : Make a smarter top system. won't matter that much in speed though. - : #define ST fpu.top #define ST(i) (fpu.top+(i))&7 maybe*/ +*/ +/* WATCHIT : ALWAYS UPDATE REGISTERS BEFORE AND AFTER USING THEM + STATUS WORD => FPU_SET_TOP(TOP) BEFORE a read + TOP=FPU_GET_TOP() after a write; + */ static void EATREE(Bitu _rm){ Bitu group=(_rm >> 3) & 7; - Bitu top = FPU_GET_TOP(); /* data will allready be put in register 8 by caller */ switch(group){ case 0x00: /* FIADD */ - FPU_FADD(top, 8); + FPU_FADD(TOP, 8); break; case 0x01: /* FIMUL */ - FPU_FMUL(top, 8); + FPU_FMUL(TOP, 8); break; case 0x02: /* FICOM */ - FPU_FCOM(top,8); + FPU_FCOM(TOP,8); break; case 0x03: /* FICOMP */ - FPU_FCOM(top,8); + FPU_FCOM(TOP,8); FPU_FPOP(); break; case 0x04: /* FISUB */ - FPU_FSUB(top,8); + FPU_FSUB(TOP,8); break; case 0x05: /* FISUBR */ - FPU_FSUBR(top,8); + FPU_FSUBR(TOP,8); case 0x06: /* FIDIV */ - FPU_FDIV(top, 8); + FPU_FDIV(TOP, 8); break; case 0x07: /* FIDIVR */ - FPU_FDIVR(top,8); + FPU_FDIVR(TOP,8); break; default: break; @@ -138,10 +143,7 @@ static void EATREE(Bitu _rm){ } void FPU_ESC0_EA(Bitu rm,PhysPt addr) { - /* REGULAR TREE WITH 32 BITS REALS ? float ? */ - //THIS SHOULD GO ALLRIGHT !?! -// LOG(LOG_FPU, LOG_WARN)("ESC 0 EA used (check the result!)"); - + /* REGULAR TREE WITH 32 BITS REALS -> float */ union { float f; Bit32u l; @@ -154,32 +156,31 @@ void FPU_ESC0_EA(Bitu rm,PhysPt addr) { void FPU_ESC0_Normal(Bitu rm) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - Bitu top = FPU_GET_TOP(); switch (group){ case 0x00: /* FADD ST,STi */ - FPU_FADD(top,(top+sub)&7); + FPU_FADD(TOP,ST(sub)); break; case 0x01: /* FMUL ST,STi */ - FPU_FMUL(top,(top+sub)&7); + FPU_FMUL(TOP,ST(sub)); break; case 0x02: /* FCOM STi */ - FPU_FCOM(top,(top+sub)&7); + FPU_FCOM(TOP,ST(sub)); break; case 0x03: /* FCOMP STi */ - FPU_FCOM(top,(top+sub)&7); + FPU_FCOM(TOP,ST(sub)); FPU_FPOP(); break; case 0x04: /* FSUB ST,STi */ - FPU_FSUB(top,(top+sub)&7); + FPU_FSUB(TOP,ST(sub)); break; case 0x05: /* FSUBR ST,STi */ - FPU_FSUBR(top,(top+sub)&7); + FPU_FSUBR(TOP,ST(sub)); break; case 0x06: /* FDIV ST,STi */ - FPU_FDIV(top,(top+sub)&7); + FPU_FDIV(TOP,ST(sub)); break; case 0x07: /* FDIVR ST,STi */ - FPU_FDIVR(top,(top+sub)&7); + FPU_FDIVR(TOP,ST(sub)); break; default: break; @@ -192,7 +193,7 @@ void FPU_ESC1_EA(Bitu rm,PhysPt addr) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); switch(group){ - case 0x00: /* FLD */ + case 0x00: /* FLD float*/ { union { float f; @@ -206,25 +207,25 @@ void FPU_ESC1_EA(Bitu rm,PhysPt addr) { case 0x01: /* UNKNOWN */ LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); break; - case 0x02: /* FST */ + case 0x02: /* FST float*/ { union { float f; Bit32u l; } blah; //should depend on rounding method - blah.f = static_cast(fpu.regs[FPU_GET_TOP()].d); + blah.f = static_cast(fpu.regs[TOP].d); mem_writed(addr,blah.l); } break; - case 0x03: /* FSTP */ + case 0x03: /* FSTP float*/ { union { float f; Bit32u l; } blah; - blah.f = static_cast(fpu.regs[FPU_GET_TOP()].d); + blah.f = static_cast(fpu.regs[TOP].d); mem_writed(addr,blah.l); } FPU_FPOP(); @@ -250,42 +251,30 @@ void FPU_ESC1_Normal(Bitu rm) { Bitu sub=(rm & 7); switch (group){ case 0x00: /* FLD STi */ - { - Bitu top = FPU_GET_TOP(); - FPU_PUSH(fpu.regs[(top+sub)&7].d); - } + FPU_PUSH(fpu.regs[ST(sub)].d); break; case 0x01: /* FXCH STi */ - { - Bitu top = FPU_GET_TOP(); - FPU_FXCH(top,(top+sub)&7); - } + FPU_FXCH(TOP,ST(sub)); break; case 0x04: switch(sub){ case 0x00: /* FCHS */ - { - Bitu top = FPU_GET_TOP(); - fpu.regs[top].d = -1.0*(fpu.regs[top].d); - } + fpu.regs[TOP].d = -1.0*(fpu.regs[TOP].d); break; case 0x01: /* FABS */ - { - Bitu top = FPU_GET_TOP(); - fpu.regs[top].d = fabs(fpu.regs[top].d); - } + fpu.regs[TOP].d = fabs(fpu.regs[TOP].d); break; case 0x02: /* UNKNOWN */ case 0x03: /* ILLEGAL */ LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); break; case 0x04: /* FTST */ - { Bitu top = FPU_GET_TOP(); - fpu.regs[8].d=0.0; - FPU_FCOM(top,8); - } + fpu.regs[8].d=0.0; + FPU_FCOM(TOP,8); break; case 0x05: /* FXAM */ + FPU_FXAM(); + break; case 0x06: /* FTSTP (cyrix)*/ case 0x07: /* UNKNOWN */ LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); @@ -335,7 +324,9 @@ void FPU_ESC1_Normal(Bitu rm) { break; case 0x07: switch(sub){ - + case 0x00: /* FPREM */ + FPU_FPREM(); + break; case 0x02: /* FSQRT */ FPU_FSQRT(); break; @@ -344,9 +335,9 @@ void FPU_ESC1_Normal(Bitu rm) { break; case 0x04: /* FRNDINT */ { - Bitu top = FPU_GET_TOP(); - Bit32s temp= static_cast(FROUND(fpu.regs[top].d)); - fpu.regs[top].d=static_cast(temp); +//TODO + Bit64s temp= static_cast(FROUND(fpu.regs[TOP].d)); + fpu.regs[TOP].d=static_cast(temp); } //TODO break; @@ -356,6 +347,7 @@ void FPU_ESC1_Normal(Bitu rm) { case 0x07: /* FCOS */ FPU_FCOS(); break; + case 0x01: /* FYL2XP1 */ default: LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); break; @@ -398,15 +390,18 @@ void FPU_ESC3_EA(Bitu rm,PhysPt addr) { break; case 0x02: /* FIST */ - { Bitu top = FPU_GET_TOP(); - mem_writed(addr,static_cast(FROUND(fpu.regs[top].d))); - } + mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); break; case 0x03: /*FISTP */ - { Bitu top = FPU_GET_TOP(); - mem_writed(addr,static_cast(FROUND(fpu.regs[top].d))); - FPU_FPOP(); - } + mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); + FPU_FPOP(); + break; + case 0x05: /* FLD 80 Bits Real */ + FPU_FLD80(addr); + break; + case 0x07: /* FSTP 80 Bits Real */ + FPU_ST80(addr); + FPU_FPOP(); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); @@ -458,32 +453,31 @@ void FPU_ESC4_Normal(Bitu rm) { //LOOKS LIKE number 6 without popping*/ Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - Bitu top = FPU_GET_TOP(); switch(group){ case 0x00: /*FADDP STi,ST*/ - FPU_FADD((top+sub)&7,top); + FPU_FADD(ST(sub),TOP); break; case 0x01: /* FMULP STi,ST*/ - FPU_FMUL((top+sub)&7,top); + FPU_FMUL(ST(sub),TOP); break; case 0x02: /* FCOM*/ - FPU_FCOM(top,(top+sub)&7); + FPU_FCOM(TOP,ST(sub)); break; /* TODO IS THIS ALLRIGHT ????????? (maybe reverse operators) */ case 0x03: /* FCOMP*/ - FPU_FCOM(top,(top+sub)&7); + FPU_FCOM(TOP,ST(sub)); FPU_FPOP(); break; case 0x04: /* FSUBRP STi,ST*/ - FPU_FSUBR((top+sub)&7,top); + FPU_FSUBR(ST(sub),TOP); break; case 0x05: /* FSUBP STi,ST*/ - FPU_FSUB((top+sub)&7,top); + FPU_FSUB(ST(sub),TOP); break; case 0x06: /* FDIVRP STi,ST*/ - FPU_FDIVR((top+sub)&7,top); + FPU_FDIVR(ST(sub),TOP); break; case 0x07: /* FDIVP STi,ST*/ - FPU_FDIV((top+sub)&7,top); + FPU_FDIV(ST(sub),TOP); break; default: break; @@ -494,7 +488,7 @@ void FPU_ESC5_EA(Bitu rm,PhysPt addr) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); switch(group){ - case 0x00: /* FLD */ + case 0x00: /* FLD double real*/ { FPU_Reg blah; blah.l.lower=mem_readd(addr); @@ -502,24 +496,21 @@ void FPU_ESC5_EA(Bitu rm,PhysPt addr) { FPU_PUSH(blah.d); } break; - case 0x01: /* FISTTP */ + case 0x01: /* FISTTP longint*/ LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); break; - case 0x02: /* FIST */ - { Bitu top = FPU_GET_TOP(); - mem_writed(addr,fpu.regs[top].l.lower); - mem_writed(addr+4,fpu.regs[top].l.upper); - } + case 0x02: /* FIST double real*/ + mem_writed(addr,fpu.regs[TOP].l.lower); + mem_writed(addr+4,fpu.regs[TOP].l.upper); break; - case 0x03: /*FISTP */ - { Bitu top = FPU_GET_TOP(); - mem_writed(addr,fpu.regs[top].l.lower); - mem_writed(addr+4,fpu.regs[top].l.upper); - FPU_FPOP(); - } + case 0x03: /*FISTP double real*/ + mem_writed(addr,fpu.regs[TOP].l.lower); + mem_writed(addr+4,fpu.regs[TOP].l.upper); + FPU_FPOP(); break; case 0x07: /*FNSTSW NG DISAGREES ON THIS*/ + FPU_SET_TOP(TOP); mem_writew(addr,fpu.sw); //seems to break all dos4gw games :) break; @@ -531,26 +522,25 @@ void FPU_ESC5_EA(Bitu rm,PhysPt addr) { void FPU_ESC5_Normal(Bitu rm) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - Bitu top = FPU_GET_TOP(); switch(group){ case 0x00: /* FFREE STi */ - fpu.tags[(top+sub)&7]=TAG_Empty; + fpu.tags[ST(sub)]=TAG_Empty; break; case 0x01: /* FXCH STi*/ - FPU_FXCH(top,(top+sub)&7); + FPU_FXCH(TOP,ST(sub)); break; case 0x02: /* FST STi */ - FPU_FST(top,(top+sub)&7); + FPU_FST(TOP,ST(sub)); break; case 0x03: /* FSTP STi*/ - FPU_FST(top,(top+sub)&7); + FPU_FST(TOP,ST(sub)); FPU_FPOP(); break; case 0x04: /* FUCOM STi */ - FPU_FUCOM(top,(top+sub)&7); + FPU_FUCOM(TOP,ST(sub)); break; - case 0x05: - FPU_FUCOM(top,(top+sub)&7); + case 0x05: /*FUCOMP STi */ + FPU_FUCOM(TOP,ST(sub)); FPU_FPOP(); break; default: @@ -572,36 +562,36 @@ void FPU_ESC6_Normal(Bitu rm) { /* get top before switch and pop afterwards */ Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - Bitu top = FPU_GET_TOP(); switch(group){ case 0x00: /*FADDP STi,ST*/ - FPU_FADD((top+sub)&7,top); + FPU_FADD(ST(sub),TOP); break; case 0x01: /* FMULP STi,ST*/ - FPU_FMUL((top+sub)&7,top); + FPU_FMUL(ST(sub),TOP); break; case 0x02: /* FCOMP5*/ - FPU_FCOM(top,(top+sub)&7); + FPU_FCOM(TOP,ST(sub)); break; /* TODO IS THIS ALLRIGHT ????????? */ case 0x03: /* weird*/ /*FCOMPP*/ if(sub != 1){ LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub); + ; break; } - FPU_FCOM(top,(top+sub)&7); - FPU_FPOP(); + FPU_FCOM(TOP,ST(1)); + FPU_FPOP(); /* extra pop at the bottom*/ break; case 0x04: /* FSUBRP STi,ST*/ - FPU_FSUBR((top+sub)&7,top); + FPU_FSUBR(ST(sub),TOP); break; case 0x05: /* FSUBP STi,ST*/ - FPU_FSUB((top+sub)&7,top); + FPU_FSUB(ST(sub),TOP); break; case 0x06: /* FDIVRP STi,ST*/ - FPU_FDIVR((top+sub)&7,top); + FPU_FDIVR(ST(sub),TOP); break; case 0x07: /* FDIVP STi,ST*/ - FPU_FDIV((top+sub)&7,top); + FPU_FDIV(ST(sub),TOP); break; default: break; @@ -627,15 +617,11 @@ void FPU_ESC7_EA(Bitu rm,PhysPt addr) { break; case 0x02: /* FIST Bit16s */ - { Bitu top = FPU_GET_TOP(); - mem_writew(addr,static_cast(FROUND(fpu.regs[top].d))); - } + mem_writew(addr,static_cast(FROUND(fpu.regs[TOP].d))); break; case 0x03: /* FISTP Bit16s */ - { Bitu top = FPU_GET_TOP(); - mem_writew(addr,static_cast(FROUND(fpu.regs[top].d))); - FPU_FPOP(); - } + mem_writew(addr,static_cast(FROUND(fpu.regs[TOP].d))); + FPU_FPOP(); break; case 0x05: /* FILD Bit32s */ { @@ -643,11 +629,13 @@ void FPU_ESC7_EA(Bitu rm,PhysPt addr) { FPU_PUSH( static_cast(blah)); } break; + case 0x06: /* FBSTP packed BCD */ + FPU_FBST(addr); + FPU_FPOP(); + break; case 0x07: /* FISTP Bit32s */ - { Bitu top = FPU_GET_TOP(); - mem_writed(addr,static_cast(FROUND(fpu.regs[top].d))); - FPU_FPOP(); - } + mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); + FPU_FPOP(); break; default: LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); @@ -661,6 +649,7 @@ void FPU_ESC7_Normal(Bitu rm) { case 0x04: switch(sub){ case 0x00: /* FNSTSW AX*/ + FPU_SET_TOP(TOP); reg_ax = fpu.sw; break; default: diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index d5953d30..57d7d6ac 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -21,6 +21,7 @@ static void FPU_FINIT(void) { FPU_SetCW(0x37F); fpu.sw=0; + TOP=FPU_GET_TOP(); fpu.tags[0]=TAG_Empty; fpu.tags[1]=TAG_Empty; fpu.tags[2]=TAG_Empty; @@ -40,26 +41,22 @@ static void FPU_FNOP(void){ } static void FPU_PUSH(double in){ - Bitu newtop = (FPU_GET_TOP() - 1) &7; - FPU_SET_TOP(newtop); + TOP = (TOP - 1) &7; //actually check if empty - fpu.tags[newtop]=TAG_Valid; - fpu.regs[newtop].d=in; + fpu.tags[TOP]=TAG_Valid; + fpu.regs[TOP].d=in; +// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); return; } static void FPU_PUSH_ZERO(void){ - Bitu newtop = (FPU_GET_TOP() - 1) &7; - FPU_SET_TOP(newtop); - //actually check if empty - fpu.tags[newtop]=TAG_Zero; - fpu.regs[newtop].d=0.0; - return; + FPU_PUSH(0.0); + return; //maybe oneday needed } static void FPU_FPOP(void){ - Bitu top = FPU_GET_TOP(); - fpu.tags[top]=TAG_Empty; + fpu.tags[TOP]=TAG_Empty; //maybe set zero in it as well - FPU_SET_TOP((top+1)&7); + TOP = ((TOP+1)&7); +// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d); return; } @@ -70,49 +67,42 @@ static void FPU_FADD(Bitu op1, Bitu op2){ } static void FPU_FSIN(void){ - Bitu top = FPU_GET_TOP(); - fpu.regs[top].d = sin(fpu.regs[top].d); + fpu.regs[TOP].d = sin(fpu.regs[TOP].d); FPU_SET_C2(0); //flags and such :) return; } static void FPU_FSINCOS(void){ - Bitu top = FPU_GET_TOP(); - - double temp = sin(fpu.regs[top].d); - FPU_PUSH(cos(fpu.regs[top].d)); - fpu.regs[top].d = temp; + Real64 temp = fpu.regs[TOP].d; + fpu.regs[TOP].d = sin(temp); + FPU_PUSH(cos(temp)); FPU_SET_C2(0); //flags and such :) return; } static void FPU_FCOS(void){ - Bitu top = FPU_GET_TOP(); - fpu.regs[top].d = cos(fpu.regs[top].d); + fpu.regs[TOP].d = cos(fpu.regs[TOP].d); FPU_SET_C2(0); //flags and such :) return; } static void FPU_FSQRT(void){ - Bitu top = FPU_GET_TOP(); - fpu.regs[top].d = sqrt(fpu.regs[top].d); + fpu.regs[TOP].d = sqrt(fpu.regs[TOP].d); //flags and such :) return; } static void FPU_FPATAN(void){ - Bitu top = FPU_GET_TOP(); - fpu.regs[(top+1)&7].d = atan(fpu.regs[(top+1)&7].d/fpu.regs[top].d); + fpu.regs[ST(1)].d = atan(fpu.regs[ST(1)].d/fpu.regs[TOP].d); FPU_FPOP(); FPU_SET_C2(0); //flags and such :) return; } static void FPU_FPTAN(void){ - Bitu top = FPU_GET_TOP(); - fpu.regs[top].d = tan(fpu.regs[top].d); + fpu.regs[TOP].d = tan(fpu.regs[TOP].d); FPU_PUSH(1.0); FPU_SET_C2(0); //flags and such :) @@ -166,16 +156,16 @@ static void FPU_FST(Bitu st, Bitu other){ static void FPU_FCOM(Bitu st, Bitu other){ if((fpu.tags[st] != TAG_Valid) || (fpu.tags[other] != TAG_Valid)){ - FPU_SET_C3(1);FPU_SET_C2(1);FPU_SET_C0(1);return; + FPU_SET_C3(1);FPU_SET_C1(1);FPU_SET_C0(1);return; } if(fpu.regs[st].d == fpu.regs[other].d){ - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);return; + FPU_SET_C3(1);FPU_SET_C1(0);FPU_SET_C0(0);return; } if(fpu.regs[st].d < fpu.regs[other].d){ - FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(1);return; + FPU_SET_C3(0);FPU_SET_C1(0);FPU_SET_C0(1);return; } // st > other - FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(0);return; + FPU_SET_C3(0);FPU_SET_C1(0);FPU_SET_C0(0);return; } static void FPU_FUCOM(Bitu st, Bitu other){ @@ -202,3 +192,109 @@ static double FROUND(double in){ break; } } + +static void FPU_FPREM(void){ + Real64 valtop = fpu.regs[TOP].d; + Real64 valdiv = fpu.regs[ST(1)].d; + Real64 res = floor(valtop/valdiv); + res=valtop - res*valdiv; + fpu.regs[TOP].d = res; + FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C1(0);FPU_SET_C0(0); +} + +static void FPU_FXAM(void){ + if(fpu.tags[TOP] == TAG_Empty) + { + FPU_SET_C3(1);FPU_SET_C0(1); + return; + } + if(fpu.regs[TOP].ll & 0x8000000000000000) //sign + { + FPU_SET_C1(1); + } + else + { + FPU_SET_C1(0); + } + if(fpu.regs[TOP].d == 0.0) //zero or normalized number. + { + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); + } + else{ + FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); + } +} + +static void FPU_FBST(PhysPt addr) +{ + FPU_Reg val = fpu.regs[TOP]; + bool sign = false; + if(val.d<0.0){ //sign + sign=true; + val.d=-val.d; + } + //numbers from back to front + Real64 temp=val.d; + Bitu p; + for(Bitu i=0;i<9;i++){ + val.d=temp; + temp = static_cast(static_cast(floor(val.d/10.0))); + p = static_cast(val.d - 10.0*temp); + val.d=temp; + temp = static_cast(static_cast(floor(val.d/10.0))); + p |= (static_cast(val.d - 10.0*temp)<<4); + + mem_writeb(addr+i,p); + } + val.d=temp; + temp = static_cast(static_cast(floor(val.d/10.0))); + p = static_cast(val.d - 10.0*temp); + if(sign) + p|=0x80; + mem_writeb(addr+9,p); +} + +#define BIAS80 16383 +#define BIAS64 1023 + +static void FPU_FLD80(PhysPt addr) +{ + struct{ + Bit16s begin; + FPU_Reg eind; + } test; + test.eind.l.lower=mem_readd(addr); + test.eind.l.upper =mem_readd(addr+4); + test.begin=mem_readw(addr+8); + + Bit64s exp64= (((test.begin & 0x7fff) - BIAS80)); + Bit64s blah= ((exp64 >0)?exp64:-exp64)&0x3ff; + Bit64s exp64final= ((exp64 >0)?blah:-blah) +BIAS64; + + Bit64s mant64= (test.eind.ll >> 11) & 0xfffffffffffff; + Bit64s sign = (test.begin &0x8000)?1:0; + FPU_Reg result; + result.ll= (sign <<63)|(exp64final << 52)| mant64; + FPU_PUSH(result.d); + //mant64= test.mant80/2***64 * 2 **53 +} + +static void FPU_ST80(PhysPt addr) +{ + struct{ + Bit16s begin; + FPU_Reg eind; + } test; + Bit64s sign80= (fpu.regs[TOP].ll&0x8000000000000000)?1:0; + Bit64s exp80 = fpu.regs[TOP].ll&0x7ff0000000000000; + Bit64s exp80final= (exp80>>52) - BIAS64 + BIAS80; + Bit64s mant80 = fpu.regs[TOP].ll&0x000fffffffffffff; + Bit64s mant80final= (mant80 << 11) | 0x8000000000000000; + test.begin= (static_cast(sign80)<<15)| static_cast(exp80final); + test.eind.ll=mant80final; + mem_writed(addr,test.eind.l.lower); + mem_writed(addr+4,test.eind.l.upper); + mem_writew(addr+8,test.begin); +} + + diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h index 7cec00b2..c459feb8 100644 --- a/src/fpu/fpu_types.h +++ b/src/fpu/fpu_types.h @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2002-2003 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + typedef union { double d; #ifndef WORDS_BIGENDIAN @@ -14,15 +32,6 @@ typedef union { Bit64s ll; } FPU_Reg; -/* the following deal with IEEE double-precision numbers */ -#define MAXEXPD 0x7ff -#define EXPBIAS 1023 -#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) -#define SIGND(fp) ((fp.l.upper) & 0x80000000) -#define MANTD(fp) (fp.ll & ((1LL << 52) - 1)) -#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20) - - enum FPU_Tag { TAG_Valid = 0, TAG_Zero = 1,