📄 errors.c
字号:
0x213 in wm_sqrt.S 0x214 in wm_sqrt.S 0x215 in wm_sqrt.S 0x216 in reg_round.S 0x217 in reg_round.S 0x218 in reg_round.S */voidexception(int n){ int i, int_type; int_type = 0; /* Needed only to stop compiler warnings */ if (n & EX_INTERNAL) { int_type = n - EX_INTERNAL; n = EX_INTERNAL; /* Set lots of exception bits! */ status_word |= (SW_Exc_Mask | SW_Summary | FPU_BUSY); } else { /* Extract only the bits which we use to set the status word */ n &= (SW_Exc_Mask); /* Set the corresponding exception bit */ status_word |= n; if (status_word & ~control_word & CW_Exceptions) status_word |= SW_Summary; if (n & (SW_Stack_Fault | EX_Precision)) { if (!(n & SW_C1)) /* This bit distinguishes over- from underflow * for a stack fault, and roundup from * round-down for precision loss. */ status_word &= ~SW_C1; } } REENTRANT_CHECK(OFF); if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) {#ifdef PRINT_MESSAGES /* My message from the sponsor */ printf(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n");#endif /* PRINT_MESSAGES */ /* Get a name string for error reporting */ for (i = 0; exception_names[i].type; i++) if ((exception_names[i].type & n) == exception_names[i].type) break; if (exception_names[i].type) {#ifdef PRINT_MESSAGES printf("FP Exception: %s!\n", exception_names[i].name);#endif /* PRINT_MESSAGES */ } else printf("FP emulator: Unknown Exception: 0x%04x!\n", n); if (n == EX_INTERNAL) { printf("FP emulator: Internal error type 0x%04x\n", int_type); emu_printall(); }#ifdef PRINT_MESSAGES else emu_printall();#endif /* PRINT_MESSAGES */ /* The 80486 generates an interrupt on the next non-control * FPU instruction. So we need some means of flagging it. We * use the ES (Error Summary) bit for this, assuming that this * is the way a real FPU does it (until I can check it out), * if not, then some method such as the following kludge might * be needed. *//* regs[0].tag |= TW_FPU_Interrupt; */ } REENTRANT_CHECK(ON);#ifdef __DEBUG__ math_abort(SIGFPE);#endif /* __DEBUG__ */}/* Real operation attempted on two operands, one a NaN */voidreal_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest){ FPU_REG *x; int signalling; x = a; if (a->tag == TW_NaN) { if (b->tag == TW_NaN) { signalling = !(a->sigh & b->sigh & 0x40000000); /* find the "larger" */ if (*(long long *) &(a->sigl) < *(long long *) &(b->sigl)) x = b; } else { /* return the quiet version of the NaN in a */ signalling = !(a->sigh & 0x40000000); } } else#ifdef PARANOID if (b->tag == TW_NaN)#endif /* PARANOID */ { signalling = !(b->sigh & 0x40000000); x = b; }#ifdef PARANOID else { signalling = 0; EXCEPTION(EX_INTERNAL | 0x113); x = &CONST_QNaN; }#endif /* PARANOID */ if (!signalling) { if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ x = &CONST_QNaN; reg_move(x, dest); return; } if (control_word & CW_Invalid) { /* The masked response */ if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ x = &CONST_QNaN; reg_move(x, dest); /* ensure a Quiet NaN */ dest->sigh |= 0x40000000; } EXCEPTION(EX_Invalid); return;}/* Invalid arith operation on Valid registers */voidarith_invalid(FPU_REG * dest){ if (control_word & CW_Invalid) { /* The masked response */ reg_move(&CONST_QNaN, dest); } EXCEPTION(EX_Invalid); return;}/* Divide a finite number by zero */voiddivide_by_zero(int sign, FPU_REG * dest){ if (control_word & CW_ZeroDiv) { /* The masked response */ reg_move(&CONST_INF, dest); dest->sign = (unsigned char) sign; } EXCEPTION(EX_ZeroDiv); return;}/* This may be called often, so keep it lean */voidset_precision_flag_up(void){ if (control_word & CW_Precision) status_word |= (SW_Precision | SW_C1); /* The masked response */ else exception(EX_Precision | SW_C1);}/* This may be called often, so keep it lean */voidset_precision_flag_down(void){ if (control_word & CW_Precision) { /* The masked response */ status_word &= ~SW_C1; status_word |= SW_Precision; } else exception(EX_Precision);}intdenormal_operand(void){ if (control_word & CW_Denormal) { /* The masked response */ status_word |= SW_Denorm_Op; return 0; } else { exception(EX_Denormal); return 1; }}voidarith_overflow(FPU_REG * dest){ if (control_word & CW_Overflow) { char sign; /* The masked response *//* **** The response here depends upon the rounding mode */ sign = dest->sign; reg_move(&CONST_INF, dest); dest->sign = sign; } else { /* Subtract the magic number from the exponent */ dest->exp -= (3 * (1 << 13)); } /* By definition, precision is lost. It appears that the roundup bit * (C1) is also set by convention. */ EXCEPTION(EX_Overflow | EX_Precision | SW_C1); return;}voidarith_underflow(FPU_REG * dest){ if (control_word & CW_Underflow) { /* The masked response */ if (dest->exp <= EXP_UNDER - 63) reg_move(&CONST_Z, dest); } else { /* Add the magic number to the exponent */ dest->exp += (3 * (1 << 13)); } EXCEPTION(EX_Underflow); return;}voidstack_overflow(void){ if (control_word & CW_Invalid) { /* The masked response */ top--; reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); } EXCEPTION(EX_StackOver); return;}voidstack_underflow(void){ if (control_word & CW_Invalid) { /* The masked response */ reg_move(&CONST_QNaN, FPU_st0_ptr); } EXCEPTION(EX_StackUnder); return;}voidstack_underflow_i(int i){ if (control_word & CW_Invalid) { /* The masked response */ reg_move(&CONST_QNaN, &(st(i))); } EXCEPTION(EX_StackUnder); return;}voidstack_underflow_pop(int i){ if (control_word & CW_Invalid) { /* The masked response */ reg_move(&CONST_QNaN, &(st(i))); pop(); } EXCEPTION(EX_StackUnder); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -