New FPU opcode handling layout
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1020
This commit is contained in:
parent
2667e412a2
commit
b81081ed2b
5 changed files with 77 additions and 580 deletions
|
@ -1,4 +1,4 @@
|
|||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
noinst_LIBRARIES = libfpu.a
|
||||
libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h
|
||||
libfpu_a_SOURCES = fpu.cpp fpu_types.h fpu_instructions.h
|
203
src/fpu/fpu.cpp
203
src/fpu/fpu.cpp
|
@ -30,101 +30,32 @@ typedef PhysPt EAPoint;
|
|||
#define LoadMw(off) mem_readw(off)
|
||||
#define LoadMd(off) mem_readd(off)
|
||||
|
||||
#define LoadMbs(off) (Bit8s)(LoadMb(off))
|
||||
#define LoadMws(off) (Bit16s)(LoadMw(off))
|
||||
#define LoadMds(off) (Bit32s)(LoadMd(off))
|
||||
|
||||
#define SaveMb(off,val) mem_writeb(off,val)
|
||||
#define SaveMw(off,val) mem_writew(off,val)
|
||||
#define SaveMd(off,val) mem_writed(off,val)
|
||||
|
||||
typedef double Real;
|
||||
|
||||
#include "fpu_types.h"
|
||||
|
||||
struct {
|
||||
FPU_Reg regs[8];
|
||||
FPU_Tag tags[8];
|
||||
Bitu cw;
|
||||
FPU_Round round;
|
||||
Bitu ex_mask;
|
||||
Bitu sw;
|
||||
Bitu top;
|
||||
|
||||
} fpu;
|
||||
|
||||
INLINE void FPU_SetCW(Bitu word) {
|
||||
fpu.cw = word;
|
||||
fpu.round = (FPU_Round)((word >> 8) & 3);
|
||||
fpu.ex_mask = word & 0x3f;
|
||||
}
|
||||
|
||||
#include "fpu_instructions.h"
|
||||
|
||||
FPU_Flag_Info fpu_flags;
|
||||
FPU_Reg fpu_regs[8];
|
||||
|
||||
#define FPU_GetZF fpu_flags.sw.zf = FPU_get_ZF();
|
||||
|
||||
#define FPU_ParseCW(newcw) { \
|
||||
fpu_flags.cw.ic = ((bool)((newcw&0x1000)>>12)?true:false); \
|
||||
fpu_flags.cw.rc = (Bit8u)((newcw&0x0C00)>>10); \
|
||||
fpu_flags.cw.pc = (Bit8u)((newcw&0x0300)>>8); \
|
||||
fpu_flags.cw.ie = ((bool)((newcw&0x0080)>>7)?true:false); \
|
||||
fpu_flags.cw.sf = ((bool)((newcw&0x0040)>>6)?true:false); \
|
||||
fpu_flags.cw.pf = ((bool)((newcw&0x0020)>>5)?true:false); \
|
||||
fpu_flags.cw.uf = ((bool)((newcw&0x0010)>>4)?true:false); \
|
||||
fpu_flags.cw.of = ((bool)((newcw&0x0008)>>3)?true:false); \
|
||||
fpu_flags.cw.zf = ((bool)((newcw&0x0004)>>2)?true:false); \
|
||||
fpu_flags.cw.df = ((bool)((newcw&0x0002)>>1)?true:false); \
|
||||
fpu_flags.cw.in = ((bool)(newcw&0x0001)?true:false); \
|
||||
}
|
||||
|
||||
#define FPU_makeCW(newcw) { \
|
||||
newcw = (Bit16u)fpu_flags.cw.in; \
|
||||
newcw |= (fpu_flags.cw.df<<1); \
|
||||
newcw |= (fpu_flags.cw.zf<<2); \
|
||||
newcw |= (fpu_flags.cw.of<<3); \
|
||||
newcw |= (fpu_flags.cw.uf<<4); \
|
||||
newcw |= (fpu_flags.cw.pf<<5); \
|
||||
newcw |= (fpu_flags.cw.sf<<6); \
|
||||
newcw |= (fpu_flags.cw.ie<<7); \
|
||||
newcw |= (fpu_flags.cw.pc<<8); \
|
||||
newcw |= (fpu_flags.cw.rc<<10); \
|
||||
newcw |= (fpu_flags.cw.ic<<12); \
|
||||
}
|
||||
|
||||
#define FPU_ParseSW(newsw) { \
|
||||
fpu_flags.sw.bf = ((bool)((newsw&0x8000)>>15)?true:false); \
|
||||
fpu_flags.sw.c3 = ((bool)((newsw&0x4000)>>14)?true:false); \
|
||||
fpu_flags.sw.tos = (Bit8s)((newsw&0x3800)>>11); \
|
||||
fpu_flags.sw.c2 = ((bool)((newsw&0x0400)>>10)?true:false); \
|
||||
fpu_flags.sw.c1 = ((bool)((newsw&0x0200)>>9)?true:false); \
|
||||
fpu_flags.sw.c0 = ((bool)((newsw&0x0100)>>8)?true:false); \
|
||||
fpu_flags.sw.ir = ((bool)((newsw&0x0080)>>7)?true:false); \
|
||||
fpu_flags.sw.sf = ((bool)((newsw&0x0040)>>6)?true:false); \
|
||||
fpu_flags.sw.pf = ((bool)((newsw&0x0020)>>5)?true:false); \
|
||||
fpu_flags.sw.uf = ((bool)((newsw&0x0010)>>4)?true:false); \
|
||||
fpu_flags.sw.of = ((bool)((newsw&0x0008)>>3)?true:false); \
|
||||
fpu_flags.sw.zf = ((bool)((newsw&0x0004)>>2)?true:false); \
|
||||
fpu_flags.sw.df = ((bool)((newsw&0x0002)>>1)?true:false); \
|
||||
fpu_flags.sw.in = ((bool)(newsw&0x0001)?true:false); \
|
||||
}
|
||||
|
||||
#define FPU_makeSW(newsw) { \
|
||||
newsw = (Bit16u)fpu_flags.sw.in; \
|
||||
newsw |= (fpu_flags.sw.df<<1); \
|
||||
newsw |= (fpu_flags.sw.zf<<2); \
|
||||
newsw |= (fpu_flags.sw.of<<3); \
|
||||
newsw |= (fpu_flags.sw.uf<<4); \
|
||||
newsw |= (fpu_flags.sw.pf<<5); \
|
||||
newsw |= (fpu_flags.sw.sf<<6); \
|
||||
newsw |= (fpu_flags.sw.ir<<7); \
|
||||
newsw |= (fpu_flags.sw.c0<<8); \
|
||||
newsw |= (fpu_flags.sw.c1<<9); \
|
||||
newsw |= (fpu_flags.sw.c2<<10); \
|
||||
newsw |= (fpu_flags.sw.tos<<11); \
|
||||
newsw |= (fpu_flags.sw.c3<<14); \
|
||||
newsw |= (fpu_flags.sw.bf<<15); \
|
||||
}
|
||||
|
||||
#define FPU_LOADFLAGS { \
|
||||
fpu_flags.sw.bf = false; \
|
||||
fpu_flags.sw.c3 = FPU_get_C3(); \
|
||||
fpu_flags.sw.c2 = FPU_get_C2(); \
|
||||
fpu_flags.sw.c1 = FPU_get_C1(); \
|
||||
fpu_flags.sw.c0 = FPU_get_C0(); \
|
||||
fpu_flags.sw.ir = FPU_get_IR(); \
|
||||
fpu_flags.sw.sf = FPU_get_SF(); \
|
||||
fpu_flags.sw.pf = FPU_get_PF(); \
|
||||
fpu_flags.sw.uf = FPU_get_UF(); \
|
||||
fpu_flags.sw.of = FPU_get_OF(); \
|
||||
fpu_flags.sw.zf = FPU_get_ZF(); \
|
||||
fpu_flags.sw.df = FPU_get_DF(); \
|
||||
fpu_flags.sw.in = FPU_get_IN(); \
|
||||
}
|
||||
|
||||
void FPU_ESC0_EA(Bitu rm,PhysPt addr) {
|
||||
}
|
||||
|
@ -134,50 +65,10 @@ void FPU_ESC0_Normal(Bitu rm) {
|
|||
|
||||
|
||||
void FPU_ESC1_EA(Bitu rm,PhysPt addr) {
|
||||
Bit16u cw;
|
||||
Bitu opcode = (rm&0x38)>>3;
|
||||
|
||||
switch(opcode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
break;
|
||||
case 5:
|
||||
FPU_ParseCW(LoadMw(addr)); /* FLDCW */
|
||||
break;
|
||||
case 7: /* FSTCW */
|
||||
FPU_makeCW(cw);
|
||||
SaveMw(addr,cw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FPU_ESC1_Normal(Bitu rm) {
|
||||
Bitu opcode = (rm&0xF0);
|
||||
|
||||
switch(opcode) {
|
||||
case 0xC0:
|
||||
// if(rm&8)
|
||||
// else
|
||||
FLDST(rm-0xC0); /* FLDST */
|
||||
break;
|
||||
case 0xD0:
|
||||
break;
|
||||
}
|
||||
switch(rm) {
|
||||
case 0xE0: /* FCHS */
|
||||
FCHS;
|
||||
break;
|
||||
case 0xE8: /* FLD1 */
|
||||
FLD(1);
|
||||
break;
|
||||
case 0xEE: /* FLDZ */
|
||||
FLD(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -192,14 +83,18 @@ void FPU_ESC3_EA(Bitu rm,PhysPt addr) {
|
|||
}
|
||||
|
||||
void FPU_ESC3_Normal(Bitu rm) {
|
||||
switch( rm ) {
|
||||
case 0xE3: /* FINIT */
|
||||
FPU_ParseCW(0x037F);
|
||||
for(int i=0;i<8;i++) {
|
||||
fpu_regs.st[i].r = 0;
|
||||
fpu_regs.st[i].tag = FPUREG_EMPTY;
|
||||
}
|
||||
Bitu group=(rm >> 3) & 7;
|
||||
Bitu sub=(rm & 7);
|
||||
switch (group) {
|
||||
case 0x04:
|
||||
switch (sub) {
|
||||
case 0x03: //FINIT
|
||||
FPU_FINIT();
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub);
|
||||
}
|
||||
LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d",group);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,23 +107,6 @@ void FPU_ESC4_Normal(Bitu rm) {
|
|||
|
||||
|
||||
void FPU_ESC5_EA(Bitu rm,PhysPt addr) {
|
||||
Bit16u sw;
|
||||
Bitu opcode = (rm&0x38)>>3;
|
||||
|
||||
switch(opcode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7: /* FSTSW */
|
||||
FPU_LOADFLAGS;
|
||||
FPU_makeSW(sw);
|
||||
SaveMw(addr,sw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FPU_ESC5_Normal(Bitu rm) {
|
||||
|
@ -239,27 +117,6 @@ void FPU_ESC6_EA(Bitu rm,PhysPt addr) {
|
|||
}
|
||||
|
||||
void FPU_ESC6_Normal(Bitu rm) {
|
||||
Bitu opcode = (rm&0xF0);
|
||||
|
||||
if(rm==0xD9) { /* FCOMPP */
|
||||
FCOMPP;
|
||||
return;
|
||||
}
|
||||
switch(opcode) {
|
||||
case 0xC0:
|
||||
// if(rm&8)
|
||||
break;
|
||||
case 0xD0:
|
||||
// if(rm&8)
|
||||
break;
|
||||
case 0xE0:
|
||||
// if(rm&8)
|
||||
break;
|
||||
case 0xF0:
|
||||
if(rm&8)
|
||||
FDIVP(rm-0xF8,0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -271,7 +128,7 @@ void FPU_ESC7_Normal(Bitu rm) {
|
|||
|
||||
|
||||
void FPU_Init(void) {
|
||||
fpu_flags.type = t_FUNKNOWN;
|
||||
FPU_FINIT();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,235 +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.
|
||||
*/
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "fpu.h"
|
||||
#include "pic.h"
|
||||
#include "fpu_types.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;
|
||||
}
|
|
@ -16,147 +16,16 @@
|
|||
* 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; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void FPU_FINIT(void) {
|
||||
FPU_SetCW(0x37);
|
||||
fpu.sw=0;
|
||||
fpu.tags[0]=TAG_Empty;
|
||||
fpu.tags[1]=TAG_Empty;
|
||||
fpu.tags[2]=TAG_Empty;
|
||||
fpu.tags[3]=TAG_Empty;
|
||||
fpu.tags[4]=TAG_Empty;
|
||||
fpu.tags[5]=TAG_Empty;
|
||||
fpu.tags[6]=TAG_Empty;
|
||||
fpu.tags[7]=TAG_Empty;
|
||||
}
|
|
@ -1,33 +1,39 @@
|
|||
typedef union {
|
||||
double d;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
struct {
|
||||
Bit32u lower;
|
||||
Bit32s upper;
|
||||
} l;
|
||||
#else
|
||||
struct {
|
||||
Bit32s upper;
|
||||
Bit32u lower;
|
||||
} l;
|
||||
#endif
|
||||
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 { 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
|
||||
enum FPU_Tag {
|
||||
TAG_Valid = 0,
|
||||
TAG_Zero = 1,
|
||||
TAG_Weird = 2,
|
||||
TAG_Empty = 3
|
||||
};
|
||||
|
||||
struct FPU_Flag_Info {
|
||||
struct {
|
||||
Real64 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 {
|
||||
Real64 r;
|
||||
Bit8u tag;
|
||||
};
|
||||
enum FPU_Round {
|
||||
ROUND_Nearest = 0,
|
||||
ROUND_Down = 1,
|
||||
ROUND_Up = 2,
|
||||
ROUND_Chop = 3
|
||||
};
|
Loading…
Add table
Reference in a new issue