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

📄 fpu_trig.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	      if ( arith_invalid(1) < 0 )		return;	    }	  else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  else	    {	      if ( exponent(st0_ptr) < 0 )		sign ^= SIGN_NEG;	      FPU_copy_to_reg1(&CONST_Z, TAG_Zero);	      setsign(st1_ptr, sign);	    }	}      else	{	  /* One or both operands are denormals. */	  if ( denormal_operand() < 0 )	    return;	  goto both_valid;	}    }  else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )    {      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )	return;    }  /* One or both arg must be an infinity */  else if ( st0_tag == TW_Infinity )    {      if ( (signnegative(st0_ptr)) || (st1_tag == TAG_Zero) )	{	  /* log(-infinity) or 0*log(infinity) */	  if ( arith_invalid(1) < 0 )	    return;	}      else	{	  u_char sign = getsign(st1_ptr);	  if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  FPU_copy_to_reg1(&CONST_INF, TAG_Special);	  setsign(st1_ptr, sign);	}    }  /* st(1) must be infinity here */  else if ( ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))	    && ( signpositive(st0_ptr) ) )    {      if ( exponent(st0_ptr) >= 0 )	{	  if ( (exponent(st0_ptr) == 0) &&	      (st0_ptr->sigh == 0x80000000) &&	      (st0_ptr->sigl == 0) )	    {	      /* st(0) holds 1.0 */	      /* infinity*log(1) */	      if ( arith_invalid(1) < 0 )		return;	    }	  /* else st(0) is positive and > 1.0 */	}      else	{	  /* st(0) is positive and < 1.0 */	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  changesign(st1_ptr);	}    }  else    {      /* st(0) must be zero or negative */      if ( st0_tag == TAG_Zero )	{	  /* This should be invalid, but a real 80486 is happy with it. */#ifndef PECULIAR_486	  sign = getsign(st1_ptr);	  if ( FPU_divide_by_zero(1, sign) < 0 )	    return;#endif /* PECULIAR_486 */	  changesign(st1_ptr);	}      else if ( arith_invalid(1) < 0 )	  /* log(negative) */	return;    }  FPU_pop();}static void fpatan(FPU_REG *st0_ptr, u_char st0_tag){  FPU_REG *st1_ptr = &st(1);  u_char st1_tag = FPU_gettagi(1);  int tag;  clear_C1();  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )    {    valid_atan:      poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag);      FPU_pop();      return;    }  if ( st0_tag == TAG_Special )    st0_tag = FPU_Special(st0_ptr);  if ( st1_tag == TAG_Special )    st1_tag = FPU_Special(st1_ptr);  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))	    || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))	    || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )    {      if ( denormal_operand() < 0 )	return;      goto valid_atan;    }  else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )    {      FPU_stack_underflow_pop(1);      return;    }  else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )    {      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0 )	  FPU_pop();      return;    }  else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) )    {      u_char sign = getsign(st1_ptr);      if ( st0_tag == TW_Infinity )	{	  if ( st1_tag == TW_Infinity )	    {	      if ( signpositive(st0_ptr) )		{		  FPU_copy_to_reg1(&CONST_PI4, TAG_Valid);		}	      else		{		  setpositive(st1_ptr);		  tag = FPU_u_add(&CONST_PI4, &CONST_PI2, st1_ptr,				  FULL_PRECISION, SIGN_POS,				  exponent(&CONST_PI4), exponent(&CONST_PI2));		  if ( tag >= 0 )		    FPU_settagi(1, tag);		}	    }	  else	    {	      if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )		return;	      if ( signpositive(st0_ptr) )		{		  FPU_copy_to_reg1(&CONST_Z, TAG_Zero);		  setsign(st1_ptr, sign);   /* An 80486 preserves the sign */		  FPU_pop();		  return;		}	      else		{		  FPU_copy_to_reg1(&CONST_PI, TAG_Valid);		}	    }	}      else	{	  /* st(1) is infinity, st(0) not infinity */	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);	}      setsign(st1_ptr, sign);    }  else if ( st1_tag == TAG_Zero )    {      /* st(0) must be valid or zero */      u_char sign = getsign(st1_ptr);      if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	return;      if ( signpositive(st0_ptr) )	{	  /* An 80486 preserves the sign */	  FPU_pop();	  return;	}      FPU_copy_to_reg1(&CONST_PI, TAG_Valid);      setsign(st1_ptr, sign);    }  else if ( st0_tag == TAG_Zero )    {      /* st(1) must be TAG_Valid here */      u_char sign = getsign(st1_ptr);      if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )	return;      FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);      setsign(st1_ptr, sign);    }#ifdef PARANOID  else    EXCEPTION(EX_INTERNAL | 0x125);#endif /* PARANOID */  FPU_pop();  set_precision_flag_up();  /* We do not really know if up or down */}static void fprem(FPU_REG *st0_ptr, u_char st0_tag){  do_fprem(st0_ptr, st0_tag, RC_CHOP);}static void fprem1(FPU_REG *st0_ptr, u_char st0_tag){  do_fprem(st0_ptr, st0_tag, RC_RND);}static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag){  u_char sign, sign1;  FPU_REG *st1_ptr = &st(1), a, b;  u_char st1_tag = FPU_gettagi(1);  clear_C1();  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )    {    valid_yl2xp1:      sign = getsign(st0_ptr);      sign1 = getsign(st1_ptr);      FPU_to_exp16(st0_ptr, &a);      FPU_to_exp16(st1_ptr, &b);      if ( poly_l2p1(sign, sign1, &a, &b, st1_ptr) )	return;      FPU_pop();      return;    }  if ( st0_tag == TAG_Special )    st0_tag = FPU_Special(st0_ptr);  if ( st1_tag == TAG_Special )    st1_tag = FPU_Special(st1_ptr);  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))	    || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))	    || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )    {      if ( denormal_operand() < 0 )	return;      goto valid_yl2xp1;    }  else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )    {      FPU_stack_underflow_pop(1);      return;    }  else if ( st0_tag == TAG_Zero )    {      switch ( st1_tag )	{	case TW_Denormal:	  if ( denormal_operand() < 0 )	    return;	case TAG_Zero:	case TAG_Valid:	  setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));	  FPU_copy_to_reg1(st0_ptr, st0_tag);	  break;	case TW_Infinity:	  /* Infinity*log(1) */	  if ( arith_invalid(1) < 0 )	    return;	  break;	case TW_NaN:	  if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )	    return;	  break;	default:#ifdef PARANOID	  EXCEPTION(EX_INTERNAL | 0x116);	  return;#endif /* PARANOID */	  break;	}    }  else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )    {      switch ( st1_tag )	{	case TAG_Zero:	  if ( signnegative(st0_ptr) )	    {	      if ( exponent(st0_ptr) >= 0 )		{		  /* st(0) holds <= -1.0 */#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */		  changesign(st1_ptr);#else		  if ( arith_invalid(1) < 0 )		    return;#endif /* PECULIAR_486 */		}	      else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )		return;	      else		changesign(st1_ptr);	    }	  else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  break;	case TW_Infinity:	  if ( signnegative(st0_ptr) )	    {	      if ( (exponent(st0_ptr) >= 0) &&		  !((st0_ptr->sigh == 0x80000000) &&		    (st0_ptr->sigl == 0)) )		{		  /* st(0) holds < -1.0 */#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */		  changesign(st1_ptr);#else		  if ( arith_invalid(1) < 0 ) return;#endif /* PECULIAR_486 */		}	      else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )		return;	      else		changesign(st1_ptr);	    }	  else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  break;	case TW_NaN:	  if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )	    return;	}    }  else if ( st0_tag == TW_NaN )    {      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )	return;    }  else if ( st0_tag == TW_Infinity )    {      if ( st1_tag == TW_NaN )	{	  if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )	    return;	}      else if ( signnegative(st0_ptr) )	{#ifndef PECULIAR_486	  /* This should have higher priority than denormals, but... */	  if ( arith_invalid(1) < 0 )  /* log(-infinity) */	    return;#endif /* PECULIAR_486 */	  if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;#ifdef PECULIAR_486	  /* Denormal operands actually get higher priority */	  if ( arith_invalid(1) < 0 )  /* log(-infinity) */	    return;#endif /* PECULIAR_486 */	}      else if ( st1_tag == TAG_Zero )	{	  /* log(infinity) */	  if ( arith_invalid(1) < 0 )	    return;	}	      /* st(1) must be valid here. */      else if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )	return;      /* The Manual says that log(Infinity) is invalid, but a real	 80486 sensibly says that it is o.k. */      else	{	  u_char sign = getsign(st1_ptr);	  FPU_copy_to_reg1(&CONST_INF, TAG_Special);	  setsign(st1_ptr, sign);	}    }#ifdef PARANOID  else    {      EXCEPTION(EX_INTERNAL | 0x117);      return;    }#endif /* PARANOID */  FPU_pop();  return;}static void fscale(FPU_REG *st0_ptr, u_char st0_tag){  FPU_REG *st1_ptr = &st(1);  u_char st1_tag = FPU_gettagi(1);  int old_cw = control_word;  u_char sign = getsign(st0_ptr);  clear_C1();  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )    {      long scale;      FPU_REG tmp;      /* Convert register for internal use. */      setexponent16(st0_ptr, exponent(st0_ptr));    valid_scale:      if ( exponent(st1_ptr) > 30 )	{	  /* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */	  if ( signpositive(st1_ptr) )	    {	      EXCEPTION(EX_Overflow);	      FPU_copy_to_reg0(&CONST_INF, TAG_Special);	    }	  else	    {	      EXCEPTION(EX_Underflow);	      FPU_copy_to_reg0(&CONST_Z, TAG_Zero);	    }	  setsign(st0_ptr, sign);	  return;	}      control_word &= ~CW_RC;      control_word |= RC_CHOP;      reg_copy(st1_ptr, &tmp);      FPU_round_to_int(&tmp, st1_tag);      /* This can never overflow here */      control_word = old_cw;      scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl;      scale += exponent16(st0_ptr);      setexponent16(st0_ptr, scale);      /* Use FPU_round() to properly detect under/overflow etc */      FPU_round(st0_ptr, 0, 0, control_word, sign);      return;    }  if ( st0_tag == TAG_Special )    st0_tag = FPU_Special(st0_ptr);  if ( st1_tag == TAG_Special )    st1_tag = FPU_Special(st1_ptr);  if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )    {      switch ( st1_tag )	{	case TAG_Valid:	  /* st(0) must be a denormal */	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  FPU_to_exp16(st0_ptr, st0_ptr);  /* Will not be left on stack */	  goto valid_scale;	case TAG_Zero:	  if ( st0_tag == TW_Denormal )	    denormal_operand();	  return;	case TW_Denormal:	  denormal_operand();	  return;	case TW_Infinity:	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )	    return;	  if ( signpositive(st1_ptr) )	    FPU_copy_to_reg0(&CONST_INF, TAG_Special);	  else	    FPU_copy_to_reg0(&CONST_Z, TAG_Zero);	  setsign(st0_ptr, sign);	  return;	case TW_NaN:	  real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);	  return;	}    }  else if ( st0_tag == TAG_Zero )    {      switch ( st1_tag )	{	case TAG_Valid:	case TAG_Zero:	  return;	case TW_Denormal:	  denormal_operand();	  return;	case TW_Infinity:	  if ( signpositive(st1_ptr) )	    arith_invalid(0); /* Zero scaled by +Infinity */	  return;	case TW_NaN:	  real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);	  return;	}    }  else if ( st0_tag == TW_Infinity )    {      switch ( st1_tag )	{	case TAG_Valid:	case TAG_Zero:	  return;	case TW_Denormal:	  denormal_operand();	  return;	case TW_Infinity:	  if ( signnegative(st1_ptr) )	    arith_invalid(0); /* Infinity scaled by -Infinity */	  return;	case TW_NaN:	  real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);	  return;	}    }  else if ( st0_tag == TW_NaN )    {      if ( st1_tag != TAG_Empty )	{ real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); return; }    }#ifdef PARANOID  if ( !((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) )    {      EXCEPTION(EX_INTERNAL | 0x115);      return;    }#endif  /* At least one of st(0), st(1) must be empty */  FPU_stack_underflow();}/*---------------------------------------------------------------------------*/static FUNC_ST0 const trig_table_a[] = {  f2xm1, fyl2x, fptan, fpatan,  fxtract, fprem1, (FUNC_ST0)fdecstp, (FUNC_ST0)fincstp};void FPU_triga(void){  (trig_table_a[FPU_rm])(&st(0), FPU_gettag0());}static FUNC_ST0 const trig_table_b[] =  {    fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0)fsin, fcos  };void FPU_trigb(void){  (trig_table_b[FPU_rm])(&st(0), FPU_gettag0());}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -