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); }
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::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::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); }
static void fabs(FPU_REG *st0_ptr, u_char st0tag) { if (st0tag ^ TAG_Empty) { setpositive(st0_ptr); clear_C1(); } else FPU_stack_underflow(); }
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 single_arg_error(FPU_REG *st0_ptr, u_char st0_tag) { if (st0_tag == TAG_Empty) FPU_stack_underflow(); else if (st0_tag == TW_NaN) real_1op_NaN(st0_ptr); #ifdef PARANOID else EXCEPTION(EX_INTERNAL | 0x0112); #endif }
static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag) { if (st0_tag == TAG_Empty) FPU_stack_underflow(); /* Puts a QNaN in st(0) */ else if (st0_tag == TW_NaN) real_1op_NaN(st0_ptr); /* return with a NaN in st(0) */ #ifdef PARANOID else EXCEPTION(EX_INTERNAL | 0x0112); #endif /* PARANOID */ }
static void fxtract(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st_new_ptr; u_char sign; register FPU_REG *st1_ptr = st0_ptr; if (STACK_OVERFLOW) { FPU_stack_overflow(); return; } clear_C1(); if (st0_tag == TAG_Valid) { long e; push(); sign = getsign(st1_ptr); reg_copy(st1_ptr, st_new_ptr); setexponent16(st_new_ptr, exponent(st_new_ptr)); denormal_arg: e = exponent16(st_new_ptr); convert_l2reg(&e, 1); setexponentpos(st_new_ptr, 0); setsign(st_new_ptr, sign); FPU_settag0(TAG_Valid); return; } else if (st0_tag == TAG_Zero) { sign = getsign(st0_ptr); if (FPU_divide_by_zero(0, SIGN_NEG) < 0) return; push(); FPU_copy_to_reg0(&CONST_Z, TAG_Zero); setsign(st_new_ptr, sign); return; } if (st0_tag == TAG_Special) st0_tag = FPU_Special(st0_ptr); if (st0_tag == TW_Denormal) { if (denormal_operand() < 0) return; push(); sign = getsign(st1_ptr); FPU_to_exp16(st1_ptr, st_new_ptr); goto denormal_arg; } else if (st0_tag == TW_Infinity) { sign = getsign(st0_ptr); setpositive(st0_ptr); push(); FPU_copy_to_reg0(&CONST_INF, TAG_Special); setsign(st_new_ptr, sign); return; } else if (st0_tag == TW_NaN) { if (real_1op_NaN(st0_ptr) < 0) return; push(); FPU_copy_to_reg0(st0_ptr, TAG_Special); return; } else if (st0_tag == TAG_Empty) { if (control_word & EX_Invalid) { FPU_stack_underflow(); push(); FPU_stack_underflow(); } else EXCEPTION(EX_StackUnder); } #ifdef PARANOID else EXCEPTION(EX_INTERNAL | 0x119); #endif }
static void fptan(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st_new_ptr; int q; u_char arg_sign = getsign(st0_ptr); if (st0_tag == TAG_Empty) { FPU_stack_underflow(); if (control_word & CW_Invalid) { st_new_ptr = &st(-1); push(); FPU_stack_underflow(); } return; } if (STACK_OVERFLOW) { FPU_stack_overflow(); return; } if (st0_tag == TAG_Valid) { if (exponent(st0_ptr) > -40) { if ((q = trig_arg(st0_ptr, 0)) == -1) { return; } poly_tan(st0_ptr); setsign(st0_ptr, (q & 1) ^ (arg_sign != 0)); set_precision_flag_up(); } else { denormal_arg: FPU_to_exp16(st0_ptr, st0_ptr); st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign); FPU_settag0(st0_tag); } push(); FPU_copy_to_reg0(&CONST_1, TAG_Valid); return; } if (st0_tag == TAG_Zero) { push(); FPU_copy_to_reg0(&CONST_1, TAG_Valid); setcc(0); return; } if (st0_tag == TAG_Special) st0_tag = FPU_Special(st0_ptr); if (st0_tag == TW_Denormal) { if (denormal_operand() < 0) return; goto denormal_arg; } if (st0_tag == TW_Infinity) { if (arith_invalid(0) >= 0) { st_new_ptr = &st(-1); push(); arith_invalid(0); } return; } single_arg_2_error(st0_ptr, st0_tag); }
static void fptan(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st_new_ptr; int q; u_char arg_sign = getsign(st0_ptr); /* Stack underflow has higher priority */ if (st0_tag == TAG_Empty) { FPU_stack_underflow(); /* Puts a QNaN in st(0) */ if (control_word & CW_Invalid) { st_new_ptr = &st(-1); push(); FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */ } return; } if (STACK_OVERFLOW) { FPU_stack_overflow(); return; } if (st0_tag == TAG_Valid) { if (exponent(st0_ptr) > -40) { if ((q = trig_arg(st0_ptr, 0)) == -1) { /* Operand is out of range */ return; } poly_tan(st0_ptr); setsign(st0_ptr, (q & 1) ^ (arg_sign != 0)); set_precision_flag_up(); /* We do not really know if up or down */ } else { /* For a small arg, the result == the argument */ /* Underflow may happen */ denormal_arg: FPU_to_exp16(st0_ptr, st0_ptr); st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign); FPU_settag0(st0_tag); } push(); FPU_copy_to_reg0(&CONST_1, TAG_Valid); return; } if (st0_tag == TAG_Zero) { push(); FPU_copy_to_reg0(&CONST_1, TAG_Valid); setcc(0); return; } if (st0_tag == TAG_Special) st0_tag = FPU_Special(st0_ptr); if (st0_tag == TW_Denormal) { if (denormal_operand() < 0) return; goto denormal_arg; } if (st0_tag == TW_Infinity) { /* The 80486 treats infinity as an invalid operand */ if (arith_invalid(0) >= 0) { st_new_ptr = &st(-1); push(); arith_invalid(0); } return; } single_arg_2_error(st0_ptr, st0_tag); }