From dda8d374558fa76235a9f8af6cddc2a8e8ac6653 Mon Sep 17 00:00:00 2001 From: Felix Jakschitsch Date: Sun, 28 Jul 2002 15:43:11 +0000 Subject: [PATCH] some FPU emulation added :) Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@82 --- src/fpu/fpu_core_16/instructions.h | 158 +++++++++++++++++++ src/fpu/fpu_core_16/support.h | 89 +++++++++++ src/fpu/fpu_flags.cpp | 235 +++++++++++++++++++++++++++++ src/fpu/fpu_load.h | 21 --- 4 files changed, 482 insertions(+), 21 deletions(-) create mode 100644 src/fpu/fpu_core_16/instructions.h create mode 100644 src/fpu/fpu_core_16/support.h create mode 100644 src/fpu/fpu_flags.cpp delete mode 100644 src/fpu/fpu_load.h diff --git a/src/fpu/fpu_core_16/instructions.h b/src/fpu/fpu_core_16/instructions.h new file mode 100644 index 00000000..271f03f8 --- /dev/null +++ b/src/fpu/fpu_core_16/instructions.h @@ -0,0 +1,158 @@ +/* + * 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; \ +} \ No newline at end of file diff --git a/src/fpu/fpu_core_16/support.h b/src/fpu/fpu_core_16/support.h new file mode 100644 index 00000000..dd6434ae --- /dev/null +++ b/src/fpu/fpu_core_16/support.h @@ -0,0 +1,89 @@ +/* + * 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 FPU_ESC_0 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC0_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC0_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_1 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC1_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC1_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_2 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC2_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC2_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_3 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC3_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC3_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_4 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC4_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC4_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_5 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC5_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC5_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_6 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC6_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC6_EA(rm,eaa); \ + } \ + } + +#define FPU_ESC_7 { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC7_Normal(rm); \ + } else { \ + GetEAa;FPU_ESC7_EA(rm,eaa); \ + } \ + } \ No newline at end of file diff --git a/src/fpu/fpu_flags.cpp b/src/fpu/fpu_flags.cpp new file mode 100644 index 00000000..be463c0c --- /dev/null +++ b/src/fpu/fpu_flags.cpp @@ -0,0 +1,235 @@ +/* + * 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. + */ + +#include "dosbox.h" +#include "fpu.h" +#include "pic.h" + +//extern FPU_Flag_Info fpu_flags; + +bool FPU_get_C3() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c3; + case t_FCOMP: + return (fpu_flags.result.tag==FPUREG_EMPTY||fpu_flags.result.tag==FPUREG_ZERO); + default: + E_Exit("FPU_get_C3 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_C2() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c2; + case t_FCOMP: + return (fpu_flags.result.tag==FPUREG_EMPTY); + default: + E_Exit("FPU_get_C2 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_C1() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c1; + case t_FCOMP: + return false; /* FIXME */ + default: + E_Exit("FPU_get_C1 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_C0() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c0; + case t_FCOMP: + return (fpu_flags.result.tag!=FPUREG_ZERO&&fpu_flags.result.tag!=FPUREG_PNAN); + default: + E_Exit("FPU_get_C0 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_IR() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.ir; + default: + E_Exit("FPU_get_IR Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_SF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.sf; + case t_FCOMP: + return false; /* FIXME */ + default: + E_Exit("FPU_get_SF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_PF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.pf; + default: + E_Exit("FPU_get_PF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_UF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.uf; + default: + E_Exit("FPU_get_UF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_OF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.of; + default: + E_Exit("FPU_get_OF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_ZF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.zf; + case t_FDIV: + case t_FDIVP: + return (fpu_flags.result.tag==FPUREG_PNAN||fpu_flags.result.tag==FPUREG_NNAN); + default: + E_Exit("FPU_get_ZF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_DF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.df; + case t_FCOMP: + return false; /* FIXME */ + default: + E_Exit("FPU_get_DF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_IN(){ + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.in; + case t_FCOMP: + return (fpu_flags.result.tag==FPUREG_EMPTY); /* FIXME */ + default: + E_Exit("FPU_get_IN Unknown %d",fpu_flags.type); + } + return 0; +} diff --git a/src/fpu/fpu_load.h b/src/fpu/fpu_load.h deleted file mode 100644 index b7f6ee0f..00000000 --- a/src/fpu/fpu_load.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ - -INLINE FPUREG Load_Short(EAPoint addr) { - return (Bit16s)mem_readw(addr); -} \ No newline at end of file