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
This commit is contained in:
parent
4e62907e37
commit
e2f947a1c1
3 changed files with 246 additions and 152 deletions
211
src/fpu/fpu.cpp
211
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<float>(fpu.regs[FPU_GET_TOP()].d);
|
||||
blah.f = static_cast<float>(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<float>(fpu.regs[FPU_GET_TOP()].d);
|
||||
blah.f = static_cast<float>(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<Bit32s>(FROUND(fpu.regs[top].d));
|
||||
fpu.regs[top].d=static_cast<double>(temp);
|
||||
//TODO
|
||||
Bit64s temp= static_cast<Bit64s>(FROUND(fpu.regs[TOP].d));
|
||||
fpu.regs[TOP].d=static_cast<double>(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<Bit32s>(FROUND(fpu.regs[top].d)));
|
||||
}
|
||||
mem_writed(addr,static_cast<Bit32s>(FROUND(fpu.regs[TOP].d)));
|
||||
break;
|
||||
case 0x03: /*FISTP */
|
||||
{ Bitu top = FPU_GET_TOP();
|
||||
mem_writed(addr,static_cast<Bit32s>(FROUND(fpu.regs[top].d)));
|
||||
FPU_FPOP();
|
||||
}
|
||||
mem_writed(addr,static_cast<Bit32s>(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<Bit16s>(FROUND(fpu.regs[top].d)));
|
||||
}
|
||||
mem_writew(addr,static_cast<Bit16s>(FROUND(fpu.regs[TOP].d)));
|
||||
break;
|
||||
case 0x03: /* FISTP Bit16s */
|
||||
{ Bitu top = FPU_GET_TOP();
|
||||
mem_writew(addr,static_cast<Bit16s>(FROUND(fpu.regs[top].d)));
|
||||
FPU_FPOP();
|
||||
}
|
||||
mem_writew(addr,static_cast<Bit16s>(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<double>(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<Bit32s>(FROUND(fpu.regs[top].d)));
|
||||
FPU_FPOP();
|
||||
}
|
||||
mem_writed(addr,static_cast<Bit32s>(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:
|
||||
|
|
|
@ -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<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
|
||||
p = static_cast<Bitu>(val.d - 10.0*temp);
|
||||
val.d=temp;
|
||||
temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
|
||||
p |= (static_cast<Bitu>(val.d - 10.0*temp)<<4);
|
||||
|
||||
mem_writeb(addr+i,p);
|
||||
}
|
||||
val.d=temp;
|
||||
temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
|
||||
p = static_cast<Bitu>(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<Bit16s>(sign80)<<15)| static_cast<Bit16s>(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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue