📄 errors.c
字号:
} else printk("FPU emulator: Unknown Exception: 0x%04x!\n", n); if ( n == EX_INTERNAL ) { printk("FPU 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; */ } RE_ENTRANT_CHECK_ON;#ifdef __DEBUG__ math_abort(FPU_info,SIGFPE);#endif __DEBUG__}/* Real operation attempted on two operands, one a NaN. *//* Returns nz if the exception is unmasked */asmlinkage int real_2op_NaN(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest){ FPU_REG const *x; int signalling; /* The default result for the case of two "equal" NaNs (signs may differ) is chosen to reproduce 80486 behaviour */ x = a; if (a->tag == TW_NaN) { if (b->tag == TW_NaN) { signalling = !(a->sigh & b->sigh & 0x40000000); /* find the "larger" */ if ( significand(a) < significand(b) ) 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 0; } 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 !(control_word & CW_Invalid);}/* Invalid arith operation on Valid registers *//* Returns nz if the exception is unmasked */asmlinkage int arith_invalid(FPU_REG *dest){ EXCEPTION(EX_Invalid); if ( control_word & CW_Invalid ) { /* The masked response */ reg_move(&CONST_QNaN, dest); } return !(control_word & CW_Invalid);}/* Divide a finite number by zero */asmlinkage int divide_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 !(control_word & CW_ZeroDiv);}/* 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 0; } else { exception(EX_Denormal); return 1; }}asmlinkage int arith_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)); } 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 !(control_word & CW_Precision); } return !(control_word & CW_Overflow);}asmlinkage int arith_underflow(FPU_REG *dest){ if ( control_word & CW_Underflow ) { /* The masked response */ if ( dest->exp <= EXP_UNDER - 63 ) { reg_move(&CONST_Z, dest); partial_status &= ~SW_C1; /* Round down. */ } } else { /* Add the magic number to the exponent. */ dest->exp += (3 * (1 << 13)); } EXCEPTION(EX_Underflow); if ( control_word & CW_Underflow ) { /* The underflow exception is masked. */ EXCEPTION(EX_Precision); return !(control_word & CW_Precision); } return !(control_word & CW_Underflow);}void stack_overflow(void){ if ( control_word & CW_Invalid ) { /* The masked response */ top--; reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); } EXCEPTION(EX_StackOver); return;}void stack_underflow(void){ if ( control_word & CW_Invalid ) { /* The masked response */ reg_move(&CONST_QNaN, FPU_st0_ptr); } EXCEPTION(EX_StackUnder); return;}void stack_underflow_i(int i){ if ( control_word & CW_Invalid ) { /* The masked response */ reg_move(&CONST_QNaN, &(st(i))); } EXCEPTION(EX_StackUnder); return;}void stack_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 + -