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

📄 sim-fpu.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  }}INLINE_SIM_FPU (int)sim_fpu_mul (sim_fpu *f,	     const sim_fpu *l,	     const sim_fpu *r){  if (sim_fpu_is_snan (l))    {      *f = *l;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_snan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (l))    {      *f = *l;      return 0;    }  if (sim_fpu_is_qnan (r))    {      *f = *r;      return 0;    }  if (sim_fpu_is_infinity (l))    {      if (sim_fpu_is_zero (r))	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_imz;	}      *f = *l;      f->sign = l->sign ^ r->sign;      return 0;    }  if (sim_fpu_is_infinity (r))    {      if (sim_fpu_is_zero (l))	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_imz;	}      *f = *r;      f->sign = l->sign ^ r->sign;      return 0;    }  if (sim_fpu_is_zero (l) || sim_fpu_is_zero (r))    {      *f = sim_fpu_zero;      f->sign = l->sign ^ r->sign;      return 0;    }  /* Calculate the mantissa by multiplying both 64bit numbers to get a     128 bit number */  {    unsigned64 low;    unsigned64 high;    unsigned64 nl = l->fraction & 0xffffffff;    unsigned64 nh = l->fraction >> 32;    unsigned64 ml = r->fraction & 0xffffffff;    unsigned64 mh = r->fraction >>32;    unsigned64 pp_ll = ml * nl;    unsigned64 pp_hl = mh * nl;    unsigned64 pp_lh = ml * nh;    unsigned64 pp_hh = mh * nh;    unsigned64 res2 = 0;    unsigned64 res0 = 0;    unsigned64 ps_hh__ = pp_hl + pp_lh;    if (ps_hh__ < pp_hl)      res2 += UNSIGNED64 (0x100000000);    pp_hl = (ps_hh__ << 32) & UNSIGNED64 (0xffffffff00000000);    res0 = pp_ll + pp_hl;    if (res0 < pp_ll)      res2++;    res2 += ((ps_hh__ >> 32) & 0xffffffff) + pp_hh;    high = res2;    low = res0;        f->normal_exp = l->normal_exp + r->normal_exp;    f->sign = l->sign ^ r->sign;    f->class = sim_fpu_class_number;    /* Input is bounded by [1,2)   ;   [2^60,2^61)       Output is bounded by [1,4)  ;   [2^120,2^122) */     /* Adjust the exponent according to where the decimal point ended       up in the high 64 bit word.  In the source the decimal point       was at NR_FRAC_GUARD. */    f->normal_exp += NR_FRAC_GUARD + 64 - (NR_FRAC_GUARD * 2);    /* The high word is bounded according to the above.  Consequently       it has never overflowed into IMPLICIT_2. */    ASSERT (high < LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64));    ASSERT (high >= LSBIT64 ((NR_FRAC_GUARD * 2) - 64));    ASSERT (LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64) < IMPLICIT_1);    /* normalize */    do      {	f->normal_exp--;	high <<= 1;	if (low & LSBIT64 (63))	  high |= 1;	low <<= 1;      }    while (high < IMPLICIT_1);    ASSERT (high >= IMPLICIT_1 && high < IMPLICIT_2);    if (low != 0)      {	f->fraction = (high | 1); /* sticky */	return sim_fpu_status_inexact;      }    else      {	f->fraction = high;	return 0;      }    return 0;  }}INLINE_SIM_FPU (int)sim_fpu_div (sim_fpu *f,	     const sim_fpu *l,	     const sim_fpu *r){  if (sim_fpu_is_snan (l))    {      *f = *l;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_snan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (l))    {      *f = *l;      f->class = sim_fpu_class_qnan;      return 0;    }  if (sim_fpu_is_qnan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return 0;    }  if (sim_fpu_is_infinity (l))    {      if (sim_fpu_is_infinity (r))	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_idi;	}      else	{	  *f = *l;	  f->sign = l->sign ^ r->sign;	  return 0;	}    }  if (sim_fpu_is_zero (l))    {      if (sim_fpu_is_zero (r))	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_zdz;	}      else	{	  *f = *l;	  f->sign = l->sign ^ r->sign;	  return 0;	}    }  if (sim_fpu_is_infinity (r))    {      *f = sim_fpu_zero;      f->sign = l->sign ^ r->sign;      return 0;    }  if (sim_fpu_is_zero (r))    {      f->class = sim_fpu_class_infinity;      f->sign = l->sign ^ r->sign;      return sim_fpu_status_invalid_div0;    }  /* Calculate the mantissa by multiplying both 64bit numbers to get a     128 bit number */  {    /* quotient =  ( ( numerator / denominator)                      x 2^(numerator exponent -  denominator exponent)     */    unsigned64 numerator;    unsigned64 denominator;    unsigned64 quotient;    unsigned64 bit;    f->class = sim_fpu_class_number;    f->sign = l->sign ^ r->sign;    f->normal_exp = l->normal_exp - r->normal_exp;    numerator = l->fraction;    denominator = r->fraction;    /* Fraction will be less than 1.0 */    if (numerator < denominator)      {	numerator <<= 1;	f->normal_exp--;      }    ASSERT (numerator >= denominator);        /* Gain extra precision, already used one spare bit */    numerator <<=    NR_SPARE;    denominator <<=  NR_SPARE;    /* Does divide one bit at a time.  Optimize???  */    quotient = 0;    bit = (IMPLICIT_1 << NR_SPARE);    while (bit)      {	if (numerator >= denominator)	  {	    quotient |= bit;	    numerator -= denominator;	  }	bit >>= 1;	numerator <<= 1;      }    /* discard (but save) the extra bits */    if ((quotient & LSMASK64 (NR_SPARE -1, 0)))      quotient = (quotient >> NR_SPARE) | 1;    else      quotient = (quotient >> NR_SPARE);    f->fraction = quotient;    ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2);    if (numerator != 0)      {	f->fraction |= 1; /* stick remaining bits */	return sim_fpu_status_inexact;      }    else      return 0;  }}INLINE_SIM_FPU (int)sim_fpu_max (sim_fpu *f,	     const sim_fpu *l,	     const sim_fpu *r){  if (sim_fpu_is_snan (l))    {      *f = *l;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_snan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (l))    {      *f = *l;      return 0;    }  if (sim_fpu_is_qnan (r))    {      *f = *r;      return 0;    }  if (sim_fpu_is_infinity (l))    {      if (sim_fpu_is_infinity (r)	  && l->sign == r->sign)	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_isi;	}      if (l->sign)	*f = *r; /* -inf < anything */      else	*f = *l; /* +inf > anthing */      return 0;    }  if (sim_fpu_is_infinity (r))    {      if (r->sign)	*f = *l; /* anything > -inf */      else	*f = *r; /* anthing < +inf */      return 0;    }  if (l->sign > r->sign)    {      *f = *r; /* -ve < +ve */      return 0;    }  if (l->sign < r->sign)    {      *f = *l; /* +ve > -ve */      return 0;    }  ASSERT (l->sign == r->sign);  if (l->normal_exp > r->normal_exp      || (l->normal_exp == r->normal_exp && 	  l->fraction > r->fraction))    {      /* |l| > |r| */      if (l->sign)	*f = *r; /* -ve < -ve */      else	*f = *l; /* +ve > +ve */      return 0;    }  else    {      /* |l| <= |r| */      if (l->sign)	*f = *l; /* -ve > -ve */      else	*f = *r; /* +ve < +ve */      return 0;    }}INLINE_SIM_FPU (int)sim_fpu_min (sim_fpu *f,	     const sim_fpu *l,	     const sim_fpu *r){  if (sim_fpu_is_snan (l))    {      *f = *l;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_snan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (l))    {      *f = *l;      return 0;    }  if (sim_fpu_is_qnan (r))    {      *f = *r;      return 0;    }  if (sim_fpu_is_infinity (l))    {      if (sim_fpu_is_infinity (r)	  && l->sign == r->sign)	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_isi;	}      if (l->sign)	*f = *l; /* -inf < anything */      else	*f = *r; /* +inf > anthing */      return 0;    }  if (sim_fpu_is_infinity (r))    {      if (r->sign)	*f = *r; /* anything > -inf */      else	*f = *l; /* anything < +inf */      return 0;    }  if (l->sign > r->sign)    {      *f = *l; /* -ve < +ve */      return 0;    }  if (l->sign < r->sign)    {      *f = *r; /* +ve > -ve */      return 0;    }  ASSERT (l->sign == r->sign);  if (l->normal_exp > r->normal_exp      || (l->normal_exp == r->normal_exp && 	  l->fraction > r->fraction))    {      /* |l| > |r| */      if (l->sign)	*f = *l; /* -ve < -ve */      else	*f = *r; /* +ve > +ve */      return 0;    }  else    {      /* |l| <= |r| */      if (l->sign)	*f = *r; /* -ve > -ve */      else	*f = *l; /* +ve < +ve */      return 0;    }}INLINE_SIM_FPU (int)sim_fpu_neg (sim_fpu *f,	     const sim_fpu *r){  if (sim_fpu_is_snan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (r))    {      *f = *r;      return 0;    }  *f = *r;  f->sign = !r->sign;  return 0;}INLINE_SIM_FPU (int)sim_fpu_abs (sim_fpu *f,	     const sim_fpu *r){  if (sim_fpu_is_snan (r))    {      *f = *r;      f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (r))    {      *f = *r;      return 0;    }  *f = *r;  f->sign = 0;  return 0;}INLINE_SIM_FPU (int)sim_fpu_inv (sim_fpu *f,	     const sim_fpu *r){  return sim_fpu_div (f, &sim_fpu_one, r);}INLINE_SIM_FPU (int)sim_fpu_sqrt (sim_fpu *f,	      const sim_fpu *r){  if (sim_fpu_is_snan (r))    {      *f = sim_fpu_qnan;      return sim_fpu_status_invalid_snan;    }  if (sim_fpu_is_qnan (r))    {      *f = sim_fpu_qnan;      return 0;    }  if (sim_fpu_is_zero (r))    {      f->class = sim_fpu_class_zero;      f->sign = r->sign;      f->normal_exp = 0;      return 0;    }  if (sim_fpu_is_infinity (r))    {      if (r->sign)	{	  *f = sim_fpu_qnan;	  return sim_fpu_status_invalid_sqrt;	}      else	{	  f->class = sim_fpu_class_infinity;	  f->sign = 0;	  f->sign = 0;	  return 0;	}    }  if (r->sign)    {      *f = sim_fpu_qnan;      return sim_fpu_status_invalid_sqrt;    }  /* @(#)e_sqrt.c 5.1 93/09/24 */  /*   * ====================================================   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.   *   * Developed at SunPro, a Sun Microsystems, Inc. business.   * Permission to use, copy, modify, and distribute this   * software is freely granted, provided that this notice    * is preserved.   * ====================================================   */    /* __ieee754_sqrt(x)   * Return correctly rounded sqrt.   *           ------------------------------------------   *           |  Use the hardware sqrt if you have one |   *           ------------------------------------------   * Method:    *   Bit by bit method using integer arithmetic. (Slow, but portable)    *   1. Normalization   *	Scale x to y in [1,4) with even powers of 2:    *	find an integer k such that  1 <= (y=x*2^(2k)) < 4, then   *		sqrt(x) = 2^k * sqrt(y)   -   - Since:   -   sqrt ( x*2^(2m) )     = sqrt(x).2^m    ; m even   -   sqrt ( x*2^(2m + 1) ) = sqrt(2.x).2^m  ; m odd   - Define:   -   y = ((m even) ? x : 2.x)   - Then:   -   y in [1, 4)                            ; [IMPLICIT_1,IMPLICIT_4)   - And:   -   sqrt (y) in [1, 2)                     ; [IMPLICIT_1,IMPLICIT_2)   -   *   2. Bit by bit computation   *	Let q  = sqrt(y) truncated to i bit after binary point (q = 1),   *	     i							 0   *                                     i+1         2   *	    s  = 2*q , and	y  =  2   * ( y - q  ).		(1)   *	     i      i            i                 i   *                                                           *	To compute q    from q , one checks whether    *		    i+1       i                          *   *			      -(i+1) 2   *			(q + 2      ) <= y.			(2)   *     			  i   *							      -(i+1)   *	If (2) is false, then q   = q ; otherwise q   = q  + 2      .   *		 	       i+1   i             i+1   i   *   *	With some algebric manipulation, it is not difficult to see   *	that (2) is equivalent to    *                             -(i+1)   *			s  +  2       <= y			(3)   *			 i                i   *   *	The advantage of (3) is that s  and y  can be computed by    *				      i      i   *	the following recurrence formula:   *	    if (3) is false   *   *	    s     =  s  ,	y    = y   ;			(4)   *	     i+1      i		 i+1    i   *   -   -                      NOTE: y    = 2*y   -                             i+1      i   -   *	    otherwise,   *                       -i                      -(i+1)   *	    s	  =  s  + 2  ,  y    = y  -  s  - 2  		(5)   *         i+1      i          i+1    i     i   *				   -   -                                                   -(i+1)   -                      NOTE: y    = 2 (y  -  s  -  2      ) 		   -                             i+1       i     i   -   *	One may easily use induction to prove (4) and (5).    *	Note. Since the left hand side of (3) contain only i+2 bits,   *	      it does not necessary to do a full (53-bit) comparison    *	      in (3).   *   3. Final rounding   *	After generating the 53 bits result, we compute one more bit.   *	Together with the remainder, we can decide whether the   *	result is exact, bigger than 1/2ulp, or less than 1/2ulp   *	(it will never equal to 1/2ulp).   *	The rounding mode can be detected by checking whether   *	huge + tiny is equal to huge, and whether huge - tiny is   *	equal to huge for some floating point number "huge" and "tiny".   *		   * Special cases:   *	sqrt(+-0) = +-0 	... exact   *	sqrt(inf) = inf   *	sqrt(-ve) = NaN		... with invalid signal   *	sqrt(NaN) = NaN		... with invalid signal for signaling NaN   *   * Other methods : see the appended file at the end of the program below.   *---------------   */  {    /* generate sqrt(x) bit by bit */    unsigned64 y;    unsigned64 q;    unsigned64 s;    unsigned64 b;    f->class = sim_fpu_class_number;    f->sign = 0;    y = r->fraction;    f->normal_exp = (r->normal_exp >> 1);	/* exp = [exp/2] */    /* odd exp, double x to make it even */    ASSERT (y >= IMPLICIT_1 && y < IMPLICIT_4);    if ((r->normal_exp & 1))      {	y += y;      }    ASSERT (y >= IMPLICIT_1 && y < (IMPLICIT_2 << 1));

⌨️ 快捷键说明

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