示例#1
0
文件: fpu_compare.cpp 项目: iver6/BA
/* DA E9 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FUCOMPP(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          BX_CPU_THIS_PTR the_i387.FPU_pop();
          BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_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(1), status);
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     BX_CPU_THIS_PTR the_i387.FPU_pop();
     BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
示例#2
0
文件: fpu_compare.cpp 项目: iver6/BA
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FUCOMI_ST0_STj(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  int pop_stack = i->b1() & 4;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_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);
  BX_CPU_THIS_PTR write_eflags_fpu_compare(rc);

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
         BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
示例#3
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_STi(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  FPU_update_last_instruction(i);

  clear_C1();

  if (! IS_TAG_EMPTY(-1))
  {
    FPU_stack_overflow();
    BX_NEXT_INSTR(i);
  }

  floatx80 sti_reg = floatx80_default_nan;

  if (IS_TAG_EMPTY(i->rm()))
  {
    FPU_exception(FPU_EX_Stack_Underflow);

    if (! BX_CPU_THIS_PTR the_i387.is_IA_masked()) 
      BX_NEXT_INSTR(i);
  }
  else {
    sti_reg = BX_READ_FPU_REG(i->rm());
  }

  BX_CPU_THIS_PTR the_i387.FPU_push();
  BX_WRITE_FPU_REG(sti_reg, 0);

  BX_NEXT_INSTR(i);
}
示例#4
0
/* DB /7 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FSTP_EXTENDED_REAL(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
  BX_CPU_THIS_PTR prepareFPU(i);

  clear_C1();

  floatx80 save_reg = floatx80_default_nan; /* 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
}
示例#5
0
void BX_CPP_AttrRegparmN(1) 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;
  }

  floatx80 sti_reg = BX_READ_FPU_REG(i->rm());

  BX_CPU_THIS_PTR the_i387.FPU_push();
  BX_WRITE_FPU_REG(sti_reg, 0);
#else
  BX_INFO(("FLD_STi: required FPU, configure --enable-fpu"));
#endif
}
示例#6
0
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_STi(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
  BX_CPU_THIS_PTR prepareFPU(i);

  int pop_stack = i->nnn() & 1;
  // handle special case of FSTP opcode @ 0xDF 0xD0..D7
  if (i->b1() == 0xdf)
    pop_stack = 1;

  clear_C1();

  if (IS_TAG_EMPTY(0)) {
    BX_CPU_THIS_PTR FPU_stack_underflow(i->rm(), pop_stack);
    return;
  }

  floatx80 st0_reg = BX_READ_FPU_REG(0);

  BX_WRITE_FPU_REG(st0_reg, 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
}
示例#7
0
文件: fpu_compare.cpp 项目: iver6/BA
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCMOV_ST0_STj(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
     FPU_stack_underflow(0);
     BX_NEXT_INSTR(i);
  }

  floatx80 sti_reg = BX_READ_FPU_REG(i->rm());

  bx_bool condition = 0;
  switch(i->nnn() & 3)
  {
     case 0: condition = get_CF(); break;
     case 1: condition = get_ZF(); break;
     case 2: condition = get_CF() || get_ZF(); break;
     case 3: condition = get_PF(); break;
     default:
        BX_PANIC(("FCMOV_ST0_STj: default case"));
  }
  if (i->b1() & 1)
     condition = !condition;

  if (condition)
     BX_WRITE_FPU_REG(sti_reg, 0);

  BX_NEXT_INSTR(i);
}
示例#8
0
/* DB /7 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FSTP_EXTENDED_REAL(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));

  FPU_update_last_instruction(i);

  clear_C1();

  floatx80 save_reg = floatx80_default_nan; /* The masked response */

  if (IS_TAG_EMPTY(0))
  {
     FPU_exception(FPU_EX_Stack_Underflow);

     if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
        BX_NEXT_INSTR(i);
  }
  else
  {
     save_reg = BX_READ_FPU_REG(0);
  }

  write_virtual_qword(i->seg(), RMAddr(i), save_reg.fraction);
  write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg.exp);

  BX_CPU_THIS_PTR the_i387.FPU_pop();

  BX_NEXT_INSTR(i);
}
示例#9
0
/* DD /1 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP64(bxInstruction_c *i)
{
#if BX_SUPPORT_SSE >= 3
  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
  {
     float_status_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 SSE3, use --enable-sse option"));
  UndefinedOpcode(i);
#endif
}
示例#10
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FST_STi(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  FPU_update_last_instruction(i);

  int pop_stack = i->nnn() & 1;
  // handle special case of FSTP opcode @ 0xDF 0xD0..D7
  if (i->b1() == 0xdf)
    pop_stack = 1;

  clear_C1();

  if (IS_TAG_EMPTY(0)) {
    FPU_stack_underflow(i->rm(), pop_stack);
  }
  else {
    floatx80 st0_reg = BX_READ_FPU_REG(0);

    BX_WRITE_FPU_REG(st0_reg, i->rm());
    if (pop_stack)
      BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
示例#11
0
文件: fpu_compare.cpp 项目: iver6/BA
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_STi(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  int pop_stack = i->nnn() & 1;
  // handle special case of FSTP opcode @ 0xDE 0xD0..D7
  if (i->b1() == 0xde)
    pop_stack = 1;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_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);
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
        BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
示例#12
0
文件: fpu_compare.cpp 项目: iver6/BA
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_DOUBLE_REAL(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  int pop_stack = i->nnn() & 1, rc;

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
  float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));

  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_t status =
      FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

  floatx80 a = BX_READ_FPU_REG(0);

  if (floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(load_reg)) {
    rc = float_relation_unordered;
    float_raise(status, float_flag_invalid);
  }
  else {
    rc = floatx80_compare(a, float64_to_floatx80(load_reg, status), status);
  }
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
         BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
示例#13
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_DWORD_INTEGER(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));

  FPU_update_last_instruction(i);

  Bit16u x87_sw = FPU_PARTIAL_STATUS;

  Bit32s save_reg = int32_indefinite; /* The masked response */

  int pop_stack = i->nnn() & 1;

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
     FPU_exception(FPU_EX_Stack_Underflow);

     if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
        BX_NEXT_INSTR(i);
  }
  else
  {
     float_status_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 (FPU_exception(status.float_exception_flags, 1))
         BX_NEXT_INSTR(i);
  }

  // store to the memory might generate an exception, in this case origial FPU_SW must be kept
  swap_values16u(x87_sw, FPU_PARTIAL_STATUS);

  write_virtual_dword(i->seg(), RMAddr(i), (Bit32u)(save_reg));

  FPU_PARTIAL_STATUS = x87_sw;
  if (pop_stack)
     BX_CPU_THIS_PTR the_i387.FPU_pop();

  BX_NEXT_INSTR(i);
}
示例#14
0
文件: fpu_compare.cpp 项目: iver6/BA
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FICOM_WORD_INTEGER(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  int pop_stack = i->nnn() & 1;

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
  Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));

  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_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);
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
         BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
示例#15
0
void BX_CPP_AttrRegparmN(1) 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->nnn() & 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
  {
     float_status_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
}
示例#16
0
文件: fpu_compare.cpp 项目: iver6/BA
/* D9 E4 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FTST(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  clear_C1();

  if (IS_TAG_EMPTY(0)) {
     FPU_exception(FPU_EX_Stack_Underflow);
     setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
  }
  else {
     extern const floatx80 Const_Z;

     float_status_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);
     setcc(status_word_flags_fpu_compare(rc));
     FPU_exception(status.float_exception_flags);
  }

  BX_NEXT_INSTR(i);
}
示例#17
0
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
  BX_CPU_THIS_PTR prepareFPU(i);

  /*
   * The packed BCD integer indefinite encoding (FFFFC000000000000000H)
   * is stored in response to a masked floating-point invalid-operation
   * exception.
   */
  Bit16u save_reg_hi = 0xFFFF;
  Bit64u save_reg_lo = BX_CONST64(0xC000000000000000);

  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
  {
     float_status_t status =
        FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

     floatx80 reg = BX_READ_FPU_REG(0);

     Bit64s save_val = floatx80_to_int64(reg, status);

     int sign = (reg.exp & 0x8000) != 0;
     if (sign)
        save_val = -save_val;

     if (save_val > BX_CONST64(999999999999999999))
     {
        float_raise(status, float_flag_invalid);
     }

     if (! (status.float_exception_flags & float_flag_invalid))
     {
        save_reg_hi = (sign) ? 0x8000 : 0;
        save_reg_lo = 0;

        for (int i=0; i<16; i++)
        {
           save_reg_lo += ((Bit64u)(save_val % 10)) << (4*i);
           save_val /= 10;
        }

        save_reg_hi += (Bit16u)(save_val % 10);
        save_val /= 10;
        save_reg_hi += (Bit16u)(save_val % 10) << 4;
    }

    /* check for fpu arithmetic exceptions */
    if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags))
        return;
  }

  // write packed bcd to memory
  write_virtual_qword(i->seg(), RMAddr(i),     save_reg_lo);
  write_virtual_word (i->seg(), RMAddr(i) + 8, save_reg_hi);

  BX_CPU_THIS_PTR the_i387.FPU_pop();
#else
  BX_INFO(("FBSTP_PACKED_BCD: required FPU, configure --enable-fpu"));
#endif
}
示例#18
0
文件: fpu_compare.cpp 项目: iver6/BA
/* D9 E5 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FXAM(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(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_zero:
           setcc(FPU_SW_C3|FPU_SW_C1);
           break;

        case float_NaN:
           // unsupported handled as NaNs
           if (floatx80_is_unsupported(reg)) {
               setcc(FPU_SW_C1);
           } 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();

  BX_NEXT_INSTR(i);
}
示例#19
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));

  FPU_update_last_instruction(i);

  Bit16u x87_sw = FPU_PARTIAL_STATUS;

  /*
   * The packed BCD integer indefinite encoding (FFFFC000000000000000H)
   * is stored in response to a masked floating-point invalid-operation
   * exception.
   */
  Bit16u save_reg_hi = 0xFFFF;
  Bit64u save_reg_lo = BX_CONST64(0xC000000000000000);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
     FPU_exception(FPU_EX_Stack_Underflow);

     if (! BX_CPU_THIS_PTR the_i387.is_IA_masked())
        BX_NEXT_INSTR(i);
  }
  else
  {
     float_status_t status =
        FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

     floatx80 reg = BX_READ_FPU_REG(0);

     Bit64s save_val = floatx80_to_int64(reg, status);

     int sign = (reg.exp & 0x8000) != 0;
     if (sign)
        save_val = -save_val;

     if (save_val > BX_CONST64(999999999999999999)) {
        status.float_exception_flags = float_flag_invalid; // throw away other flags
     }

     if (! (status.float_exception_flags & float_flag_invalid))
     {
        save_reg_hi = (sign) ? 0x8000 : 0;
        save_reg_lo = 0;

        for (int i=0; i<16; i++) {
           save_reg_lo += ((Bit64u)(save_val % 10)) << (4*i);
           save_val /= 10;
        }

        save_reg_hi += (Bit16u)(save_val % 10);
        save_val /= 10;
        save_reg_hi += (Bit16u)(save_val % 10) << 4;
    }

    /* check for fpu arithmetic exceptions */
    if (FPU_exception(status.float_exception_flags, 1))
        BX_NEXT_INSTR(i);
  }

  // store to the memory might generate an exception, in this case origial FPU_SW must be kept
  swap_values16u(x87_sw, FPU_PARTIAL_STATUS);

  // write packed bcd to memory
  write_virtual_qword(i->seg(), RMAddr(i), save_reg_lo);
  write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg_hi);

  FPU_PARTIAL_STATUS = x87_sw;

  BX_CPU_THIS_PTR the_i387.FPU_pop();

  BX_NEXT_INSTR(i);
}