diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index 61c68de7..ced68606 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -16,10 +16,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "dosbox.h" +#ifdef C_FPU + #include #include #include "mem.h" -#include "dosbox.h" #include "fpu.h" typedef PhysPt EAPoint; @@ -36,13 +38,16 @@ typedef PhysPt EAPoint; #define SaveMw(off,val) mem_writew(off,val) #define SaveMd(off,val) mem_writed(off,val) +typedef double Real; + +#include "fpu_types.h" +#include "fpu_instructions.h" + FPU_Flag_Info fpu_flags; -FPU_Regs fpu_regs; +FPU_Reg fpu_regs[8]; #define FPU_GetZF fpu_flags.sw.zf = FPU_get_ZF(); -#include "fpu_core_16/instructions.h" - #define FPU_ParseCW(newcw) { \ fpu_flags.cw.ic = ((bool)((newcw&0x1000)>>12)?true:false); \ fpu_flags.cw.rc = (Bit8u)((newcw&0x0C00)>>10); \ @@ -264,8 +269,9 @@ void FPU_ESC7_EA(Bitu rm,PhysPt addr) { void FPU_ESC7_Normal(Bitu rm) { } + void FPU_Init(void) { fpu_flags.type = t_FUNKNOWN; } - +#endif diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h new file mode 100644 index 00000000..49de9d00 --- /dev/null +++ b/src/fpu/fpu_instructions.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2002 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. + */ + +#define FLD(op1) { \ + FPU_GetZF; \ + fpu_flags.type=t_FLD; \ + if(--fpu_flags.sw.tos < 0) \ + fpu_flags.sw.tos = 7; \ + if( fpu_regs.st[fpu_flags.sw.tos].tag != FPUREG_EMPTY ) { \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ + break; \ + } \ + if(op1) \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_VALID; \ + else \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_ZERO; \ + fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = op1; \ +} + +#define FLDST(op1) { \ + FPU_GetZF; \ + fpu_flags.type=t_FLDST; \ + Bit8u reg = fpu_flags.sw.tos+op1; \ + if(reg>7) reg-=8; \ + if(--fpu_flags.sw.tos < 0) \ + fpu_flags.sw.tos = 7; \ + if(fpu_regs.st[fpu_flags.sw.tos].tag!=FPUREG_EMPTY) { \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ + break; \ + } \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = fpu_regs.st[reg].tag; \ + fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = fpu_regs.st[reg].r; \ +} + +#define FPOP { \ + fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_EMPTY; \ + if(++fpu_flags.sw.tos > 7 ) \ + fpu_flags.sw.tos = 0; \ +} +/* FPOP: fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = 0; is not really neccessary */ + +#define FDIVP(op1,op2) { \ + Bit8u reg1 = fpu_flags.sw.tos+op1; \ + Bit8u reg2 = fpu_flags.sw.tos+op2; \ + fpu_flags.type=t_FDIVP; \ + if(reg1>7) reg1-=8; \ + if(reg2>7) reg2-=8; \ + if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + FPOP; \ + break; \ + } \ + if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \ + if(fpu_regs.st[reg1].r > 0) \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \ + else \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + FPOP; \ + break; \ + } \ + if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \ + FPOP; \ + break; \ + } \ + fpu_flags.result.tag = FPUREG_VALID; \ + fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \ + FPOP; \ +} + +#define FDIV(op1,op2) { \ + Bit8u reg1 = fpu_flags.sw.tos+op1; \ + Bit8u reg2 = fpu_flags.sw.tos+op2; \ + fpu_flags.type=t_FDIV; \ + if(reg1>7) reg1-=7; \ + if(reg2>7) reg2-=7; \ + if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + break; \ + } \ + if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \ + if(fpu_regs.st[reg1].r > 0) \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \ + else \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + break; \ + } \ + if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \ + break; \ + } \ + fpu_flags.result.tag = FPUREG_VALID; \ + fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \ +} + +#define FCHS { \ + FPU_GetZF; \ + fpu_flags.type=t_FCHS; \ + if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_PNAN) { \ + fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ + } else if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_NNAN) { \ + fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_PNAN; \ + } else \ + fpu_regs.st[fpu_flags.sw.tos].r = -fpu_regs.st[fpu_flags.sw.tos].r; \ +} + +#define FCOMPP { \ + Bit8u reg = fpu_flags.sw.tos+1; \ + FPU_GetZF; \ + fpu_flags.type=t_FCOMP; \ + if(reg>7) \ + reg=0; \ + if((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)&&(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO)) { \ + fpu_flags.result.r = fpu_regs.st[reg].r - fpu_regs.st[fpu_flags.sw.tos].r; \ + if(fpu_flags.result.r==0) \ + fpu_flags.result.tag = FPUREG_ZERO; \ + else \ + fpu_flags.result.tag = FPUREG_VALID; \ + FPOP; \ + FPOP; \ + return; \ + } else if(((fpu_regs.st[reg].tag==FPUREG_EMPTY)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_EMPTY))||((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO))) { \ + fpu_flags.result.tag = FPUREG_EMPTY; \ + FPOP; \ + FPOP; \ + return; \ + } \ + Bit8s res = (fpu_regs.st[reg].tag-fpu_regs.st[fpu_flags.sw.tos].tag); \ + if(res==0||fpu_flags.cw.ic==0) { \ + fpu_flags.result.tag = FPUREG_ZERO; \ + FPOP; \ + FPOP; \ + return; \ + } else if(res>0) { \ + fpu_flags.result.tag = FPUREG_NNAN; \ + FPOP; \ + FPOP; \ + return; \ + } \ + fpu_flags.result.tag = FPUREG_PNAN; \ + FPOP; \ + FPOP; \ +} + + + + diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h new file mode 100644 index 00000000..1079dbf8 --- /dev/null +++ b/src/fpu/fpu_types.h @@ -0,0 +1,32 @@ + +enum { FPUREG_VALID=0, FPUREG_ZERO, FPUREG_PNAN, FPUREG_NNAN, FPUREG_EMPTY }; + +enum { + t_FLD=0, t_FLDST, t_FDIV, + t_FDIVP, t_FCHS, t_FCOMP, + + t_FUNKNOWN, + t_FNOTDONE, +}; + +struct FPU_Flag_Info { + struct { + Real r; + Bit8u tag; + } var1,var2, result; + struct { + bool bf,c3,c2,c1,c0,ir,sf,pf,uf,of,zf,df,in; + Bit8s tos; + } sw; + struct { + bool ic,ie,sf,pf,uf,of,zf,df,in; + Bit8u rc,pc; + } cw; + Bitu type; + Bitu prev_type; +}; + +struct FPU_Reg { + Real r; + Bit8u tag; +};