new version of softfloat-fpu branch
currectly stable
This commit is contained in:
parent
7664560010
commit
967297b8a4
1287
bochs/cpu/fpu_arith.cc
Normal file
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
798
bochs/cpu/fpu_compare.cc
Executable 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
202
bochs/cpu/fpu_const.cc
Executable 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
590
bochs/cpu/fpu_load_store.cc
Executable 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
159
bochs/cpu/fpu_misc.cc
Executable 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
161
bochs/cpu/fpu_trans.cc
Executable 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
104
bochs/cpu/softfloat-fpu.h
Executable 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.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.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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user