new version of softfloat-fpu branch

currectly stable
This commit is contained in:
Stanislav Shwartsman 2004-03-12 20:08:50 +00:00
parent 7664560010
commit 967297b8a4
7 changed files with 3301 additions and 0 deletions

1287
bochs/cpu/fpu_arith.cc Normal file

File diff suppressed because it is too large Load Diff

798
bochs/cpu/fpu_compare.cc Executable file
View File

@ -0,0 +1,798 @@
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 MandrakeSoft S.A.
//
// MandrakeSoft S.A.
// 43, rue d'Aboukir
// 75002 Paris - France
// http://www.linux-mandrake.com/
// http://www.mandrakesoft.com/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_SUPPORT_FPU
#include "softfloat-specialize.h"
#endif
#if BX_SUPPORT_FPU
static int status_word_flags_fpu_compare(int float_relation)
{
switch(float_relation) {
case float_relation_unordered:
return (FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
case float_relation_greater:
return (0);
case float_relation_less:
return (FPU_SW_C0);
case float_relation_equal:
return (FPU_SW_C3);
}
return (-1); // should never get here
}
#endif
#if BX_SUPPORT_FPU || BX_SUPPORT_SSE >= 1
void BX_CPU_C::write_eflags_fpu_compare(int float_relation)
{
switch(float_relation) {
case float_relation_unordered:
setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask);
break;
case float_relation_greater:
setEFlagsOSZAPC(0);
break;
case float_relation_less:
setEFlagsOSZAPC(EFlagsCFMask);
break;
case float_relation_equal:
setEFlagsOSZAPC(EFlagsZFMask);
break;
default:
BX_PANIC(("write_eflags: unknown floating point compare relation"));
}
}
#endif
void BX_CPU_C::FCOM_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FCOM(P)_STi: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FCOMI_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FCOMI(P)_ST0_STj: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FUCOMI_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FUCOMI(P)_ST0_STj: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FUCOM_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FUCOM(P)_STi: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FCOM_SINGLE_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
float32 load_reg;
read_virtual_dword(i->seg(), RMAddr(i), &load_reg);
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0),
float32_to_floatx80(load_reg, status), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FCOM(P)_SINGLE_REAL: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FCOM_DOUBLE_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
float64 load_reg;
read_virtual_qword(i->seg(), RMAddr(i), &load_reg);
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0),
float64_to_floatx80(load_reg, status), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FCOM(P)_DOUBLE_REAL: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FICOM_WORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
Bit16s load_reg;
read_virtual_word(i->seg(), RMAddr(i), (Bit16u*)(&load_reg));
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0),
int32_to_floatx80((Bit32s)(load_reg)), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FICOM(P)_WORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FICOM_DWORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
Bit32s load_reg;
read_virtual_dword(i->seg(), RMAddr(i), (Bit32u*)(&load_reg));
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0),
int32_to_floatx80(load_reg), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FICOM(P)_DWORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
/* DE D9 */
void BX_CPU_C::FCOMPP(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
BX_CPU_THIS_PTR the_i387.FPU_pop();
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
BX_CPU_THIS_PTR the_i387.FPU_pop();
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FCOMPP: required FPU, configure --enable-fpu"));
#endif
}
/* DA E9 */
void BX_CPU_C::FUCOMPP(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
BX_CPU_THIS_PTR the_i387.FPU_pop();
BX_CPU_THIS_PTR the_i387.FPU_pop();
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
BX_CPU_THIS_PTR the_i387.FPU_pop();
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FUCOMPP: required FPU, configure --enable-fpu"));
#endif
}
/* DA C0 */
void BX_CPU_C::FCMOVB_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (get_CF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVB_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DA C8 */
void BX_CPU_C::FCMOVE_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (get_ZF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVE_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DA D0 */
void BX_CPU_C::FCMOVBE_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (get_CF() || get_ZF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVBE_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DA D8 */
void BX_CPU_C::FCMOVU_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (get_PF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVU_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DB C0 */
void BX_CPU_C::FCMOVNB_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (! get_CF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVNB_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DB C8 */
void BX_CPU_C::FCMOVNE_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (! get_ZF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVNE_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DB D0 */
void BX_CPU_C::FCMOVNBE_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if ((!get_CF()) && (!get_ZF()))
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVNBE_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* DB D8 */
void BX_CPU_C::FCMOVNU_ST0_STj(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU && (BX_CPU_LEVEL == 6)
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
if (! get_PF())
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FCMOVNU_ST0_STj: required P6 FPU, configure --enable-fpu, cpu-level=6"));
UndefinedOpcode(i);
#endif
}
/* D9 E4 */
void BX_CPU_C::FTST(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* the masked response */
SETCC(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
}
return;
}
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
int rc = floatx80_compare(BX_READ_FPU_REG(0), Const_Z, status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
SETCC(status_word_flags_fpu_compare(rc));
#else
BX_INFO(("FTST: required FPU, configure --enable-fpu"));
#endif
}
/* D9 E5 */
void BX_CPU_C::FXAM(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
floatx80 reg = BX_READ_FPU_REG(0);
int sign = floatx80_sign(reg);
/*
* Examine the contents of the ST(0) register and sets the condition
* code flags C0, C2 and C3 in the FPU status word to indicate the
* class of value or number in the register.
*/
if (IS_TAG_EMPTY(0))
{
SETCC(FPU_SW_C3|FPU_SW_C1|FPU_SW_C0);
}
else
{
float_class_t aClass = floatx80_class(reg);
switch(aClass)
{
case float_negative_zero:
case float_positive_zero:
SETCC(FPU_SW_C3|FPU_SW_C1);
break;
case float_NaN:
if (! (reg.fraction & BX_CONST64(0x8000000000000000))) {
SETCC(FPU_SW_C1); // unsupported handled as NaNs
} else {
SETCC(FPU_SW_C1|FPU_SW_C0);
}
break;
case float_negative_inf:
case float_positive_inf:
SETCC(FPU_SW_C2|FPU_SW_C1|FPU_SW_C0);
break;
case float_denormal:
SETCC(FPU_SW_C3|FPU_SW_C2|FPU_SW_C1);
break;
case float_normalized:
SETCC(FPU_SW_C2|FPU_SW_C1);
break;
}
}
/*
* The C1 flag is set to the sign of the value in ST(0), regardless
* of whether the register is empty or full.
*/
if (! sign)
clear_C1();
#else
BX_INFO(("FXAM: required FPU, configure --enable-fpu"));
#endif
}

202
bochs/cpu/fpu_const.cc Executable file
View File

@ -0,0 +1,202 @@
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 MandrakeSoft S.A.
//
// MandrakeSoft S.A.
// 43, rue d'Aboukir
// 75002 Paris - France
// http://www.linux-mandrake.com/
// http://www.mandrakesoft.com/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_SUPPORT_FPU
#include "softfloat-specialize.h"
#endif
#if BX_SUPPORT_FPU
const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
const floatx80 Const_Z = packFloatx80(0, 0x0000, 0);
const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe));
const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc));
const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
const floatx80 Const_PI2 = packFloatx80(0, 0x3fff, BX_CONST64(0xc90fdaa22168c235));
const floatx80 Const_PI4 = packFloatx80(0, 0x3ffe, BX_CONST64(0xc90fdaa22168c235));
const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799));
const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac));
/* A fast way to find out whether x is one of RC_DOWN or RC_CHOP
(and not one of RC_RND or RC_UP).
*/
#define DOWN_OR_CHOP() (FPU_CONTROL_WORD & FPU_CW_RC & FPU_RC_DOWN)
BX_CPP_INLINE floatx80 FPU_round_const(const floatx80 &a, int adj)
{
floatx80 result = a;
result.fraction += adj;
return result;
}
#endif
void BX_CPU_C::FLDL2T(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(FPU_round_const(Const_L2T,
(FPU_CONTROL_WORD == FPU_RC_UP) ? 1 : 0), FPU_Tag_Valid, 0);
#else
BX_INFO(("FLDL2T: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLDL2E(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(FPU_round_const(Const_L2E,
DOWN_OR_CHOP() ? -1 : 0), FPU_Tag_Valid, 0);
#else
BX_INFO(("FLDL2E: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLDPI(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(FPU_round_const(Const_PI,
DOWN_OR_CHOP() ? -1 : 0), FPU_Tag_Valid, 0);
#else
BX_INFO(("FLDPI: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLDLG2(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(FPU_round_const(Const_LG2,
DOWN_OR_CHOP() ? -1 : 0), FPU_Tag_Valid, 0);
#else
BX_INFO(("FLDLG2: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLDLN2(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(FPU_round_const(Const_LN2,
DOWN_OR_CHOP() ? -1 : 0), FPU_Tag_Valid, 0);
#else
BX_INFO(("FLDLN2: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLD1(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(Const_1, FPU_Tag_Valid, 0);
#else
BX_INFO(("FLD1: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLDZ(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(Const_Z, FPU_Tag_Zero, 0);
#else
BX_INFO(("FLDZ: required FPU, configure --enable-fpu"));
#endif
}

590
bochs/cpu/fpu_load_store.cc Executable file
View File

@ -0,0 +1,590 @@
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 MandrakeSoft S.A.
//
// MandrakeSoft S.A.
// 43, rue d'Aboukir
// 75002 Paris - France
// http://www.linux-mandrake.com/
// http://www.mandrakesoft.com/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_SUPPORT_FPU
#include "softfloat-fpu.h"
#endif
void BX_CPU_C::FLD_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
if (IS_TAG_EMPTY(i->rm()))
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FLD_STi: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLD_SINGLE_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
float32 load_reg;
read_virtual_dword(i->seg(), RMAddr(i), &load_reg);
// convert to floatx80 format
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
floatx80 result = float32_to_floatx80(load_reg, status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REG(result, 0);
#else
BX_INFO(("FLD_SINGLE_REAL: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
float64 load_reg;
read_virtual_qword(i->seg(), RMAddr(i), &load_reg);
// convert to floatx80 format
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
floatx80 result = float64_to_floatx80(load_reg, status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REG(result, 0);
#else
BX_INFO(("FLD_DOUBLE_REAL: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FLD_EXTENDED_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
floatx80 result;
read_virtual_tword(i->seg(), RMAddr(i), &result);
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REG(result, 0);
#else
BX_INFO(("FLD_EXTENDED_REAL: required FPU, configure --enable-fpu"));
#endif
}
/* DF /0 */
void BX_CPU_C::FILD_WORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
Bit16s load_reg;
read_virtual_word(i->seg(), RMAddr(i), (Bit16u*)(&load_reg));
floatx80 result = int32_to_floatx80((Bit32s) load_reg);
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REG(result, 0);
#else
BX_INFO(("FILD_WORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
/* DB /0 */
void BX_CPU_C::FILD_DWORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
Bit32s load_reg;
read_virtual_dword(i->seg(), RMAddr(i), (Bit32u*)(&load_reg));
floatx80 result = int32_to_floatx80(load_reg);
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REG(result, 0);
#else
BX_INFO(("FILD_DWORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
/* DF /5 */
void BX_CPU_C::FILD_QWORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
if (! IS_TAG_EMPTY(-1))
{
BX_CPU_THIS_PTR FPU_stack_overflow();
return;
}
Bit64s load_reg;
read_virtual_qword(i->seg(), RMAddr(i), (Bit64u*)(&load_reg));
floatx80 result = int64_to_floatx80(load_reg);
BX_CPU_THIS_PTR the_i387.FPU_push();
BX_WRITE_FPU_REG(result, 0);
#else
BX_INFO(("FILD_QWORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
/* DF /4 */
void BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FBLD_PACKED_BCD: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FST_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int pop_stack = (i->b1() & 0x10) >> 1;
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
if (st0_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(i->rm(), pop_stack);
return;
}
floatx80 st0_reg = BX_READ_FPU_REG(0);
BX_WRITE_FPU_REGISTER_AND_TAG(st0_reg, st0_tag, i->rm());
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FST(P)_STi: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FST_SINGLE_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
float32 save_reg = float32_default_nan; /* The masked response */
int pop_stack = (i->b1() & 0x10) >> 1;
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_float32(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_dword(i->seg(), RMAddr(i), &save_reg);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FST(P)_SINGLE_REAL: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FST_DOUBLE_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
float64 save_reg = float64_default_nan; /* The masked response */
int pop_stack = (i->b1() & 0x10) >> 1;
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_float64(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_qword(i->seg(), RMAddr(i), &save_reg);
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FST(P)_DOUBLE_REAL: required FPU, configure --enable-fpu"));
#endif
}
/* DB /7 */
void BX_CPU_C::FSTP_EXTENDED_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
floatx80 save_reg = Const_QNaN; /* The masked response */
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
save_reg = BX_READ_FPU_REG(0);
}
write_virtual_tword(i->seg(), RMAddr(i), &save_reg);
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FSTP_EXTENDED_REAL: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FIST_WORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
Bit16s save_reg = int16_indefinite;
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_int16(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_word(i->seg(), RMAddr(i), (Bit16u*)(&save_reg));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FIST(P)_WORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FIST_DWORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
Bit32s save_reg = int32_indefinite; /* The masked response */
int pop_stack = (i->b1() & 0x10) >> 1;
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_int32(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_dword(i->seg(), RMAddr(i), (Bit32u*)(&save_reg));
if (pop_stack)
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FIST(P)_DWORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FISTP_QWORD_INTEGER(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
Bit64s save_reg = int64_indefinite; /* The masked response */
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_int64(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_qword(i->seg(), RMAddr(i), (Bit64u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTP_QWORD_INTEGER: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FBSTP_PACKED_BCD: required FPU, configure --enable-fpu"));
#endif
}
/* DF /1 */
void BX_CPU_C::FISTTP16(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareFPU(i);
Bit16s save_reg = int16_indefinite; /* The masked response */
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_int16_round_to_zero(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_word(i->seg(), RMAddr(i), (Bit16u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTTP16: required PNI, configure --enable-pni"));
UndefinedOpcode(i);
#endif
}
/* DB /1 */
void BX_CPU_C::FISTTP32(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareFPU(i);
Bit32s save_reg = int32_indefinite; /* The masked response */
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_int32_round_to_zero(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_dword(i->seg(), RMAddr(i), (Bit32u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTTP32: required PNI, configure --enable-pni"));
UndefinedOpcode(i);
#endif
}
/* DD /1 */
void BX_CPU_C::FISTTP64(bxInstruction_c *i)
{
#if BX_SUPPORT_PNI
BX_CPU_THIS_PTR prepareFPU(i);
Bit64s save_reg = int64_indefinite; /* The masked response */
clear_C1();
if (IS_TAG_EMPTY(0))
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked()))
return;
}
else
{
softfloat_status_word_t status =
FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());
save_reg = floatx80_to_int64_round_to_zero(BX_READ_FPU_REG(0), status);
if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
return;
}
write_virtual_qword(i->seg(), RMAddr(i), (Bit64u*)(&save_reg));
BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
BX_INFO(("FISTTP64: required PNI, configure --enable-pni"));
UndefinedOpcode(i);
#endif
}

159
bochs/cpu/fpu_misc.cc Executable file
View File

@ -0,0 +1,159 @@
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 MandrakeSoft S.A.
//
// MandrakeSoft S.A.
// 43, rue d'Aboukir
// 75002 Paris - France
// http://www.linux-mandrake.com/
// http://www.mandrakesoft.com/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
#if BX_SUPPORT_FPU
#include "softfloat-fpu.h"
#endif
/* D9 C8 */
void BX_CPU_C::FXCH_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
int sti_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(i->rm());
floatx80 st0_reg = BX_READ_FPU_REG(0);
floatx80 sti_reg = BX_READ_FPU_REG(i->rm());
clear_C1();
if (st0_tag == FPU_Tag_Empty || sti_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow);
if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
{
/* Masked response */
if (st0_tag == FPU_Tag_Empty)
{
st0_reg = Const_QNaN;
st0_tag = FPU_Tag_Special;
}
if (sti_tag == FPU_Tag_Empty)
{
sti_reg = Const_QNaN;
sti_tag = FPU_Tag_Special;
}
}
else return;
}
BX_WRITE_FPU_REGISTER_AND_TAG(st0_reg, st0_tag, i->rm());
BX_WRITE_FPU_REGISTER_AND_TAG(sti_reg, sti_tag, 0);
#else
BX_INFO(("FXCH_STi: required FPU, configure --enable-fpu"));
#endif
}
/* D9 E0 */
void BX_CPU_C::FCHS(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
if (st0_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
clear_C1();
floatx80 st0_reg = BX_READ_FPU_REG(0);
BX_WRITE_FPU_REGISTER_AND_TAG(floatx80_chs(st0_reg), st0_tag, 0);
#else
BX_INFO(("FCHS: required FPU, configure --enable-fpu"));
#endif
}
/* D9 E1 */
void BX_CPU_C::FABS(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
int st0_tag = BX_CPU_THIS_PTR the_i387.FPU_gettagi(0);
if (st0_tag == FPU_Tag_Empty)
{
BX_CPU_THIS_PTR FPU_stack_underflow(0);
return;
}
clear_C1();
floatx80 st0_reg = BX_READ_FPU_REG(0);
BX_WRITE_FPU_REGISTER_AND_TAG(floatx80_abs(st0_reg), st0_tag, 0);
#else
BX_INFO(("FABS: required FPU, configure --enable-fpu"));
#endif
}
/* D9 F6 */
void BX_CPU_C::FDECSTP(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
BX_CPU_THIS_PTR the_i387.tos = (BX_CPU_THIS_PTR the_i387.tos-1) & 7;
#else
BX_INFO(("FDECSTP: required FPU, configure --enable-fpu"));
#endif
}
/* D9 F7 */
void BX_CPU_C::FINCSTP(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
clear_C1();
BX_CPU_THIS_PTR the_i387.tos = (BX_CPU_THIS_PTR the_i387.tos+1) & 7;
#else
BX_INFO(("FINCSTP: required FPU, configure --enable-fpu"));
#endif
}
/* DD C0 */
void BX_CPU_C::FFREE_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
BX_CPU_THIS_PTR the_i387.FPU_settagi(FPU_Tag_Empty, i->rm());
#else
BX_INFO(("FFREE_STi: required FPU, configure --enable-fpu"));
#endif
}

161
bochs/cpu/fpu_trans.cc Executable file
View File

@ -0,0 +1,161 @@
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 MandrakeSoft S.A.
//
// MandrakeSoft S.A.
// 43, rue d'Aboukir
// 75002 Paris - France
// http://www.linux-mandrake.com/
// http://www.mandrakesoft.com/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
void BX_CPU_C::FSIN(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FSIN: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FCOS(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FCOS: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FSINCOS(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FSINCOS: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FPTAN(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FPTAN: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FPATAN(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FPATAN: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FYL2XP1(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FYL2XP1: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::F2XM1(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("F2XM1: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FYL2X(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FYL2X: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FSCALE(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FSCALE: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FXTRACT(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FXTRACT: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FPREM1(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FPREM1: required FPU, configure --enable-fpu"));
#endif
}
void BX_CPU_C::FPREM(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
BX_CPU_THIS_PTR prepareFPU(i);
fpu_execute(i);
//#else
BX_INFO(("FPREM: required FPU, configure --enable-fpu"));
#endif
}

104
bochs/cpu/softfloat-fpu.h Executable file
View File

@ -0,0 +1,104 @@
/*============================================================================
This source file is an addon to the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
floating point emulation.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman (gate@fidonet.org.il)
* ==========================================================================*/
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Functions and definitions to determine: (1) whether tininess for underflow
| is detected before or after rounding by default, (2) what (if anything)
| happens when exceptions are raised, (3) how signaling NaNs are distinguished
| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
| are propagated from function inputs to output. These details are target-
| specific.
*----------------------------------------------------------------------------*/
#include "softfloat-specialize.h"
/*-----------------------------------------------------------------------------
| Calculates the absolute value of the extended double-precision floating-point
| value `a'. The operation is performed according to the IEC/IEEE Standard
| for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE floatx80& floatx80_abs(floatx80 &reg)
{
reg.exp &= 0x7FFF;
return reg;
}
/*-----------------------------------------------------------------------------
| Changes the sign of the extended double-precision floating-point value 'a'.
| The operation is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE floatx80& floatx80_chs(floatx80 &reg)
{
reg.exp ^= 0x8000;
return reg;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the 16-bit two's complement integer format. The
| conversion is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic - which means in particular that the conversion
| is rounded according to the current rounding mode. If `a' is a NaN or the
| conversion overflows, the integer indefinite value is returned.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16s floatx80_to_int16(floatx80 a, float_status_t &status)
{
Bit32s v32 = floatx80_to_int32(a, status);
if ((v32 > (Bit32s) BX_MAX_BIT16S) || (v32 < (Bit32s) BX_MIN_BIT16S))
{
float_raise(status, float_flag_invalid);
return int16_indefinite;
}
return (Bit16s) v32;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the 16-bit two's complement integer format. The
| conversion is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic, except that the conversion is always rounded
| toward zero. If `a' is a NaN or the conversion overflows, the integer
| indefinite value is returned.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16s floatx80_to_int16_round_to_zero(floatx80 a, float_status_t &status)
{
Bit32s v32 = floatx80_to_int32_round_to_zero(a, status);
if ((v32 > (Bit32s) BX_MAX_BIT16S) || (v32 < (Bit32s) BX_MIN_BIT16S))
{
float_raise(status, float_flag_invalid);
return int16_indefinite;
}
return (Bit16s) v32;
}