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

📄 sim-fpu.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  return 0;}/* Convert an unsigned integer into a floating point */STATIC_INLINE_SIM_FPU (int)u2fpu (sim_fpu *f, unsigned64 u, int is_64bit){  if (u == 0)    {      f->class = sim_fpu_class_zero;      f->sign = 0;      f->normal_exp = 0;    }  else    {      f->class = sim_fpu_class_number;      f->sign = 0;      f->normal_exp = NR_FRAC_GUARD;      f->fraction = u;      while (f->fraction < IMPLICIT_1)	{	  f->fraction <<= 1;	  f->normal_exp -= 1;	}    }  return 0;}/* register <-> sim_fpu */INLINE_SIM_FPU (void)sim_fpu_32to (sim_fpu *f, unsigned32 s){  unpack_fpu (f, s, 0);}INLINE_SIM_FPU (void)sim_fpu_232to (sim_fpu *f, unsigned32 h, unsigned32 l){  unsigned64 s = h;  s = (s << 32) | l;  unpack_fpu (f, s, 1);}INLINE_SIM_FPU (void)sim_fpu_64to (sim_fpu *f, unsigned64 s){  unpack_fpu (f, s, 1);}INLINE_SIM_FPU (void)sim_fpu_to32 (unsigned32 *s,	      const sim_fpu *f){  *s = pack_fpu (f, 0);}INLINE_SIM_FPU (void)sim_fpu_to232 (unsigned32 *h, unsigned32 *l,	       const sim_fpu *f){  unsigned64 s = pack_fpu (f, 1);  *l = s;  *h = (s >> 32);}INLINE_SIM_FPU (void)sim_fpu_to64 (unsigned64 *u,	      const sim_fpu *f){  *u = pack_fpu (f, 1);}INLINE_SIM_FPU (void)sim_fpu_fractionto (sim_fpu *f,		    int sign,		    int normal_exp,		    unsigned64 fraction,		    int precision){  int shift = (NR_FRAC_GUARD - precision);  f->class = sim_fpu_class_number;  f->sign = sign;  f->normal_exp = normal_exp;  /* shift the fraction to where sim-fpu expects it */  if (shift >= 0)    f->fraction = (fraction << shift);  else    f->fraction = (fraction >> -shift);  f->fraction |= IMPLICIT_1;}INLINE_SIM_FPU (unsigned64)sim_fpu_tofraction (const sim_fpu *d,		    int precision){  /* we have NR_FRAC_GUARD bits, we want only PRECISION bits */  int shift = (NR_FRAC_GUARD - precision);  unsigned64 fraction = (d->fraction & ~IMPLICIT_1);  if (shift >= 0)    return fraction >> shift;  else    return fraction << -shift;}/* Rounding */STATIC_INLINE_SIM_FPU (int)do_normal_overflow (sim_fpu *f,		    int is_double,		    sim_fpu_round round){  switch (round)    {    case sim_fpu_round_default:      return 0;    case sim_fpu_round_near:      f->class = sim_fpu_class_infinity;      break;    case sim_fpu_round_up:      if (!f->sign)	f->class = sim_fpu_class_infinity;      break;    case sim_fpu_round_down:      if (f->sign)	f->class = sim_fpu_class_infinity;      break;    case sim_fpu_round_zero:      break;    }  f->normal_exp = NORMAL_EXPMAX;  f->fraction = LSMASK64 (NR_FRAC_GUARD, NR_GUARDS);  return (sim_fpu_status_overflow | sim_fpu_status_inexact);}STATIC_INLINE_SIM_FPU (int)do_normal_underflow (sim_fpu *f,		     int is_double,		     sim_fpu_round round){  switch (round)    {    case sim_fpu_round_default:      return 0;    case sim_fpu_round_near:      f->class = sim_fpu_class_zero;      break;    case sim_fpu_round_up:      if (f->sign)	f->class = sim_fpu_class_zero;      break;    case sim_fpu_round_down:      if (!f->sign)	f->class = sim_fpu_class_zero;      break;    case sim_fpu_round_zero:      f->class = sim_fpu_class_zero;      break;    }  f->normal_exp = NORMAL_EXPMIN - NR_FRACBITS;  f->fraction = IMPLICIT_1;  return (sim_fpu_status_inexact | sim_fpu_status_underflow);}/* Round a number using NR_GUARDS.   Will return the rounded number or F->FRACTION == 0 when underflow */STATIC_INLINE_SIM_FPU (int)do_normal_round (sim_fpu *f,		 int nr_guards,		 sim_fpu_round round){  unsigned64 guardmask = LSMASK64 (nr_guards - 1, 0);  unsigned64 guardmsb = LSBIT64 (nr_guards - 1);  unsigned64 fraclsb = guardmsb << 1;  if ((f->fraction & guardmask))    {      int status = sim_fpu_status_inexact;      switch (round)	{	case sim_fpu_round_default:	  return 0;	case sim_fpu_round_near:	  if ((f->fraction & guardmsb))	    {	      if ((f->fraction & fraclsb))		{		  status |= sim_fpu_status_rounded;		}	      else if ((f->fraction & (guardmask >> 1)))		{		  status |= sim_fpu_status_rounded;		}	    }	  break;	case sim_fpu_round_up:	  if (!f->sign)	    status |= sim_fpu_status_rounded;	  break;	case sim_fpu_round_down:	  if (f->sign)	    status |= sim_fpu_status_rounded;	  break;	case sim_fpu_round_zero:	  break;	}      f->fraction &= ~guardmask;      /* round if needed, handle resulting overflow */      if ((status & sim_fpu_status_rounded))	{	  f->fraction += fraclsb;	  if ((f->fraction & IMPLICIT_2))	    {	      f->fraction >>= 1;	      f->normal_exp += 1;	    }	}      return status;    }  else    return 0;}STATIC_INLINE_SIM_FPU (int)do_round (sim_fpu *f,	  int is_double,	  sim_fpu_round round,	  sim_fpu_denorm denorm){  switch (f->class)    {    case sim_fpu_class_qnan:    case sim_fpu_class_zero:    case sim_fpu_class_infinity:      return 0;      break;    case sim_fpu_class_snan:      /* Quieten a SignalingNaN */       f->class = sim_fpu_class_qnan;      return sim_fpu_status_invalid_snan;      break;    case sim_fpu_class_number:    case sim_fpu_class_denorm:      {	int status;	ASSERT (f->fraction < IMPLICIT_2);	ASSERT (f->fraction >= IMPLICIT_1);	if (f->normal_exp < NORMAL_EXPMIN)	  {	    /* This number's exponent is too low to fit into the bits	       available in the number.  Round off any bits that will be	       discarded as a result of denormalization.  Edge case is	       the implicit bit shifted to GUARD0 and then rounded	       up. */	    int shift = NORMAL_EXPMIN - f->normal_exp;	    if (shift + NR_GUARDS <= NR_FRAC_GUARD + 1		&& !(denorm & sim_fpu_denorm_zero))	      {		status = do_normal_round (f, shift + NR_GUARDS, round);		if (f->fraction == 0) /* rounding underflowed */		  {		    status |= do_normal_underflow (f, is_double, round);		  }		else if (f->normal_exp < NORMAL_EXPMIN) /* still underflow? */		  {		    status |= sim_fpu_status_denorm;		    /* Any loss of precision when denormalizing is		       underflow. Some processors check for underflow		       before rounding, some after! */		    if (status & sim_fpu_status_inexact)		      status |= sim_fpu_status_underflow;		    /* Flag that resultant value has been denormalized */		    f->class = sim_fpu_class_denorm;		  }		else if ((denorm & sim_fpu_denorm_underflow_inexact))		  {		    if ((status & sim_fpu_status_inexact))		      status |= sim_fpu_status_underflow;		  }	      }	    else	      {		status = do_normal_underflow (f, is_double, round);	      }	  }	else if (f->normal_exp > NORMAL_EXPMAX)	  {	    /* Infinity */	    status = do_normal_overflow (f, is_double, round);	  }	else	  {	    status = do_normal_round (f, NR_GUARDS, round);	    if (f->fraction == 0)	      /* f->class = sim_fpu_class_zero; */	      status |= do_normal_underflow (f, is_double, round);	    else if (f->normal_exp > NORMAL_EXPMAX)	      /* oops! rounding caused overflow */	      status |= do_normal_overflow (f, is_double, round);	  }	ASSERT ((f->class == sim_fpu_class_number		 || f->class == sim_fpu_class_denorm)		<= (f->fraction < IMPLICIT_2 && f->fraction >= IMPLICIT_1));	return status;      }    }  return 0;}INLINE_SIM_FPU (int)sim_fpu_round_32 (sim_fpu *f,		  sim_fpu_round round,		  sim_fpu_denorm denorm){  return do_round (f, 0, round, denorm);}INLINE_SIM_FPU (int)sim_fpu_round_64 (sim_fpu *f,		  sim_fpu_round round,		  sim_fpu_denorm denorm){  return do_round (f, 1, round, denorm);}/* Arithmetic ops */INLINE_SIM_FPU (int)sim_fpu_add (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;	}      *f = *l;      return 0;    }  if (sim_fpu_is_infinity (r))    {      *f = *r;      return 0;    }  if (sim_fpu_is_zero (l))    {      if (sim_fpu_is_zero (r))	{	  *f = sim_fpu_zero;	  f->sign = l->sign & r->sign;	}      else	*f = *r;      return 0;    }  if (sim_fpu_is_zero (r))    {      *f = *l;      return 0;    }  {    int status = 0;    int shift = l->normal_exp - r->normal_exp;    unsigned64 lfraction;    unsigned64 rfraction;    /* use exp of larger */    if (shift >= NR_FRAC_GUARD)      {	/* left has much bigger magnitute */	*f = *l;	return sim_fpu_status_inexact;      }    if (shift <= - NR_FRAC_GUARD)      {	/* right has much bigger magnitute */	*f = *r;	return sim_fpu_status_inexact;      }    lfraction = l->fraction;    rfraction = r->fraction;    if (shift > 0)      {	f->normal_exp = l->normal_exp;	if (rfraction & LSMASK64 (shift - 1, 0))	  {	    status |= sim_fpu_status_inexact;	    rfraction |= LSBIT64 (shift); /* stick LSBit */	  }	rfraction >>= shift;      }    else if (shift < 0)      {	f->normal_exp = r->normal_exp;	if (lfraction & LSMASK64 (- shift - 1, 0))	  {	    status |= sim_fpu_status_inexact;	    lfraction |= LSBIT64 (- shift); /* stick LSBit */	  }	lfraction >>= -shift;      }    else      {	f->normal_exp = r->normal_exp;      }    /* perform the addition */    if (l->sign)      lfraction = - lfraction;    if (r->sign)      rfraction = - rfraction;    f->fraction = lfraction + rfraction;    /* zero? */    if (f->fraction == 0)      {	*f = sim_fpu_zero;	return 0;      }    /* sign? */    f->class = sim_fpu_class_number;    if ((signed64) f->fraction >= 0)      f->sign = 0;    else      {	f->sign = 1;	f->fraction = - f->fraction;      }    /* normalize it */    if ((f->fraction & IMPLICIT_2))      {	f->fraction = (f->fraction >> 1) | (f->fraction & 1);	f->normal_exp ++;      }    else if (f->fraction < IMPLICIT_1)      {	do	  {	    f->fraction <<= 1;	    f->normal_exp --;	  }	while (f->fraction < IMPLICIT_1);      }    ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2);    return status;  }}INLINE_SIM_FPU (int)sim_fpu_sub (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;	}      *f = *l;      return 0;    }  if (sim_fpu_is_infinity (r))    {      *f = *r;      f->sign = !r->sign;      return 0;    }  if (sim_fpu_is_zero (l))    {      if (sim_fpu_is_zero (r))	{	  *f = sim_fpu_zero;	  f->sign = l->sign & !r->sign;	}      else	{	  *f = *r;	  f->sign = !r->sign;	}      return 0;    }  if (sim_fpu_is_zero (r))    {      *f = *l;      return 0;    }  {    int status = 0;    int shift = l->normal_exp - r->normal_exp;    unsigned64 lfraction;    unsigned64 rfraction;    /* use exp of larger */    if (shift >= NR_FRAC_GUARD)      {	/* left has much bigger magnitute */	*f = *l;	return sim_fpu_status_inexact;      }    if (shift <= - NR_FRAC_GUARD)      {	/* right has much bigger magnitute */	*f = *r;	f->sign = !r->sign;	return sim_fpu_status_inexact;      }    lfraction = l->fraction;    rfraction = r->fraction;    if (shift > 0)      {	f->normal_exp = l->normal_exp;	if (rfraction & LSMASK64 (shift - 1, 0))	  {	    status |= sim_fpu_status_inexact;	    rfraction |= LSBIT64 (shift); /* stick LSBit */	  }	rfraction >>= shift;      }    else if (shift < 0)      {	f->normal_exp = r->normal_exp;	if (lfraction & LSMASK64 (- shift - 1, 0))	  {	    status |= sim_fpu_status_inexact;	    lfraction |= LSBIT64 (- shift); /* stick LSBit */	  }	lfraction >>= -shift;      }    else      {	f->normal_exp = r->normal_exp;      }    /* perform the subtraction */    if (l->sign)      lfraction = - lfraction;    if (!r->sign)      rfraction = - rfraction;    f->fraction = lfraction + rfraction;    /* zero? */    if (f->fraction == 0)      {	*f = sim_fpu_zero;	return 0;      }    /* sign? */    f->class = sim_fpu_class_number;    if ((signed64) f->fraction >= 0)      f->sign = 0;    else      {	f->sign = 1;	f->fraction = - f->fraction;      }    /* normalize it */    if ((f->fraction & IMPLICIT_2))      {	f->fraction = (f->fraction >> 1) | (f->fraction & 1);	f->normal_exp ++;      }    else if (f->fraction < IMPLICIT_1)      {	do	  {	    f->fraction <<= 1;	    f->normal_exp --;	  }	while (f->fraction < IMPLICIT_1);      }    ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2);    return status;

⌨️ 快捷键说明

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