⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 errors.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
      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 + -