📄 errors.c
字号:
/* Real operation attempted on a NaN. *//* Returns < 0 if the exception is unmasked */int real_1op_NaN(FPU_REG *a){ int signalling, isNaN; isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000); /* The default result for the case of two "equal" NaNs (signs may differ) is chosen to reproduce 80486 behaviour */ signalling = isNaN && !(a->sigh & 0x40000000); if ( !signalling ) { if ( !isNaN ) /* pseudo-NaN, or other unsupported? */ { if ( control_word & CW_Invalid ) { /* Masked response */ reg_copy(&CONST_QNaN, a); } EXCEPTION(EX_Invalid); return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; } return TAG_Special; } if ( control_word & CW_Invalid ) { /* The masked response */ if ( !(a->sigh & 0x80000000) ) /* pseudo-NaN ? */ { reg_copy(&CONST_QNaN, a); } /* ensure a Quiet NaN */ a->sigh |= 0x40000000; } EXCEPTION(EX_Invalid); return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;}/* Real operation attempted on two operands, one a NaN. *//* Returns < 0 if the exception is unmasked */int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr, FPU_REG const *defaultNaN){ FPU_REG *dest = &st(deststnr); FPU_REG const *a = dest; u_char taga = FPU_gettagi(deststnr); FPU_REG const *x; int signalling, unsupported; if ( taga == TAG_Special ) taga = FPU_Special(a); if ( tagb == TAG_Special ) tagb = FPU_Special(b); /* TW_NaN is also used for unsupported data types. */ unsupported = ((taga == TW_NaN) && !((exponent(a) == EXP_OVER) && (a->sigh & 0x80000000))) || ((tagb == TW_NaN) && !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000))); if ( unsupported ) { if ( control_word & CW_Invalid ) { /* Masked response */ FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr); } EXCEPTION(EX_Invalid); return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; } if (taga == TW_NaN) { x = a; if (tagb == TW_NaN) { signalling = !(a->sigh & b->sigh & 0x40000000); if ( significand(b) > significand(a) ) x = b; else if ( significand(b) == significand(a) ) { /* The default result for the case of two "equal" NaNs (signs may differ) is chosen to reproduce 80486 behaviour */ x = defaultNaN; } } else { /* return the quiet version of the NaN in a */ signalling = !(a->sigh & 0x40000000); } } else#ifdef PARANOID if (tagb == 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) || (control_word & CW_Invalid) ) { if ( ! x ) x = b; if ( !(x->sigh & 0x80000000) ) /* pseudo-NaN ? */ x = &CONST_QNaN; FPU_copy_to_regi(x, TAG_Special, deststnr); if ( !signalling ) return TAG_Special; /* ensure a Quiet NaN */ dest->sigh |= 0x40000000; } EXCEPTION(EX_Invalid); return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;}/* Invalid arith operation on Valid registers *//* Returns < 0 if the exception is unmasked */asmlinkage int arith_invalid(int deststnr){ EXCEPTION(EX_Invalid); if ( control_word & CW_Invalid ) { /* The masked response */ FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr); } return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid;}/* Divide a finite number by zero */asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign){ FPU_REG *dest = &st(deststnr); int tag = TAG_Valid; if ( control_word & CW_ZeroDiv ) { /* The masked response */ FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr); setsign(dest, sign); tag = TAG_Special; } EXCEPTION(EX_ZeroDiv); return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag;}/* This may be called often, so keep it lean */int set_precision_flag(int flags){ if ( control_word & CW_Precision ) { partial_status &= ~(SW_C1 & flags); partial_status |= flags; /* The masked response */ return 0; } else { EXCEPTION(flags); return 1; }}/* This may be called often, so keep it lean */asmlinkage void set_precision_flag_up(void){ if ( control_word & CW_Precision ) partial_status |= (SW_Precision | SW_C1); /* The masked response */ else EXCEPTION(EX_Precision | SW_C1);}/* This may be called often, so keep it lean */asmlinkage void set_precision_flag_down(void){ if ( control_word & CW_Precision ) { /* The masked response */ partial_status &= ~SW_C1; partial_status |= SW_Precision; } else EXCEPTION(EX_Precision);}asmlinkage int denormal_operand(void){ if ( control_word & CW_Denormal ) { /* The masked response */ partial_status |= SW_Denorm_Op; return TAG_Special; } else { EXCEPTION(EX_Denormal); return TAG_Special | FPU_Exception; }}asmlinkage int arith_overflow(FPU_REG *dest){ int tag = TAG_Valid; if ( control_word & CW_Overflow ) { /* The masked response *//* ###### The response here depends upon the rounding mode */ reg_copy(&CONST_INF, dest); tag = TAG_Special; } else { /* Subtract the magic number from the exponent */ addexponent(dest, (-3 * (1 << 13))); } EXCEPTION(EX_Overflow); if ( control_word & CW_Overflow ) { /* The overflow exception is masked. */ /* By definition, precision is lost. The roundup bit (C1) is also set because we have "rounded" upwards to Infinity. */ EXCEPTION(EX_Precision | SW_C1); return tag; } return tag;}asmlinkage int arith_underflow(FPU_REG *dest){ int tag = TAG_Valid; if ( control_word & CW_Underflow ) { /* The masked response */ if ( exponent16(dest) <= EXP_UNDER - 63 ) { reg_copy(&CONST_Z, dest); partial_status &= ~SW_C1; /* Round down. */ tag = TAG_Zero; } else { stdexp(dest); } } else { /* Add the magic number to the exponent. */ addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias); } EXCEPTION(EX_Underflow); if ( control_word & CW_Underflow ) { /* The underflow exception is masked. */ EXCEPTION(EX_Precision); return tag; } return tag;}void FPU_stack_overflow(void){ if ( control_word & CW_Invalid ) { /* The masked response */ top--; FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); } EXCEPTION(EX_StackOver); return;}void FPU_stack_underflow(void){ if ( control_word & CW_Invalid ) { /* The masked response */ FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); } EXCEPTION(EX_StackUnder); return;}void FPU_stack_underflow_i(int i){ if ( control_word & CW_Invalid ) { /* The masked response */ FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i); } EXCEPTION(EX_StackUnder); return;}void FPU_stack_underflow_pop(int i){ if ( control_word & CW_Invalid ) { /* The masked response */ FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i); FPU_pop(); } EXCEPTION(EX_StackUnder); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -