From 3a059c870b4b708dd310dea77b276185edde67d4 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Sun, 1 Jun 2003 14:51:26 +0000 Subject: [PATCH] fpu updated Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1028 --- src/fpu/fpu.cpp | 274 +++++++++++++++++++++++++++++++++++-- src/fpu/fpu_instructions.h | 82 +++++++++++ src/fpu/fpu_types.h | 4 +- 3 files changed, 351 insertions(+), 9 deletions(-) diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index 70f4b66b..af40c670 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -23,6 +23,7 @@ #include #include "mem.h" #include "fpu.h" +#include "cpu.h" typedef PhysPt EAPoint; @@ -37,8 +38,8 @@ typedef PhysPt EAPoint; #include "fpu_types.h" struct { - FPU_Reg regs[8]; - FPU_Tag tags[8]; + FPU_Reg regs[9]; + FPU_Tag tags[9]; Bitu cw; FPU_Round round; Bitu ex_mask; @@ -52,33 +53,189 @@ INLINE void FPU_SetCW(Bitu word) { fpu.round = (FPU_Round)((word >> 8) & 3); fpu.ex_mask = word & 0x3f; } +INLINE Bitu FPU_GET_TOP(void){ + return (fpu.sw & 0x3800)>>11; +} +INLINE void FPU_SET_TOP(Bitu val){ + fpu.sw &= ~0x3800; + fpu.sw |= (val&7)<<11; + return; +} + #include "fpu_instructions.h" +/* TODO : MAKE REGULAR TREE A DEFINE or a function + : 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*/ +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); + break; + case 0x01: /* FIMUL */ + FPU_FMUL(top, 8); + break; + case 0x02: /* FICOM */ + case 0x03: /* FICOMP */ + LOG(LOG_FPU,LOG_WARN)("ESC EATREE:Unhandled group %d",group); + break; + case 0x04: /* FISUB */ + FPU_FSUB(top,8); + break; + case 0x05: /* FISUBR */ + FPU_FSUBR(top,8); + case 0x06: /* FIDIV */ + FPU_FDIV(top, 8); + break; + case 0x07: /* FIDIVR */ + FPU_FDIVR(top,8); + break; + default: + break; + } + +} 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!)"); + + union { + float f; + Bit32s l; + } blah; + blah.l = mem_readd(addr); + fpu.regs[8].d = static_cast(blah.f); + EATREE(rm); } void FPU_ESC0_Normal(Bitu rm) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - LOG(LOG_FPU,LOG_WARN)("ESC 0:Unhandled group %d subfunction %d",group,sub); + Bitu top = FPU_GET_TOP(); + switch (group){ + case 0x00: /* FADD ST,STi */ + FPU_FADD(top,(top+sub)&7); + break; + case 0x01: /* FMUL ST,STi */ + FPU_FMUL(top,(top+sub)&7); + break; + case 0x02: /* FCOM STi */ + case 0x03: /* FCOMP STi */ + LOG(LOG_FPU,LOG_WARN)("ESC 0:Unhandled group %d subfunction %d",group,sub); + break; + case 0x04: /* FSUB ST,STi */ + FPU_FSUB(top,(top+sub)&7); + break; + case 0x05: /* FSUBR ST,STi */ + FPU_FSUBR(top,(top+sub)&7); + break; + case 0x06: /* FDIV ST,STi */ + FPU_FDIV(top,(top+sub)&7); + break; + case 0x07: /* FDIVR ST,STi */ + FPU_FDIVR(top,(top+sub)&7); + break; + default: + break; + + } } - void FPU_ESC1_EA(Bitu rm,PhysPt addr) { - + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); } void FPU_ESC1_Normal(Bitu rm) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %d subfunction %d",group,sub); + switch (group){ + case 0x00: /* FLD STi */ + { + Bitu top = FPU_GET_TOP(); + FPU_PUSH(fpu.regs[(top+sub)&7].d); + } + break; + case 0x04: + switch(sub){ + case 0x00: /* FCHS */ + case 0x01: /* FABS */ + case 0x02: /* UNKNOWN */ + case 0x03: /* ILLEGAL */ + case 0x04: /* FTST */ + case 0x05: /* FXAM */ + case 0x06: /* FTSTP (cyrix)*/ + case 0x07: /* UNKNOWN */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + case 0x05: + switch(sub){ + case 0x00: /* FLD1 */ + FPU_PUSH(1.0); + break; + case 0x01: /* FLDL2T */ + case 0x02: /* FLDL2E */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + case 0x03: /* FLDPI */ + FPU_PUSH(PI); + break; + case 0x04: /* FLDLG2 */ + case 0x05: /* FLDLN2 */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + case 0x06: /* FLDZ*/ + FPU_PUSH_ZERO(); + break; + case 0x07: /* ILLEGAL */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + case 0x06: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + case 0x07: + switch(sub){ + + + case 0x03: /* FSINCOS */ + FPU_FSINCOS(); + break; + case 0x06: /* FSIN */ + FPU_FSIN(); + break; + case 0x07: /* FCOS */ + FPU_FCOS(); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + } + +// LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); } void FPU_ESC2_EA(Bitu rm,PhysPt addr) { + /* 32 bits integer operants */ + Bit32s blah = mem_readd(addr); + fpu.regs[8].d = static_cast(blah); + EATREE(rm); } void FPU_ESC2_Normal(Bitu rm) { @@ -125,16 +282,52 @@ void FPU_ESC3_Normal(Bitu rm) { void FPU_ESC4_EA(Bitu rm,PhysPt addr) { + /* REGULAR TREE WITH 64 BITS REALS ? double ? */ + E_Exit("how to load a double in esc 4 ea"); + //SEE ESC 0 EA +// double blah = mem_readd(addr); //wrong wrong wrong +// fpu.regs[8].d = static_cast(blah); + EATREE(rm); } void FPU_ESC4_Normal(Bitu rm) { + //LOOKS LIKE number 6 without popping*/ Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - LOG(LOG_FPU,LOG_WARN)("ESC 4:Unhandled group %d subfunction %d",group,sub); + Bitu top = FPU_GET_TOP(); + switch(group){ + case 0x00: /*FADDP STi,ST*/ + FPU_FADD((top+sub)&7,top); + break; + case 0x01: /* FMULP STi,ST*/ + FPU_FMUL((top+sub)&7,top); + break; + case 0x02: /* FCOMP5*/ + case 0x03: /* weird*/ + LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub); + break; + case 0x04: /* FSUBRP STi,ST*/ + FPU_FSUBR((top+sub)&7,top); + break; + case 0x05: /* FSUBP STi,ST*/ + FPU_FSUB((top+sub)&7,top); + break; + case 0x06: /* FDIVRP STi,ST*/ + FPU_FDIVR((top+sub)&7,top); + break; + case 0x07: /* FDIVP STi,ST*/ + FPU_FDIV((top+sub)&7,top); + break; + default: + break; + } } void FPU_ESC5_EA(Bitu rm,PhysPt addr) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + LOG(LOG_FPU,LOG_WARN)("ESC EA 5:Unhandled group %d subfunction %d",group,sub); } void FPU_ESC5_Normal(Bitu rm) { @@ -145,20 +338,85 @@ void FPU_ESC5_Normal(Bitu rm) { void FPU_ESC6_EA(Bitu rm,PhysPt addr) { + /* 16 bit (word integer) operants */ + Bit16s blah = mem_readw(addr); + fpu.regs[8].d = static_cast(blah); + EATREE(rm); } void FPU_ESC6_Normal(Bitu rm) { + /* all P variants working only on registers */ + /* 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); + break; + case 0x01: /* FMULP STi,ST*/ + FPU_FMUL((top+sub)&7,top); + break; + case 0x02: /* FCOMP5*/ + case 0x03: /* weird*/ + LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub); + // maybe return and don't pop + break; + case 0x04: /* FSUBRP STi,ST*/ + FPU_FSUBR((top+sub)&7,top); + break; + case 0x05: /* FSUBP STi,ST*/ + FPU_FSUB((top+sub)&7,top); + break; + case 0x06: /* FDIVRP STi,ST*/ + FPU_FDIVR((top+sub)&7,top); + break; + case 0x07: /* FDIVP STi,ST*/ + FPU_FDIV((top+sub)&7,top); + break; + default: + break; + } + FPU_FPOP(); } void FPU_ESC7_EA(Bitu rm,PhysPt addr) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x03: /*FISTP */ + { Bitu top = FPU_GET_TOP(); + mem_writew(addr,static_cast(fpu.regs[top].d)); + FPU_FPOP(); + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); + } } void FPU_ESC7_Normal(Bitu rm) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch (group){ + case 0x04: + switch(sub){ + case 0x00: /* FNSTSW AX*/ + reg_ax = fpu.sw; + break; + default: + break; + } + break; + default: + break; + } + LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); } -void FPU_Init(void) { +void FPU_Init(Section*) { FPU_FINIT(); } diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index e93ef964..674aaabe 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -35,4 +35,86 @@ static void FPU_FCLEX(void){ static void FPU_FNOP(void){ return; +} + +static void FPU_PUSH(double in){ + Bitu newtop = (FPU_GET_TOP() - 1) &7; + FPU_SET_TOP(newtop); + //actually check if empty + fpu.tags[newtop]=TAG_Valid; + fpu.regs[newtop].d=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; +} +static void FPU_FPOP(void){ + Bitu top = FPU_GET_TOP(); + fpu.tags[top]=TAG_Empty; + //maybe set zero in it as well + FPU_SET_TOP((top+1)&7); + return; +} + +static void FPU_FADD(Bitu op1, Bitu op2){ + fpu.regs[op1].d+=fpu.regs[op2].d; + //flags and such :) + return; +} + +static void FPU_FSIN(void){ + Bitu top = FPU_GET_TOP(); + fpu.regs[top].d = sin(fpu.regs[top].d); + //flags and such :) + return; +} + +static void FPU_FSINCOS(void){ + Bitu top = FPU_GET_TOP(); + fpu.regs[top].d = sin(fpu.regs[top].d); + FPU_PUSH(cos(fpu.regs[top].d)); + //flags and such :) + return; +} + +static void FPU_FCOS(void){ + Bitu top = FPU_GET_TOP(); + fpu.regs[top].d = cos(fpu.regs[top].d); + //flags and such :) + return; +} + +static void FPU_FDIV(Bitu st, Bitu other){ + fpu.regs[st].d= fpu.regs[st].d/fpu.regs[other].d; + //flags and such :) + return; +} + +static void FPU_FDIVR(Bitu st, Bitu other){ + fpu.regs[st].d= fpu.regs[other].d/fpu.regs[st].d; + // flags and such :) + return; +}; + +static void FPU_FMUL(Bitu st, Bitu other){ + fpu.regs[st].d*=fpu.regs[other].d; + //flags and such :) + return; +} + +static void FPU_FSUB(Bitu st, Bitu other){ + fpu.regs[st].d = fpu.regs[st].d - fpu.regs[other].d; + //flags and such :) + return; +} + +static void FPU_FSUBR(Bitu st, Bitu other){ + fpu.regs[st].d= fpu.regs[other].d - fpu.regs[st].d; + //flags and such :) + return; } \ No newline at end of file diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h index ce9cfaec..b7cb434b 100644 --- a/src/fpu/fpu_types.h +++ b/src/fpu/fpu_types.h @@ -36,4 +36,6 @@ enum FPU_Round { ROUND_Down = 1, ROUND_Up = 2, ROUND_Chop = 3 -}; \ No newline at end of file +}; +//get pi from a real library +#define PI 3.1415926535 \ No newline at end of file