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

📄 reg_ld_str.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	  if ( tmp.sigl & 0x000007ff )	    {	      precision_loss = 1;	      switch (control_word & CW_RC)		{		case RC_RND:		  /* Rounding can get a little messy.. */		  increment = ((tmp.sigl & 0x7ff) > 0x400) |  /* nearest */		    ((tmp.sigl & 0xc00) == 0xc00);            /* odd -> even */		  break;		case RC_DOWN:   /* towards -infinity */		  increment = signpositive(&tmp) ? 0 : tmp.sigl & 0x7ff;		  break;		case RC_UP:     /* towards +infinity */		  increment = signpositive(&tmp) ? tmp.sigl & 0x7ff : 0;		  break;		case RC_CHOP:		  increment = 0;		  break;		}	  	      /* Truncate the mantissa */	      tmp.sigl &= 0xfffff800;	  	      if ( increment )		{		  if ( tmp.sigl >= 0xfffff800 )		    {		      /* the sigl part overflows */		      if ( tmp.sigh == 0xffffffff )			{			  /* The sigh part overflows */			  tmp.sigh = 0x80000000;			  exp++;			  if (exp >= EXP_OVER)			    goto overflow;			}		      else			{			  tmp.sigh ++;			}		      tmp.sigl = 0x00000000;		    }		  else		    {		      /* We only need to increment sigl */		      tmp.sigl += 0x00000800;		    }		}	    }	  else	    precision_loss = 0;	  	  l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);	  l[1] = ((tmp.sigh >> 11) & 0xfffff);	  if ( exp > DOUBLE_Emax )	    {	    overflow:	      EXCEPTION(EX_Overflow);	      if ( !(control_word & CW_Overflow) )		return 0;	      set_precision_flag_up();	      if ( !(control_word & CW_Precision) )		return 0;	      /* This is a special case: see sec 16.2.5.1 of the 80486 book */	      /* Overflow to infinity */	      l[0] = 0x00000000;	/* Set to */	      l[1] = 0x7ff00000;	/* + INF */	    }	  else	    {	      if ( precision_loss )		{		  if ( increment )		    set_precision_flag_up();		  else		    set_precision_flag_down();		}	      /* Add the exponent */	      l[1] |= (((exp+DOUBLE_Ebias) & 0x7ff) << 20);	    }	}    }  else if (st0_tag == TAG_Zero)    {      /* Number is zero */      l[0] = 0;      l[1] = 0;    }  else if ( st0_tag == TAG_Special )    {      st0_tag = FPU_Special(st0_ptr);      if ( st0_tag == TW_Denormal )	{	  /* A denormal will always underflow. */#ifndef PECULIAR_486	  /* An 80486 is supposed to be able to generate	     a denormal exception here, but... */	  /* Underflow has priority. */	  if ( control_word & CW_Underflow )	    denormal_operand();#endif /* PECULIAR_486 */	  reg_copy(st0_ptr, &tmp);	  goto denormal_arg;	}      else if (st0_tag == TW_Infinity)	{	  l[0] = 0;	  l[1] = 0x7ff00000;	}      else if (st0_tag == TW_NaN)	{	  /* Is it really a NaN ? */	  if ( (exponent(st0_ptr) == EXP_OVER)	       && (st0_ptr->sigh & 0x80000000) )	    {	      /* See if we can get a valid NaN from the FPU_REG */	      l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21);	      l[1] = ((st0_ptr->sigh >> 11) & 0xfffff);	      if ( !(st0_ptr->sigh & 0x40000000) )		{		  /* It is a signalling NaN */		  EXCEPTION(EX_Invalid);		  if ( !(control_word & CW_Invalid) )		    return 0;		  l[1] |= (0x40000000 >> 11);		}	      l[1] |= 0x7ff00000;	    }	  else	    {	      /* It is an unsupported data type */	      EXCEPTION(EX_Invalid);	      if ( !(control_word & CW_Invalid) )		return 0;	      l[0] = 0;	      l[1] = 0xfff80000;	    }	}    }  else if ( st0_tag == TAG_Empty )    {      /* Empty register (stack underflow) */      EXCEPTION(EX_StackUnder);      if ( control_word & CW_Invalid )	{	  /* The masked response */	  /* Put out the QNaN indefinite */	  RE_ENTRANT_CHECK_OFF;	  FPU_access_ok(VERIFY_WRITE,dfloat,8);	  FPU_put_user(0, (unsigned long __user *) dfloat);	  FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat);	  RE_ENTRANT_CHECK_ON;	  return 1;	}      else	return 0;    }  if ( getsign(st0_ptr) )    l[1] |= 0x80000000;  RE_ENTRANT_CHECK_OFF;  FPU_access_ok(VERIFY_WRITE,dfloat,8);  FPU_put_user(l[0], (unsigned long __user *)dfloat);  FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat);  RE_ENTRANT_CHECK_ON;  return 1;}/* Put a float into user memory */int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single){  long templ = 0;  unsigned long increment = 0;     	/* avoid gcc warnings */  int precision_loss;  int exp;  FPU_REG tmp;  if ( st0_tag == TAG_Valid )    {      reg_copy(st0_ptr, &tmp);      exp = exponent(&tmp);      if ( exp < SINGLE_Emin )	{	  addexponent(&tmp, -SINGLE_Emin + 23);  /* largest exp to be 22 */	denormal_arg:	  if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )	    {#ifdef PECULIAR_486	      /* Did it round to a non-denormal ? */	      /* This behaviour might be regarded as peculiar, it appears		 that the 80486 rounds to the dest precision, then		 converts to decide underflow. */	      if ( !((tmp.sigl == 0x00800000) &&		  ((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) )#endif /* PECULIAR_486 */		{		  EXCEPTION(EX_Underflow);		  /* This is a special case: see sec 16.2.5.1 of		     the 80486 book */		  if ( !(control_word & CW_Underflow) )		    return 0;		}	      EXCEPTION(precision_loss);	      if ( !(control_word & CW_Precision) )		return 0;	    }	  templ = tmp.sigl;      }      else	{	  if ( tmp.sigl | (tmp.sigh & 0x000000ff) )	    {	      unsigned long sigh = tmp.sigh;	      unsigned long sigl = tmp.sigl;	      	      precision_loss = 1;	      switch (control_word & CW_RC)		{		case RC_RND:		  increment = ((sigh & 0xff) > 0x80)       /* more than half */		    || (((sigh & 0xff) == 0x80) && sigl)   /* more than half */		    || ((sigh & 0x180) == 0x180);        /* round to even */		  break;		case RC_DOWN:   /* towards -infinity */		  increment = signpositive(&tmp)		    ? 0 : (sigl | (sigh & 0xff));		  break;		case RC_UP:     /* towards +infinity */		  increment = signpositive(&tmp)		    ? (sigl | (sigh & 0xff)) : 0;		  break;		case RC_CHOP:		  increment = 0;		  break;		}	  	      /* Truncate part of the mantissa */	      tmp.sigl = 0;	  	      if (increment)		{		  if ( sigh >= 0xffffff00 )		    {		      /* The sigh part overflows */		      tmp.sigh = 0x80000000;		      exp++;		      if ( exp >= EXP_OVER )			goto overflow;		    }		  else		    {		      tmp.sigh &= 0xffffff00;		      tmp.sigh += 0x100;		    }		}	      else		{		  tmp.sigh &= 0xffffff00;  /* Finish the truncation */		}	    }	  else	    precision_loss = 0;      	  templ = (tmp.sigh >> 8) & 0x007fffff;	  if ( exp > SINGLE_Emax )	    {	    overflow:	      EXCEPTION(EX_Overflow);	      if ( !(control_word & CW_Overflow) )		return 0;	      set_precision_flag_up();	      if ( !(control_word & CW_Precision) )		return 0;	      /* This is a special case: see sec 16.2.5.1 of the 80486 book. */	      /* Masked response is overflow to infinity. */	      templ = 0x7f800000;	    }	  else	    {	      if ( precision_loss )		{		  if ( increment )		    set_precision_flag_up();		  else		    set_precision_flag_down();		}	      /* Add the exponent */	      templ |= ((exp+SINGLE_Ebias) & 0xff) << 23;	    }	}    }  else if (st0_tag == TAG_Zero)    {      templ = 0;    }  else if ( st0_tag == TAG_Special )    {      st0_tag = FPU_Special(st0_ptr);      if (st0_tag == TW_Denormal)	{	  reg_copy(st0_ptr, &tmp);	  /* A denormal will always underflow. */#ifndef PECULIAR_486	  /* An 80486 is supposed to be able to generate	     a denormal exception here, but... */	  /* Underflow has priority. */	  if ( control_word & CW_Underflow )	    denormal_operand();#endif /* PECULIAR_486 */ 	  goto denormal_arg;	}      else if (st0_tag == TW_Infinity)	{	  templ = 0x7f800000;	}      else if (st0_tag == TW_NaN)	{	  /* Is it really a NaN ? */	  if ( (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000) )	    {	      /* See if we can get a valid NaN from the FPU_REG */	      templ = st0_ptr->sigh >> 8;	      if ( !(st0_ptr->sigh & 0x40000000) )		{		  /* It is a signalling NaN */		  EXCEPTION(EX_Invalid);		  if ( !(control_word & CW_Invalid) )		    return 0;		  templ |= (0x40000000 >> 8);		}	      templ |= 0x7f800000;	    }	  else	    {	      /* It is an unsupported data type */	      EXCEPTION(EX_Invalid);	      if ( !(control_word & CW_Invalid) )		return 0;	      templ = 0xffc00000;	    }	}#ifdef PARANOID      else	{	  EXCEPTION(EX_INTERNAL|0x164);	  return 0;	}#endif    }  else if ( st0_tag == TAG_Empty )    {      /* Empty register (stack underflow) */      EXCEPTION(EX_StackUnder);      if ( control_word & EX_Invalid )	{	  /* The masked response */	  /* Put out the QNaN indefinite */	  RE_ENTRANT_CHECK_OFF;	  FPU_access_ok(VERIFY_WRITE,single,4);	  FPU_put_user(0xffc00000, (unsigned long __user *) single);	  RE_ENTRANT_CHECK_ON;	  return 1;	}      else	return 0;    }#ifdef PARANOID  else    {      EXCEPTION(EX_INTERNAL|0x163);      return 0;    }#endif  if ( getsign(st0_ptr) )    templ |= 0x80000000;  RE_ENTRANT_CHECK_OFF;  FPU_access_ok(VERIFY_WRITE,single,4);  FPU_put_user(templ,(unsigned long __user *) single);  RE_ENTRANT_CHECK_ON;  return 1;}/* Put a long long into user memory */int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d){  FPU_REG t;  long long tll;  int precision_loss;  if ( st0_tag == TAG_Empty )    {      /* Empty register (stack underflow) */      EXCEPTION(EX_StackUnder);      goto invalid_operand;    }  else if ( st0_tag == TAG_Special )    {      st0_tag = FPU_Special(st0_ptr);      if ( (st0_tag == TW_Infinity) ||	   (st0_tag == TW_NaN) )	{	  EXCEPTION(EX_Invalid);	  goto invalid_operand;	}    }  reg_copy(st0_ptr, &t);  precision_loss = FPU_round_to_int(&t, st0_tag);  ((long *)&tll)[0] = t.sigl;  ((long *)&tll)[1] = t.sigh;  if ( (precision_loss == 1) ||      ((t.sigh & 0x80000000) &&       !((t.sigh == 0x80000000) && (t.sigl == 0) &&	 signnegative(&t))) )    {      EXCEPTION(EX_Invalid);      /* This is a special case: see sec 16.2.5.1 of the 80486 book */    invalid_operand:      if ( control_word & EX_Invalid )	{	  /* Produce something like QNaN "indefinite" */	  tll = 0x8000000000000000LL;	}      else	return 0;    }  else    {      if ( precision_loss )	set_precision_flag(precision_loss);      if ( signnegative(&t) )	tll = - tll;    }  RE_ENTRANT_CHECK_OFF;  FPU_access_ok(VERIFY_WRITE,d,8);  if (copy_to_user(d, &tll, 8))    FPU_abort;  RE_ENTRANT_CHECK_ON;  return 1;}

⌨️ 快捷键说明

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