static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag) { int expon; clear_C1(); if (st0_tag == TAG_Valid) { u_char tag; if (signnegative(st0_ptr)) { arith_invalid(0); /* sqrt(negative) is invalid */ return; } /* make st(0) in [1.0 .. 4.0) */ expon = exponent(st0_ptr); denormal_arg: setexponent16(st0_ptr, (expon & 1)); /* Do the computation, the sign of the result will be positive. */ tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS); addexponent(st0_ptr, expon >> 1); FPU_settag0(tag); return; }
static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag) { int expon; clear_C1(); if (st0_tag == TAG_Valid) { u_char tag; if (signnegative(st0_ptr)) { arith_invalid(0); return; } expon = exponent(st0_ptr); denormal_arg: setexponent16(st0_ptr, (expon & 1)); tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS); addexponent(st0_ptr, expon >> 1); FPU_settag0(tag); return; }
/* 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); }
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); }
void fdivp_(void) { /* fdivp st(i),st */ clear_C1(); if (FPU_div(REV | DEST_RM, FPU_rm, control_word) >= 0) FPU_pop(); }
/* 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 }
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 }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i)); clear_C1(); if (! IS_TAG_EMPTY(-1)) { BX_CPU_THIS_PTR FPU_stack_overflow(); return; } float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); // convert to floatx80 format 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_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 }
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); }
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); }
void fadd_i(void) { /* fadd st(i),st */ int i = FPU_rm; clear_C1(); FPU_add(&st(i), FPU_gettagi(i), i, control_word); }
/* DE D9 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOMPP(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) || 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(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); }
/* 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 }
void fmul__(void) { /* fmul st,st(i) */ int i = FPU_rm; clear_C1(); FPU_mul(&st(i), FPU_gettagi(i), 0, control_word); }
void fsubp_(void) { /* fsubp st(i),st */ clear_C1(); if (FPU_sub(REV | DEST_RM, FPU_rm, control_word) >= 0) FPU_pop(); }
void fmulp_(void) { /* fmulp st(i),st */ clear_C1(); if (FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0) FPU_pop(); }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i)); FPU_update_last_instruction(i); clear_C1(); if (! IS_TAG_EMPTY(-1)) { FPU_stack_overflow(); BX_NEXT_INSTR(i); } float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); // convert to floatx80 format floatx80 result = float64_to_floatx80(load_reg, status); unsigned unmasked = FPU_exception(status.float_exception_flags); if (! (unmasked & FPU_CW_Invalid)) { BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } BX_NEXT_INSTR(i); }
static void fabs(FPU_REG *st0_ptr, u_char st0tag) { if (st0tag ^ TAG_Empty) { setpositive(st0_ptr); clear_C1(); } else FPU_stack_underflow(); }
void faddp_(void) { /* faddp st(i),st */ int i = FPU_rm; clear_C1(); if (FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0) FPU_pop(); }
static void fchs(FPU_REG *st0_ptr, u_char st0tag) { if (st0tag ^ TAG_Empty) { signbyte(st0_ptr) ^= SIGN_NEG; clear_C1(); } else FPU_stack_underflow(); }
static void fld_const(FPU_REG const * c, int adj, u_char tag) { FPU_REG *st_new_ptr; if (STACK_OVERFLOW) { FPU_stack_overflow(); return; } push(); reg_copy(c, st_new_ptr); st_new_ptr->sigl += adj; /* For all our fldxxx constants, we don't need to borrow or carry. */ FPU_settag0(tag); clear_C1(); }
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); }
static void f2xm1(FPU_REG *st0_ptr, u_char tag) { FPU_REG a; clear_C1(); if ( tag == TAG_Valid ) { /* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */ if ( exponent(st0_ptr) < 0 ) { denormal_arg: FPU_to_exp16(st0_ptr, &a); /* poly_2xm1(x) requires 0 < st(0) < 1. */ poly_2xm1(getsign(st0_ptr), &a, st0_ptr); } set_precision_flag_up(); /* 80486 appears to always do this */ return; } if ( tag == TAG_Zero ) return; if ( tag == TAG_Special ) tag = FPU_Special(st0_ptr); switch ( tag ) { case TW_Denormal: if ( denormal_operand() < 0 ) return; goto denormal_arg; case TW_Infinity: if ( signnegative(st0_ptr) ) { /* -infinity gives -1 (p16-10) */ FPU_copy_to_reg0(&CONST_1, TAG_Valid); setnegative(st0_ptr); } return; default: single_arg_error(st0_ptr, tag); } }
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); }
void BX_CPP_AttrRegparmN(1) 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_REG(FPU_round_const(Const_PI, DOWN_OR_CHOP() ? -1 : 0), 0); #else BX_INFO(("FLDPI: required FPU, configure --enable-fpu")); #endif }
static void f2xm1(FPU_REG *st0_ptr, u_char tag) { FPU_REG a; clear_C1(); if (tag == TAG_Valid) { if (exponent(st0_ptr) < 0) { denormal_arg: FPU_to_exp16(st0_ptr, &a); poly_2xm1(getsign(st0_ptr), &a, st0_ptr); } set_precision_flag_up(); return; } if (tag == TAG_Zero) return; if (tag == TAG_Special) tag = FPU_Special(st0_ptr); switch (tag) { case TW_Denormal: if (denormal_operand() < 0) return; goto denormal_arg; case TW_Infinity: if (signnegative(st0_ptr)) { FPU_copy_to_reg0(&CONST_1, TAG_Valid); setnegative(st0_ptr); } return; default: single_arg_error(st0_ptr, tag); } }
/* DF /4 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); // read packed bcd from memory Bit16u hi2 = read_virtual_word (i->seg(), RMAddr(i) + 8); Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i)); clear_C1(); if (! IS_TAG_EMPTY(-1)) { BX_CPU_THIS_PTR FPU_stack_overflow(); return; } // convert packed BCD to 64-bit integer Bit64s scale = 1; Bit64s val64 = 0; for (int n = 0; n < 16; n++) { val64 += (lo8 & 0x0f) * scale; lo8 >>= 4; scale *= 10; } val64 += (hi2 & 0x0f) * scale; val64 += ((hi2>>4) & 0x0f) * scale * 10; floatx80 result = int64_to_floatx80(val64); if (hi2 & 0x8000) // set negative floatx80_chs(result); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); #else BX_INFO(("FBLD_PACKED_BCD: required FPU, configure --enable-fpu")); #endif }
/* DF /4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u hi2 = read_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask()); Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i)); FPU_update_last_instruction(i); clear_C1(); if (! IS_TAG_EMPTY(-1)) { FPU_stack_overflow(); BX_NEXT_INSTR(i); } // convert packed BCD to 64-bit integer Bit64s scale = 1; Bit64s val64 = 0; for (int n = 0; n < 16; n++) { val64 += (lo8 & 0x0f) * scale; lo8 >>= 4; scale *= 10; } val64 += (hi2 & 0x0f) * scale; val64 += ((hi2>>4) & 0x0f) * scale * 10; floatx80 result = int64_to_floatx80(val64); if (hi2 & 0x8000) // set negative floatx80_chs(result); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); }
/* DF /5 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_QWORD_INTEGER(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); Bit64s load_reg = (Bit64s) read_virtual_qword(i->seg(), RMAddr(i)); clear_C1(); if (! IS_TAG_EMPTY(-1)) { BX_CPU_THIS_PTR FPU_stack_overflow(); return; } 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 }