This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Hexadecimal float egcs patch




Apology for duplication.
Here is the hexadecimal floating constants patch, against egcs-19981109.

        * real.c (ereal_atof): Add argument BASE, fix all callers.
            Interpret hexadecimal floating constants when base is 16.
         real.h (REAL_VALUE_HTOF): New macro for hex float conversion.
         c-lex.c (yylex): Use it, and check syntax of hex floats.
         fold-const.c (real_hex_to_f):  New function reads hex float
            if no REAL_ARITHMETIC.


*** real.c	1998/10/14 00:07:47	1.1
--- real.c	1998/11/16 20:31:48
***************
*** 409,420 ****
  static void e113toasc	PROTO((unsigned EMUSHORT *, char *, int));
  #endif /* 0 */
  static void etoasc	PROTO((unsigned EMUSHORT *, char *, int));
! static void asctoe24	PROTO((char *, unsigned EMUSHORT *));
! static void asctoe53	PROTO((char *, unsigned EMUSHORT *));
! static void asctoe64	PROTO((char *, unsigned EMUSHORT *));
! static void asctoe113	PROTO((char *, unsigned EMUSHORT *));
! static void asctoe	PROTO((char *, unsigned EMUSHORT *));
! static void asctoeg	PROTO((char *, unsigned EMUSHORT *, int));
  static void efloor	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
  #if 0
  static void efrexp	PROTO((unsigned EMUSHORT *, int *,
--- 409,420 ----
  static void e113toasc	PROTO((unsigned EMUSHORT *, char *, int));
  #endif /* 0 */
  static void etoasc	PROTO((unsigned EMUSHORT *, char *, int));
! static void asctoe24	PROTO((char *, unsigned EMUSHORT *, int));
! static void asctoe53	PROTO((char *, unsigned EMUSHORT *, int));
! static void asctoe64	PROTO((char *, unsigned EMUSHORT *, int));
! static void asctoe113	PROTO((char *, unsigned EMUSHORT *, int));
! static void asctoe	PROTO((char *, unsigned EMUSHORT *, int));
! static void asctoeg	PROTO((char *, unsigned EMUSHORT *, int, int));
  static void efloor	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
  #if 0
  static void efrexp	PROTO((unsigned EMUSHORT *, int *,
***************
*** 685,693 ****
     promotes the rounded value to REAL_VALUE_TYPE.  */
  
  REAL_VALUE_TYPE 
! ereal_atof (s, t)
       char *s;
       enum machine_mode t;
  {
    unsigned EMUSHORT tem[NE], e[NE];
    REAL_VALUE_TYPE r;
--- 685,694 ----
     promotes the rounded value to REAL_VALUE_TYPE.  */
  
  REAL_VALUE_TYPE 
! ereal_atof (s, t, base)
       char *s;
       enum machine_mode t;
+      int base;
  {
    unsigned EMUSHORT tem[NE], e[NE];
    REAL_VALUE_TYPE r;
***************
*** 697,703 ****
  #ifdef C4X
      case QFmode:
      case HFmode:
!       asctoe53 (s, tem);
        e53toe (tem, e);
        break;
  #else
--- 698,704 ----
  #ifdef C4X
      case QFmode:
      case HFmode:
!       asctoe53 (s, tem, base);
        e53toe (tem, e);
        break;
  #else
***************
*** 705,731 ****
  #endif
  
      case SFmode:
!       asctoe24 (s, tem);
        e24toe (tem, e);
        break;
  
      case DFmode:
!       asctoe53 (s, tem);
        e53toe (tem, e);
        break;
  
      case XFmode:
!       asctoe64 (s, tem);
        e64toe (tem, e);
        break;
  
      case TFmode:
!       asctoe113 (s, tem);
        e113toe (tem, e);
        break;
  
      default:
!       asctoe (s, e);
      }
    PUT_REAL (e, &r);
    return (r);
--- 706,732 ----
  #endif
  
      case SFmode:
!       asctoe24 (s, tem, base);
        e24toe (tem, e);
        break;
  
      case DFmode:
!       asctoe53 (s, tem, base);
        e53toe (tem, e);
        break;
  
      case XFmode:
!       asctoe64 (s, tem, base);
        e64toe (tem, e);
        break;
  
      case TFmode:
!       asctoe113 (s, tem, base);
        e113toe (tem, e);
        break;
  
      default:
!       asctoe (s, e, base);
      }
    PUT_REAL (e, &r);
    return (r);
***************
*** 1318,1328 ****
   
   		Routines for external format e-type numbers
   
!  	asctoe (string, e)	ASCII string to extended double e type
!  	asctoe64 (string, &d)	ASCII string to long double
!  	asctoe53 (string, &d)	ASCII string to double
!  	asctoe24 (string, &f)	ASCII string to single
!  	asctoeg (string, e, prec) ASCII string to specified precision
   	e24toe (&f, e)		IEEE single precision to e type
   	e53toe (&d, e)		IEEE double precision to e type
   	e64toe (&d, e)		IEEE long double precision to e type
--- 1319,1329 ----
   
   		Routines for external format e-type numbers
   
!  	asctoe (string, e, base)        ASCII string to extended double e type
!  	asctoe64 (string, &d, base)     ASCII string to long double
!  	asctoe53 (string, &d, base)     ASCII string to double
!  	asctoe24 (string, &f, base)     ASCII string to single
!  	asctoeg (string, e, prec, base) ASCII string to specified precision
   	e24toe (&f, e)		IEEE single precision to e type
   	e53toe (&d, e)		IEEE double precision to e type
   	e64toe (&d, e)		IEEE long double precision to e type
***************
*** 5000,5027 ****
  /* Convert ASCII string S to single precision float value Y.  */
  
  static void 
! asctoe24 (s, y)
       char *s;
       unsigned EMUSHORT *y;
  {
!   asctoeg (s, y, 24);
  }
  
  
  /* Convert ASCII string S to double precision value Y.  */
  
  static void 
! asctoe53 (s, y)
       char *s;
       unsigned EMUSHORT *y;
  {
  #if defined(DEC) || defined(IBM)
!   asctoeg (s, y, 56);
  #else
  #if defined(C4X)
!   asctoeg (s, y, 32);
  #else
!   asctoeg (s, y, 53);
  #endif
  #endif
  }
--- 5001,5030 ----
  /* Convert ASCII string S to single precision float value Y.  */
  
  static void 
! asctoe24 (s, y, base)
       char *s;
       unsigned EMUSHORT *y;
+      int base;
  {
!   asctoeg (s, y, 24, base);
  }
  
  
  /* Convert ASCII string S to double precision value Y.  */
  
  static void 
! asctoe53 (s, y, base)
       char *s;
       unsigned EMUSHORT *y;
+      int base;
  {
  #if defined(DEC) || defined(IBM)
!   asctoeg (s, y, 56, base);
  #else
  #if defined(C4X)
!   asctoeg (s, y, 32, base);
  #else
!   asctoeg (s, y, 53, base);
  #endif
  #endif
  }
***************
*** 5030,5070 ****
  /* Convert ASCII string S to double extended value Y.  */
  
  static void 
! asctoe64 (s, y)
       char *s;
       unsigned EMUSHORT *y;
  {
!   asctoeg (s, y, 64);
  }
  
  /* Convert ASCII string S to 128-bit long double Y.  */
  
  static void 
! asctoe113 (s, y)
       char *s;
       unsigned EMUSHORT *y;
  {
!   asctoeg (s, y, 113);
  }
  
  /* Convert ASCII string S to e type Y.  */
  
  static void 
! asctoe (s, y)
       char *s;
       unsigned EMUSHORT *y;
  {
!   asctoeg (s, y, NBITS);
  }
  
  /* Convert ASCII string SS to e type Y, with a specified rounding precision
!    of OPREC bits.  */
  
  static void 
! asctoeg (ss, y, oprec)
       char *ss;
       unsigned EMUSHORT *y;
       int oprec;
  {
    unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
    int esign, decflg, sgnflg, nexp, exp, prec, lost;
--- 5033,5077 ----
  /* Convert ASCII string S to double extended value Y.  */
  
  static void 
! asctoe64 (s, y, base)
       char *s;
       unsigned EMUSHORT *y;
+      int base;
  {
!   asctoeg (s, y, 64, base);
  }
  
  /* Convert ASCII string S to 128-bit long double Y.  */
  
  static void 
! asctoe113 (s, y, base)
       char *s;
       unsigned EMUSHORT *y;
+      int base;
  {
!   asctoeg (s, y, 113, base);
  }
  
  /* Convert ASCII string S to e type Y.  */
  
  static void 
! asctoe (s, y, base)
       char *s;
       unsigned EMUSHORT *y;
+      int base;
  {
!   asctoeg (s, y, NBITS, base);
  }
  
  /* Convert ASCII string SS to e type Y, with a specified rounding precision
!    of OPREC bits.  BASE is 16 for C9X hexadecimal floating constants.  */
  
  static void 
! asctoeg (ss, y, oprec, base)
       char *ss;
       unsigned EMUSHORT *y;
       int oprec;
+      int base;
  {
    unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
    int esign, decflg, sgnflg, nexp, exp, prec, lost;
***************
*** 5083,5088 ****
--- 5090,5103 ----
      ;
    s = lstr;
  
+   if (base == 16)
+     {
+       if (*s++ != '0')
+ 	abort ();
+       if (*s != 'x' && *s != 'X')
+ 	abort ();
+       ++s;
+     }
    rndsav = rndprc;
    rndprc = NBITS;		/* Set to full precision */
    lost = 0;
***************
*** 5096,5102 ****
    trail = 0;
  
   nxtcom:
!   k = *s - '0';
    if ((k >= 0) && (k <= 9))
      {
        /* Ignore leading zeros */
--- 5111,5132 ----
    trail = 0;
  
   nxtcom:
!   k = *s & 0x7f;
!   if (base == 10)
!     {
!       k = k - '0';
!     }
!   else if (base == 16)
!     {
!       if (k >= 'a')
! 	k = k - 'a' + 10;
!       else if (k >= 'A')
! 	k = k - 'A' + 10;
!       else
! 	k = k - '0';
!     }
!   else
!     abort();
    if ((k >= 0) && (k <= 9))
      {
        /* Ignore leading zeros */
***************
*** 5106,5117 ****
        if ((trail == 0) && (decflg != 0))
  	{
  	  sp = s;
! 	  while ((*sp >= '0') && (*sp <= '9'))
  	    ++sp;
  	  /* Check for syntax error */
  	  c = *sp & 0x7f;
! 	  if ((c != 'e') && (c != 'E') && (c != '\0')
! 	      && (c != '\n') && (c != '\r') && (c != ' ')
  	      && (c != ','))
  	    goto error;
  	  --sp;
--- 5136,5150 ----
        if ((trail == 0) && (decflg != 0))
  	{
  	  sp = s;
! 	  while (((*sp >= '0') && (*sp <= '9'))
! 		 || ((base == 16)
! 		     && (((*sp >= 'a') && (*sp <= 'f'))
! 			 || ((*sp >= 'F') && (*sp <= 'F')))))
  	    ++sp;
  	  /* Check for syntax error */
  	  c = *sp & 0x7f;
! 	  if ((c != 'e') && (c != 'E') && (c != 'p') && (c != 'P')
! 	      && (c != '\0') && (c != '\n') && (c != '\r') && (c != ' ')
  	      && (c != ','))
  	    goto error;
  	  --sp;
***************
*** 5131,5141 ****
  	{
  	  if (decflg)
  	    nexp += 1;		/* count digits after decimal point */
! 	  eshup1 (yy);		/* multiply current number by 10 */
! 	  emovz (yy, xt);
! 	  eshup1 (xt);
! 	  eshup1 (xt);
! 	  eaddm (xt, yy);
  	  ecleaz (xt);
  	  xt[NI - 2] = (unsigned EMUSHORT) k;
  	  eaddm (xt, yy);
--- 5164,5185 ----
  	{
  	  if (decflg)
  	    nexp += 1;		/* count digits after decimal point */
! 	  if (base == 10)
! 	    {
! 	      eshup1 (yy);		/* multiply current number by 10 */
! 	      emovz (yy, xt);
! 	      eshup1 (xt);
! 	      eshup1 (xt);
! 	      eaddm (xt, yy);
! 	    }
! 	  else if (base == 16)
! 	    {
! 	      eshup1 (yy);
! 	      eshup1 (yy);
! 	      eshup1 (yy);
! 	      eshup1 (yy);
! 	    }
! 	  /* Insert the current digit.  */
  	  ecleaz (xt);
  	  xt[NI - 2] = (unsigned EMUSHORT) k;
  	  eaddm (xt, yy);
***************
*** 5158,5163 ****
--- 5202,5209 ----
        break;
      case 'E':
      case 'e':
+     case 'P':
+     case 'p':
        goto expnt;
      case '.':			/* decimal point */
        if (decflg)
***************
*** 5224,5275 ****
      {
        exp *= 10;
        exp += *s++ - '0';
!       if (exp > -(MINDECEXP))
! 	{
! 	  if (esign < 0)
! 	    goto zero;
! 	  else
! 	    goto infinite;
! 	}
      }
    if (esign < 0)
      exp = -exp;
!   if (exp > MAXDECEXP)
      {
   infinite:
        ecleaz (yy);
        yy[E] = 0x7fff;		/* infinity */
        goto aexit;
      }
!   if (exp < MINDECEXP)
      {
   zero:
        ecleaz (yy);
        goto aexit;
      }
- 
   daldone:
!   nexp = exp - nexp;
!   /* Pad trailing zeros to minimize power of 10, per IEEE spec.  */
!   while ((nexp > 0) && (yy[2] == 0))
!     {
!       emovz (yy, xt);
!       eshup1 (xt);
!       eshup1 (xt);
!       eaddm (yy, xt);
!       eshup1 (xt);
!       if (xt[2] != 0)
! 	break;
!       nexp -= 1;
!       emovz (xt, yy);
!     }
!   if ((k = enormlz (yy)) > NBITS)
      {
!       ecleaz (yy);
!       goto aexit;
!     }
!   lexp = (EXONE - 1 + NBITS) - k;
!   emdnorm (yy, lost, 0, lexp, 64);
  
    /* Convert to external format:
  
--- 5270,5317 ----
      {
        exp *= 10;
        exp += *s++ - '0';
!       if (exp > 999999)
! 	break;
      }
    if (esign < 0)
      exp = -exp;
!   if ((exp > MAXDECEXP) && (base == 10))
      {
   infinite:
        ecleaz (yy);
        yy[E] = 0x7fff;		/* infinity */
        goto aexit;
      }
!   if ((exp < MINDECEXP) && (base == 10))
      {
   zero:
        ecleaz (yy);
        goto aexit;
      }
   daldone:
!   if (base == 10)
      {
!       nexp = exp - nexp;
!       /* Pad trailing zeros to minimize power of 10, per IEEE spec.  */
!       while ((nexp > 0) && (yy[2] == 0))
! 	{
! 	  emovz (yy, xt);
! 	  eshup1 (xt);
! 	  eshup1 (xt);
! 	  eaddm (yy, xt);
! 	  eshup1 (xt);
! 	  if (xt[2] != 0)
! 	    break;
! 	  nexp -= 1;
! 	  emovz (xt, yy);
! 	}
!       if ((k = enormlz (yy)) > NBITS)
! 	{
! 	  ecleaz (yy);
! 	  goto aexit;
! 	}
!       lexp = (EXONE - 1 + NBITS) - k;
!       emdnorm (yy, lost, 0, lexp, 64);
  
    /* Convert to external format:
  
***************
*** 5279,5331 ****
       For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
       For 0 >= n >= -999, it is -1.55e-19 at 10**-435.  */
  
!   lexp = yy[E];
!   if (nexp == 0)
!     {
!       k = 0;
!       goto expdon;
!     }
!   esign = 1;
!   if (nexp < 0)
!     {
!       nexp = -nexp;
!       esign = -1;
!       if (nexp > 4096)
  	{
- 	  /* Punt.  Can't handle this without 2 divides.  */
- 	  emovi (etens[0], tt);
  	  lexp -= tt[E];
  	  k = edivm (tt, yy);
  	  lexp += EXONE;
- 	  nexp -= 4096;
  	}
!     }
!   p = &etens[NTEN][0];
!   emov (eone, xt);
!   exp = 1;
!   do
!     {
!       if (exp & nexp)
! 	emul (p, xt, xt);
!       p -= NE;
!       exp = exp + exp;
!     }
!   while (exp <= MAXP);
! 
!   emovi (xt, tt);
!   if (esign < 0)
!     {
!       lexp -= tt[E];
!       k = edivm (tt, yy);
!       lexp += EXONE;
      }
    else
      {
!       lexp += tt[E];
!       k = emulm (tt, yy);
!       lexp -= EXONE - 1;
      }
- 
   expdon:
  
    /* Round and convert directly to the destination type */
--- 5321,5392 ----
       For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
       For 0 >= n >= -999, it is -1.55e-19 at 10**-435.  */
  
!       lexp = yy[E];
!       if (nexp == 0)
! 	{
! 	  k = 0;
! 	  goto expdon;
! 	}
!       esign = 1;
!       if (nexp < 0)
! 	{
! 	  nexp = -nexp;
! 	  esign = -1;
! 	  if (nexp > 4096)
! 	    {
! 	      /* Punt.  Can't handle this without 2 divides.  */
! 	      emovi (etens[0], tt);
! 	      lexp -= tt[E];
! 	      k = edivm (tt, yy);
! 	      lexp += EXONE;
! 	      nexp -= 4096;
! 	    }
! 	}
!       p = &etens[NTEN][0];
!       emov (eone, xt);
!       exp = 1;
!       do
! 	{
! 	  if (exp & nexp)
! 	    emul (p, xt, xt);
! 	  p -= NE;
! 	  exp = exp + exp;
! 	}
!       while (exp <= MAXP);
! 
!       emovi (xt, tt);
!       if (esign < 0)
  	{
  	  lexp -= tt[E];
  	  k = edivm (tt, yy);
  	  lexp += EXONE;
  	}
!       else
! 	{
! 	  lexp += tt[E];
! 	  k = emulm (tt, yy);
! 	  lexp -= EXONE - 1;
! 	}
      }
    else
      {
!       /* Base 16 hexadecimal floating constant.  */
!       if ((k = enormlz (yy)) > NBITS)
! 	{
! 	  ecleaz (yy);
! 	  goto aexit;
! 	}
!       lexp = (EXONE - 1 + NBITS) - k;
!       emdnorm (yy, lost, 0, lexp, 64);
!       /* Adjust the exponent.  NEXP is the number of hex digits,
!          EXP is a power of 2.  */
!       lexp = yy[E] + exp - 4 * nexp;
!       if (lexp > 0xffff)
! 	goto infinite;
!       if (lexp < 0)
! 	goto zero;
!       yy[E] = lexp;
      }
   expdon:
  
    /* Round and convert directly to the destination type */
*** real.h	1998/07/06 22:40:01	1.1
--- real.h	1998/11/16 20:27:06
***************
*** 132,138 ****
  				       REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
  extern REAL_VALUE_TYPE etrunci	PROTO((REAL_VALUE_TYPE));
  extern REAL_VALUE_TYPE etruncui	PROTO((REAL_VALUE_TYPE));
! extern REAL_VALUE_TYPE ereal_atof PROTO((char *, enum machine_mode));
  extern REAL_VALUE_TYPE ereal_negate PROTO((REAL_VALUE_TYPE));
  extern HOST_WIDE_INT efixi	PROTO((REAL_VALUE_TYPE));
  extern unsigned HOST_WIDE_INT efixui PROTO((REAL_VALUE_TYPE));
--- 132,138 ----
  				       REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
  extern REAL_VALUE_TYPE etrunci	PROTO((REAL_VALUE_TYPE));
  extern REAL_VALUE_TYPE etruncui	PROTO((REAL_VALUE_TYPE));
! extern REAL_VALUE_TYPE ereal_atof PROTO((char *, enum machine_mode, int base));
  extern REAL_VALUE_TYPE ereal_negate PROTO((REAL_VALUE_TYPE));
  extern HOST_WIDE_INT efixi	PROTO((REAL_VALUE_TYPE));
  extern unsigned HOST_WIDE_INT efixui PROTO((REAL_VALUE_TYPE));
***************
*** 178,184 ****
     toward zero. */
  #define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
  
! #define REAL_VALUE_ATOF ereal_atof
  #define REAL_VALUE_NEGATE ereal_negate
  
  #define REAL_VALUE_MINUS_ZERO(x) \
--- 178,188 ----
     toward zero. */
  #define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
  
! /* Convert ASCII string S to floating point in mode M.
!    Decimal input uses ATOF.  Hexadecimal uses HTOF.  */
! #define REAL_VALUE_ATOF(s,m) ereal_atof(s,m,10)
! #define REAL_VALUE_HTOF(s,m) ereal_atof(s,m,16)
! 
  #define REAL_VALUE_NEGATE ereal_negate
  
  #define REAL_VALUE_MINUS_ZERO(x) \
***************
*** 354,363 ****
  #if 1
  /* Use real.c to convert decimal numbers to binary, ... */
  REAL_VALUE_TYPE ereal_atof ();
! #define REAL_VALUE_ATOF(x, s) ereal_atof (x, s)
  #else
  /* ... or, if you like the host computer's atof, go ahead and use it: */
! #define REAL_VALUE_ATOF(x, s) atof (x)
  #if defined (MIPSEL) || defined (MIPSEB)
  /* MIPS compiler can't handle parens around the function name.
     This problem *does not* appear to be connected with any
--- 358,367 ----
  #if 1
  /* Use real.c to convert decimal numbers to binary, ... */
  REAL_VALUE_TYPE ereal_atof ();
! #define REAL_VALUE_ATOF(x, s, b) ereal_atof (x, s, b)
  #else
  /* ... or, if you like the host computer's atof, go ahead and use it: */
! #define REAL_VALUE_ATOF(x, s, b) atof (x)
  #if defined (MIPSEL) || defined (MIPSEB)
  /* MIPS compiler can't handle parens around the function name.
     This problem *does not* appear to be connected with any
***************
*** 367,372 ****
--- 371,383 ----
  extern double (atof) ();
  #endif
  #endif
+ #endif
+ 
+ /* Hexadecimal floating constant input for use with host computer's
+    fp arithmetic.  */
+ #ifndef REAL_VALUE_HTOF
+ extern REAL_VALUE_TYPE real_hex_to_f PROTO((char *, enum machine_mode));
+ #define REAL_VALUE_HTOF(s,m) real_hex_to_f(s,m)
  #endif
  
  /* Negate the floating-point value X.  */
*** c-lex.c	1998/10/29 11:54:08	1.1
--- c-lex.c	1998/11/16 20:43:26
***************
*** 1332,1339 ****
  	int parts[TOTAL_PARTS];
  	int overflow = 0;
  
! 	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
! 	  = NOT_FLOAT;
  
  	for (count = 0; count < TOTAL_PARTS; count++)
  	  parts[count] = 0;
--- 1332,1339 ----
  	int parts[TOTAL_PARTS];
  	int overflow = 0;
  
! 	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON}
! 	  floatflag = NOT_FLOAT;
  
  	for (count = 0; count < TOTAL_PARTS; count++)
  	  parts[count] = 0;
***************
*** 1369,1380 ****
  	  {
  	    if (c == '.')
  	      {
  		if (base == 16)
  		  error ("floating constant may not be in radix 16");
  		if (floatflag == TOO_MANY_POINTS)
  		  /* We have already emitted an error.  Don't need another.  */
  		  ;
! 		else if (floatflag == AFTER_POINT)
  		  {
  		    error ("malformed floating constant");
  		    floatflag = TOO_MANY_POINTS;
--- 1369,1384 ----
  	  {
  	    if (c == '.')
  	      {
+ #if 0
+ 		/* Perhaps this should still be disallowed if not C9X.  */
  		if (base == 16)
  		  error ("floating constant may not be in radix 16");
+ #endif
  		if (floatflag == TOO_MANY_POINTS)
  		  /* We have already emitted an error.  Don't need another.  */
  		  ;
! 		else if (floatflag == AFTER_POINT
! 			 || floatflag == AFTER_EXPON)
  		  {
  		    error ("malformed floating constant");
  		    floatflag = TOO_MANY_POINTS;
***************
*** 1385,1391 ****
  		else
  		  floatflag = AFTER_POINT;
  
- 		base = 10;
  		*p++ = c = GETC();
  		/* Accept '.' as the start of a floating-point number
  		   only when it is followed by a digit.
--- 1389,1394 ----
***************
*** 1424,1443 ****
  		    if (c == 'e' || c == 'E')
  		      {
  			base = 10;
! 			floatflag = AFTER_POINT;
  			break;   /* start of exponent */
  		      }
  		    error ("nondigits in number and not hexadecimal");
  		    c = 0;
  		  }
! 		else if (c >= 'a')
  		  {
  		    c = c - 'a' + 10;
  		  }
! 		else
  		  {
  		    c = c - 'A' + 10;
  		  }
  		if (c >= largest_digit)
  		  largest_digit = c;
  		numdigits++;
--- 1427,1457 ----
  		    if (c == 'e' || c == 'E')
  		      {
  			base = 10;
! 			floatflag = AFTER_EXPON;
  			break;   /* start of exponent */
  		      }
  		    error ("nondigits in number and not hexadecimal");
  		    c = 0;
  		  }
! 		else if (c >= 'a' && c <= 'f')
  		  {
  		    c = c - 'a' + 10;
  		  }
! 		else if (c >= 'A' && c <= 'F')
  		  {
  		    c = c - 'A' + 10;
  		  }
+ 		else if (base == 16)
+ 		  {
+ 		    if (c == 'p' || c == 'P')
+ 		      {
+ 			floatflag = AFTER_EXPON;
+ 			break;   /* start of exponent */
+ 		      }
+ 		    error ("non-hex digits in number");
+ 		    c = 0;
+ 		  }
+ 
  		if (c >= largest_digit)
  		  largest_digit = c;
  		numdigits++;
***************
*** 1486,1492 ****
  
  	    /* Read explicit exponent if any, and put it in tokenbuf.  */
  
! 	    if ((c == 'e') || (c == 'E'))
  	      {
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
--- 1500,1506 ----
  
  	    /* Read explicit exponent if any, and put it in tokenbuf.  */
  
! 	    if ((c == 'e') || (c == 'E') || (c == 'p') || (c == 'P'))
  	      {
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
***************
*** 1499,1504 ****
--- 1513,1519 ----
  		  }
  		if (! ISDIGIT (c))
  		  error ("floating constant exponent has no digits");
+ 		/* Exponent is decimal, even if string is a hex float.  */
  	        while (ISDIGIT (c))
  		  {
  		    if (p >= token_buffer + maxtoken - 3)
***************
*** 1507,1512 ****
--- 1522,1529 ----
  		    c = GETC();
  		  }
  	      }
+ 	    if (pedantic && base == 16 && floatflag != AFTER_EXPON)
+ 	      pedwarn ("hexadecimal floating constant has no exponent");
  
  	    *p = 0;
  
***************
*** 1537,1542 ****
--- 1554,1564 ----
  		      case 'f': case 'F':
  			if (fflag)
  			  error ("more than one `f' in numeric constant");
+ 			/* F is also a hex digit, so it cannot indicate
+ 			   the mode unless it follows the (decimal) exponent
+ 			   field. */
+ 			if (base == 16 && floatflag != AFTER_EXPON)
+ 			  break;
  			fflag = 1;
  			break;
  
***************
*** 1579,1585 ****
  
  		    type = float_type_node;
  		    errno = 0;
! 		    value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
  		    conversion_errno = errno;
  		    /* A diagnostic is required here by some ANSI C testsuites.
  		       This is not pedwarn, become some people don't want
--- 1601,1610 ----
  
  		    type = float_type_node;
  		    errno = 0;
! 		    if (base == 16)
! 		      value = REAL_VALUE_HTOF (copy, TYPE_MODE (type));
! 		    else
! 		      value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
  		    conversion_errno = errno;
  		    /* A diagnostic is required here by some ANSI C testsuites.
  		       This is not pedwarn, become some people don't want
***************
*** 1591,1597 ****
  		  {
  		    type = long_double_type_node;
  		    errno = 0;
! 		    value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
  		    conversion_errno = errno;
  		    if (REAL_VALUE_ISINF (value) && pedantic)
  		      warning ("floating point number exceeds range of `long double'");
--- 1616,1625 ----
  		  {
  		    type = long_double_type_node;
  		    errno = 0;
! 		    if (base == 16)
! 		      value = REAL_VALUE_HTOF (copy, TYPE_MODE (type));
! 		    else
! 		      value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
  		    conversion_errno = errno;
  		    if (REAL_VALUE_ISINF (value) && pedantic)
  		      warning ("floating point number exceeds range of `long double'");
***************
*** 1599,1605 ****
  		else
  		  {
  		    errno = 0;
! 		    value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
  		    conversion_errno = errno;
  		    if (REAL_VALUE_ISINF (value) && pedantic)
  		      warning ("floating point number exceeds range of `double'");
--- 1627,1636 ----
  		else
  		  {
  		    errno = 0;
! 		    if (base == 16)
! 		      value = REAL_VALUE_HTOF (copy, TYPE_MODE (type));
! 		    else
! 		      value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
  		    conversion_errno = errno;
  		    if (REAL_VALUE_ISINF (value) && pedantic)
  		      warning ("floating point number exceeds range of `double'");
*** fold-const.c	1998/10/13 15:25:13	1.1
--- fold-const.c	1998/11/16 20:47:05
***************
*** 964,969 ****
--- 964,1189 ----
    *r = y.d;
    return 1;
  }
+ 
+ 
+ /* Convert C9X hexadecimal floating point string constant S.  Return
+    real value type in mode MODE.  This function uses the host computer's
+    fp arithmetic when there is no REAL_ARITHMETIC.  */
+ 
+ REAL_VALUE_TYPE
+ real_hex_to_f (s, mode)
+    char *s;
+    enum machine_mode mode;
+ {
+    REAL_VALUE_TYPE ip;
+    char *p = s;
+    unsigned HOST_WIDE_INT low, high;
+    int frexpon, expon, shcount, nrmcount, k;
+    int sign, expsign, decpt, isfloat, isldouble, gotp, lost;
+    char c;
+ 
+    isldouble = 0;
+    isfloat = 0;
+    frexpon = 0;
+    expon = 0;
+    expsign = 1;
+    ip = 0.0;
+ 
+    while (*p == ' ' || *p == '\t')
+      ++p;
+ 
+    /* Sign, if any, comes first.  */
+    sign = 1;
+    if (*p == '-')
+      {
+        sign = -1;
+        ++p;
+      }
+ 
+    /* The string is supposed to start with 0x or 0X .  */
+    if (*p == '0')
+      {
+        ++p;
+        if (*p == 'x' || *p == 'X')
+ 	 ++p;
+        else
+ 	 abort ();
+      }
+    else
+      abort ();
+ 
+    while (*p == '0')
+      ++p;
+ 
+    high = 0;
+    low = 0;
+    lost = 0; /* Nonzero low order bits shifted out and discarded.  */
+    frexpon = 0;  /* Bits after the decimal point.  */
+    expon = 0;  /* Value of exponent.  */
+    decpt = 0;  /* How many decimal points.  */
+    gotp = 0;  /* How many P's.  */
+    shcount = 0;
+    while ((c = *p) != '\0')
+      {
+        if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
+ 	   || (c >= 'a' && c <= 'f'))
+ 	 {
+ 	   k = c & 0x7f;
+ 	   if (k >= 'a')
+ 	     k = k - 'a' + 10;
+ 	   else if (k >= 'A')
+ 	     k = k - 'A' + 10;
+ 	   else
+ 	     k = k - '0';
+ 
+ 	   if ((high & 0xf0000000) == 0)
+ 	     {
+ 	       high = (high << 4) + ((low >> 28) & 15);
+ 	       low = (low << 4) + k;
+ 	       shcount += 4;
+ 	       if (decpt)
+ 		 frexpon += 4;
+ 	     }
+ 	   else
+ 	     {
+ 	       /* Record nonzero lost bits.  */
+ 	       lost |= k;
+ 	       if (!decpt)
+ 		 frexpon -= 4;
+ 	     }
+ 	   ++p;
+ 	 }
+        else if ( c == '.')
+ 	 {
+ 	   ++decpt;
+ 	   ++p;
+ 	 }
+        else if (c == 'p' || c == 'P')
+ 	 {
+ 	   ++gotp;
+ 	   ++p;
+ 	   /* Sign of exponent.  */
+ 	   if (*p == '-')
+ 	     {
+ 	       expsign = -1;
+ 	       ++p;
+ 	     }
+ 	   /* Value of exponent.
+ 	      The exponent field is a decimal integer.  */
+ 	   while (isdigit(*p))
+ 	     {
+ 	       k = (*p++ & 0x7f) - '0';
+ 	       expon = 10 * expon + k;
+ 	     }
+ 	   expon *= expsign;
+ 	   /* F suffix is ambiguous in the significand part
+ 	      so it must appear after the decimal exponent field.  */
+ 	   if (*p == 'f' || *p == 'F')
+ 	     {
+ 	       isfloat = 1;
+ 	       ++p;
+ 	       break;
+ 	     }
+ 	 }
+        else if (c == 'l' || c == 'L')
+ 	 {
+ 	   isldouble = 1;
+ 	   ++p;
+ 	   break;
+ 	 }
+        else
+ 	 break;
+      }
+    /* Abort if last character read was not legitimate.  */
+    c = *p;
+    if ((c != '\0' && c != ' ' && c != '\n' && c != '\r') || (decpt > 1))
+      abort ();
+    /* There must be either one decimal point or one p.  */
+    if (decpt == 0 && gotp == 0)
+      abort ();
+    shcount -= 4;
+    if ((high == 0) && (low == 0))
+      {
+        return dconst0;
+      }
+ 
+    /* Normalize.  */
+    nrmcount = 0;
+    if (high == 0)
+      {
+        high = low;
+        low = 0;
+        nrmcount += 32;
+      }
+    if ((high & 0xffff0000) == 0)
+      {
+        high = (high << 16) + ((low >> 16) & 0xffff);
+        low = low << 16;
+        nrmcount += 16;
+      }
+    while ((high & 0x80000000) == 0)
+      {
+        high = (high << 1) + ((low >> 31) & 0xff);
+        low = low << 1;
+        nrmcount += 1;
+      }
+    if (isfloat)
+      {
+        /* Keep 24 bits precision, bits 0xffffff00.
+ 	  Rounding bit is 0x80.  */
+        lost = lost | low | (high & 0x7f);
+        low = 0;
+        if (high & 0x80)
+ 	 {
+ 	   if ((high & 0x100) || lost)
+ 	     {
+ 	       high += 0x80;
+ 	       high &= 0xffffff00;
+ 	     }
+ 	 }
+      }
+    else
+      {
+        /* We need real.c to do long double formats, so here default
+ 	  to double precision.  */
+ #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+        /* IEEE double.
+ 	  Keep 53 bits precision, bits 0xffffffff fffff800.
+ 	  Rounding bit is low word 0x400.  */
+        lost = lost | (low & 0x3ff);
+        if (low & 0x400)
+ 	 {
+ 	   if ((low & 0x800) || lost)
+ 	     {
+ 	       low = (low + 0x400) & 0xfffff800;
+ 	       if (low == 0)
+ 		 high += 1;
+ 	     }
+ 	 }
+ #else
+        /* Assume it's a VAX with 56-bit significand.  */
+        lost = lost | (low & 0x3ff);
+        if (low & 0x80)
+ 	 {
+ 	   if ((low & 0x100) || lost)
+ 	     {
+ 	       low = (low + 0x80) & 0xffffff00;
+ 	       if (low == 0)
+ 		 high += 1;
+ 	     }
+ 	 }
+ #endif
+      }
+    ip = (double) high;
+    ip =  REAL_VALUE_LDEXP (ip, 32) + (double) low;
+    /* Apply shifts and exponent value as power of 2.  */
+    ip = REAL_VALUE_LDEXP (ip, expon-(nrmcount + frexpon));
+ 
+    if (sign < 0)
+      ip = -ip;
+    return ip;
+ }
+ 
  #endif /* no REAL_ARITHMETIC */
  
  /* Split a tree IN into a constant and a variable part
___________________
/* Tests for hexadecimal floating constants.
   These might or might not obey the C9X rules strictly, but it seems to me
   that all of these strings are unambiguous and should be accepted.

   Steve Moshier
   November, 1998
  */

struct tstvec
{
  char *str;
  double h;
  double d;
};

#define NVECS 13
struct tstvec a[] = {
  {"0x1.0p0", 0x1.0p0, 1.0},
  {"0x1p0", 0x1p0,   1.0},
  {"0x1.", 0x1.,   1.0},
  {"-0x1.", -0x1.,   -1.0},
  {"0x.1", 0x.1,   0.0625},
  {"0x1.1", 0x1.1, 1.0625},
  {"0x10.", 0x10., 16.0},
  {"0x10.1", 0x10.1, 16.0625},
  {"0x8000000000000000.", 0x8000000000000000., 9.223372036854775808e+18},
  {"0x8000000000000000.0", 0x8000000000000000.0, 9.223372036854775808e+18},
  {"0x80000000000000000.", 0x80000000000000000., 1.475739525896764129e+20},
  {"0x1234566p0f", 0x1234566p0f, 1.9088742e7f},
  {"0x1234567p0f", 0x1234567p0f, 1.9088744e7f}, /* A critical rounding case. */
};


int
main()
{
  double hh;
  double dd;
  char *s;
  int i, errs;

  errs = 0;
  for (i = 0; i < NVECS; i++)
    {
      s = a[i].str;
      hh = a[i].h;
      dd = a[i].d;
      if (hh != dd)
	++errs;
    printf("%s : %.16e %.16e\n", s, hh, dd);
    }
  printf("%d errors\n", errs);
  exit (0);
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]