2009-05-02 23:03:37 +02:00
|
|
|
/*
|
2009-05-03 00:28:34 +02:00
|
|
|
* Copyright (C) 2002-2007 The DOSBox Team
|
2009-05-02 23:03:37 +02:00
|
|
|
*
|
|
|
|
* 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
|
2009-05-03 00:02:15 +02:00
|
|
|
* GNU General Public License for more details.
|
2009-05-02 23:03:37 +02:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2009-05-03 00:28:34 +02:00
|
|
|
/* $Id: fpu.cpp,v 1.29 2007/01/08 19:45:39 qbix79 Exp $ */
|
2009-05-02 23:53:27 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
#include "dosbox.h"
|
|
|
|
#if C_FPU
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
2009-05-02 23:43:00 +02:00
|
|
|
#include "cross.h"
|
2009-05-02 23:03:37 +02:00
|
|
|
#include "mem.h"
|
2009-05-02 23:12:18 +02:00
|
|
|
#include "fpu.h"
|
2009-05-02 23:43:00 +02:00
|
|
|
#include "cpu.h"
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_rec fpu;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-03 00:28:34 +02:00
|
|
|
void FPU_FLDCW(PhysPt addr){
|
|
|
|
Bit16u temp = mem_readw(addr);
|
|
|
|
FPU_SetCW(temp);
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-03 00:28:34 +02:00
|
|
|
|
|
|
|
Bit16u FPU_GetTag(void){
|
2009-05-03 00:02:15 +02:00
|
|
|
Bit16u tag=0;
|
|
|
|
for(Bitu i=0;i<8;i++)
|
|
|
|
tag |= ( (fpu.tags[i]&3) <<(2*i));
|
|
|
|
return tag;
|
|
|
|
}
|
|
|
|
|
2009-05-03 00:18:08 +02:00
|
|
|
#if C_FPU_X86
|
|
|
|
#include "fpu_instructions_x86.h"
|
|
|
|
#else
|
2009-05-02 23:43:00 +02:00
|
|
|
#include "fpu_instructions.h"
|
2009-05-03 00:18:08 +02:00
|
|
|
#endif
|
2009-05-02 23:43:00 +02:00
|
|
|
|
|
|
|
/* WATCHIT : ALWAYS UPDATE REGISTERS BEFORE AND AFTER USING THEM
|
|
|
|
STATUS WORD => FPU_SET_TOP(TOP) BEFORE a read
|
2009-05-03 00:02:15 +02:00
|
|
|
TOP=FPU_GET_TOP() after a write;
|
2009-05-02 23:43:00 +02:00
|
|
|
*/
|
2009-05-03 00:18:08 +02:00
|
|
|
|
2009-05-02 23:43:00 +02:00
|
|
|
static void EATREE(Bitu _rm){
|
|
|
|
Bitu group=(_rm >> 3) & 7;
|
|
|
|
switch(group){
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x00: /* FADD */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FADD_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01: /* FMUL */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FMUL_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x02: /* FCOM */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FCOM_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x03: /* FCOMP */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FCOM_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x04: /* FSUB */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FSUB_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x05: /* FSUBR */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FSUBR_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x06: /* FDIV */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FDIV_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x07: /* FDIVR */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FDIVR_EA(TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
void FPU_ESC0_EA(Bitu rm,PhysPt addr) {
|
2009-05-03 00:18:08 +02:00
|
|
|
/* REGULAR TREE WITH 32 BITS REALS */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FLD_F32_EA(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
EATREE(rm);
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC0_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch (group){
|
|
|
|
case 0x00: /* FADD ST,STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FADD(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x01: /* FMUL ST,STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FMUL(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x02: /* FCOM STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCOM(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x03: /* FCOMP STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCOM(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
case 0x04: /* FSUB ST,STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FSUB(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x05: /* FSUBR ST,STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FSUBR(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x06: /* FDIV ST,STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FDIV(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x07: /* FDIVR ST,STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FDIVR(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
|
|
|
|
void FPU_ESC1_EA(Bitu rm,PhysPt addr) {
|
2009-05-02 23:43:00 +02:00
|
|
|
// floats
|
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
|
|
|
case 0x00: /* FLD float*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FLD_F32(addr,TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x01: /* UNKNOWN */
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
case 0x02: /* FST float*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST_F32(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x03: /* FSTP float*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST_F32(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
2009-05-03 00:02:15 +02:00
|
|
|
case 0x04: /* FLDENV */
|
|
|
|
FPU_FLDENV(addr);
|
|
|
|
break;
|
|
|
|
case 0x05: /* FLDCW */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FLDCW(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:02:15 +02:00
|
|
|
case 0x06: /* FSTENV */
|
|
|
|
FPU_FSTENV(addr);
|
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x07: /* FNSTCW*/
|
|
|
|
mem_writew(addr,fpu.cw);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC1_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch (group){
|
|
|
|
case 0x00: /* FLD STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
{
|
|
|
|
Bitu reg_from=STV(sub);
|
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FST(reg_from, TOP);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01: /* FXCH STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FXCH(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x02: /* FNOP */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FNOP();
|
2009-05-02 23:53:27 +02:00
|
|
|
break;
|
|
|
|
case 0x03: /* FSTP STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST(TOP,STV(sub));
|
|
|
|
FPU_FPOP();
|
2009-05-02 23:53:27 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x04:
|
|
|
|
switch(sub){
|
|
|
|
case 0x00: /* FCHS */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCHS();
|
2009-05-02 23:12:18 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01: /* FABS */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FABS();
|
2009-05-02 23:12:18 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x02: /* UNKNOWN */
|
|
|
|
case 0x03: /* ILLEGAL */
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
|
|
|
|
break;
|
|
|
|
case 0x04: /* FTST */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FTST();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x05: /* FXAM */
|
|
|
|
FPU_FXAM();
|
2009-05-02 23:12:18 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x06: /* FTSTP (cyrix)*/
|
|
|
|
case 0x07: /* UNKNOWN */
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
|
2009-05-02 23:12:18 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x05:
|
|
|
|
switch(sub){
|
|
|
|
case 0x00: /* FLD1 */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLD1();
|
2009-05-02 23:12:18 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x01: /* FLDL2T */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLDL2T();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x02: /* FLDL2E */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLDL2E();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x03: /* FLDPI */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLDPI();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x04: /* FLDLG2 */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLDLG2();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x05: /* FLDLN2 */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLDLN2();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x06: /* FLDZ*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FLDZ();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x07: /* ILLEGAL */
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x06:
|
|
|
|
switch(sub){
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x00: /* F2XM1 */
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_F2XM1();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01: /* FYL2X */
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FYL2X();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x02: /* FPTAN */
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPTAN();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x03: /* FPATAN */
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPATAN();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x04: /* FXTRACT */
|
2009-05-03 00:08:43 +02:00
|
|
|
FPU_FXTRACT();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x05: /* FPREM1 */
|
|
|
|
FPU_FPREM1();
|
|
|
|
break;
|
|
|
|
case 0x06: /* FDECSTP */
|
|
|
|
TOP = (TOP - 1) & 7;
|
|
|
|
break;
|
|
|
|
case 0x07: /* FINCSTP */
|
|
|
|
TOP = (TOP + 1) & 7;
|
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
default:
|
2009-05-03 00:18:08 +02:00
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
|
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x07:
|
|
|
|
switch(sub){
|
|
|
|
case 0x00: /* FPREM */
|
|
|
|
FPU_FPREM();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01: /* FYL2XP1 */
|
|
|
|
FPU_FYL2XP1();
|
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x02: /* FSQRT */
|
|
|
|
FPU_FSQRT();
|
|
|
|
break;
|
|
|
|
case 0x03: /* FSINCOS */
|
|
|
|
FPU_FSINCOS();
|
|
|
|
break;
|
|
|
|
case 0x04: /* FRNDINT */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FRNDINT();
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x05: /* FSCALE */
|
|
|
|
FPU_FSCALE();
|
|
|
|
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);
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FPU_ESC2_EA(Bitu rm,PhysPt addr) {
|
2009-05-02 23:43:00 +02:00
|
|
|
/* 32 bits integer operants */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FLD_I32_EA(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
EATREE(rm);
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC2_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
2009-05-03 00:02:15 +02:00
|
|
|
switch(group){
|
|
|
|
case 0x05:
|
|
|
|
switch(sub){
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01: /* FUCOMPP */
|
|
|
|
FPU_FUCOM(TOP,STV(1));
|
2009-05-03 00:02:15 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
void FPU_ESC3_EA(Bitu rm,PhysPt addr) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x00: /* FILD */
|
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FLD_I32(addr,TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01: /* FISTTP */
|
2009-05-02 23:43:00 +02:00
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x02: /* FIST */
|
|
|
|
FPU_FST_I32(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x03: /* FISTP */
|
|
|
|
FPU_FST_I32(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
case 0x05: /* FLD 80 Bits Real */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FLD_F80(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x07: /* FSTP 80 Bits Real */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST_F80(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC3_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch (group) {
|
|
|
|
case 0x04:
|
|
|
|
switch (sub) {
|
|
|
|
case 0x00: //FNENI
|
|
|
|
case 0x01: //FNDIS
|
|
|
|
LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub);
|
|
|
|
break;
|
|
|
|
case 0x02: //FNCLEX FCLEX
|
|
|
|
FPU_FCLEX();
|
|
|
|
break;
|
|
|
|
case 0x03: //FNINIT FINIT
|
|
|
|
FPU_FINIT();
|
2009-05-02 23:12:18 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x04: //FNSETPM
|
|
|
|
case 0x05: //FRSTPM
|
2009-05-03 00:02:15 +02:00
|
|
|
// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FNOP();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:43:00 +02:00
|
|
|
return;
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FPU_ESC4_EA(Bitu rm,PhysPt addr) {
|
2009-05-03 00:18:08 +02:00
|
|
|
/* REGULAR TREE WITH 64 BITS REALS */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FLD_F64_EA(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
EATREE(rm);
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC4_Normal(Bitu rm) {
|
2009-05-03 00:18:08 +02:00
|
|
|
/* LOOKS LIKE number 6 without popping */
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x00: /* FADD STi,ST*/
|
|
|
|
FPU_FADD(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01: /* FMUL STi,ST*/
|
|
|
|
FPU_FMUL(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x02: /* FCOM*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCOM(TOP,STV(sub));
|
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x03: /* FCOMP*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCOM(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x04: /* FSUBR STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FSUBR(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x05: /* FSUB STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FSUB(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x06: /* FDIVR STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FDIVR(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x07: /* FDIV STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FDIV(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC5_EA(Bitu rm,PhysPt addr) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
|
|
|
case 0x00: /* FLD double real*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FLD_F64(addr,TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x01: /* FISTTP longint*/
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x02: /* FST double real*/
|
|
|
|
FPU_FST_F64(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x03: /* FSTP double real*/
|
|
|
|
FPU_FST_F64(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x04: /* FRSTOR */
|
|
|
|
FPU_FRSTOR(addr);
|
2009-05-03 00:02:15 +02:00
|
|
|
break;
|
|
|
|
case 0x06: /* FSAVE */
|
|
|
|
FPU_FSAVE(addr);
|
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x07: /*FNSTSW NG DISAGREES ON THIS*/
|
|
|
|
FPU_SET_TOP(TOP);
|
|
|
|
mem_writew(addr,fpu.sw);
|
|
|
|
//seems to break all dos4gw games :)
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC5_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
|
|
|
case 0x00: /* FFREE STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
fpu.tags[STV(sub)]=TAG_Empty;
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x01: /* FXCH STi*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FXCH(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x02: /* FST STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x03: /* FSTP STi*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
case 0x04: /* FUCOM STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FUCOM(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x05: /*FUCOMP STi */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FUCOM(TOP,STV(sub));
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
void FPU_ESC6_EA(Bitu rm,PhysPt addr) {
|
2009-05-02 23:43:00 +02:00
|
|
|
/* 16 bit (word integer) operants */
|
2009-05-03 00:28:34 +02:00
|
|
|
FPU_FLD_I16_EA(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
EATREE(rm);
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
void FPU_ESC6_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
/* all P variants working only on registers */
|
|
|
|
/* get top before switch and pop afterwards */
|
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
|
|
|
case 0x00: /*FADDP STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FADD(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x01: /* FMULP STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FMUL(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x02: /* FCOMP5*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCOM(TOP,STV(sub));
|
|
|
|
break; /* TODO IS THIS ALLRIGHT ????????? */
|
|
|
|
case 0x03: /*FCOMPP*/
|
|
|
|
if(sub != 1) {
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
return;
|
2009-05-02 23:43:00 +02:00
|
|
|
}
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FCOM(TOP,STV(1));
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP(); /* extra pop at the bottom*/
|
|
|
|
break;
|
|
|
|
case 0x04: /* FSUBRP STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FSUBR(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x05: /* FSUBP STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FSUB(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x06: /* FDIVRP STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FDIVR(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x07: /* FDIVP STi,ST*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FDIV(STV(sub),TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void FPU_ESC7_EA(Bitu rm,PhysPt addr) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch(group){
|
|
|
|
case 0x00: /* FILD Bit16s */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FLD_I16(addr,TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x01:
|
2009-05-02 23:43:00 +02:00
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
case 0x02: /* FIST Bit16s */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST_I16(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x03: /* FISTP Bit16s */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST_I16(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
2009-05-03 00:18:08 +02:00
|
|
|
case 0x04: /* FBLD packed BCD */
|
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FBLD(addr,TOP);
|
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x05: /* FILD Bit64s */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_PREP_PUSH();
|
|
|
|
FPU_FLD_I64(addr,TOP);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
case 0x06: /* FBSTP packed BCD */
|
|
|
|
FPU_FBST(addr);
|
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x07: /* FISTP Bit64s */
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST_I64(addr);
|
2009-05-02 23:43:00 +02:00
|
|
|
FPU_FPOP();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FPU_ESC7_Normal(Bitu rm) {
|
2009-05-02 23:43:00 +02:00
|
|
|
Bitu group=(rm >> 3) & 7;
|
|
|
|
Bitu sub=(rm & 7);
|
|
|
|
switch (group){
|
2009-05-02 23:53:27 +02:00
|
|
|
case 0x01: /* FXCH STi*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FXCH(TOP,STV(sub));
|
2009-05-02 23:53:27 +02:00
|
|
|
break;
|
|
|
|
case 0x02: /* FSTP STi*/
|
|
|
|
case 0x03: /* FSTP STi*/
|
2009-05-03 00:18:08 +02:00
|
|
|
FPU_FST(TOP,STV(sub));
|
|
|
|
FPU_FPOP();
|
2009-05-02 23:53:27 +02:00
|
|
|
break;
|
2009-05-02 23:43:00 +02:00
|
|
|
case 0x04:
|
|
|
|
switch(sub){
|
|
|
|
case 0x00: /* FNSTSW AX*/
|
|
|
|
FPU_SET_TOP(TOP);
|
|
|
|
reg_ax = fpu.sw;
|
|
|
|
break;
|
|
|
|
default:
|
2009-05-03 00:18:08 +02:00
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
|
2009-05-02 23:43:00 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
|
2009-05-02 23:43:00 +02:00
|
|
|
void FPU_Init(Section*) {
|
|
|
|
FPU_FINIT();
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
#endif
|