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]

More support for non-standard IEEE float variants



I'm trying to use a 32-bit float format that is based on the IEEE one, but
which doesn't support NaNs or denormals.  The NaN exponent can be used for
normal numbers instead.

The problems I found were:

1. fp-bit.c:pack_d() assumes that EXPBIAS is also the largest unbiased
   exponent (true for real IEEE, but not in the above)

2. fp-bit.c:pack_d() still creates denormals if NO_DENORMALS is defined
   (probably harmless on most machines, but still)

3. fp-bit.c:unpack_d() interprets EXPMAX as a NaN exponent when
   NO_NANS is defined.

4. support for NaNs in real.c can't be turned off on a per-format basis

5. there's no float.h for this type of machine.

I've tried to fix these with the patch below.  It does what I'd expect
on the target machine, and bootstraps OK on i686-pc-cygwin.  I'd
appreciate any comments on whether this is the right way to go.

For:

1. Patch adds a new #define, NORMAL_EXP_MAX, to mirror NORMAL_EXP_MIN.
   It's defined to be (EXPMAX)-(EXPBIAS) if NaNs aren't supported, and 
   (EXPMAX)-(EXPBIAS)-1 if they are.

4. Patch adds a new target macro NO_NANS_FOR_MODE(MODE), which is true if
   the given mode can't support NaNs & inifnities, but can use the
   largest exponent for normal values instead.  I've only tried to
   make the SFmode routines use this macro so far.

Richard

2001-02-22   Richard Sandiford   <rsandifo@redhat.com>

	* config/fp-bit.h (NORMAL_EXPMAX): New macro.
	* config/fp-bit.c: (pack_d): Disable denormal handling when
	NO_DENORMALS is defined.  Use NORMAL_EXPMAX instead of EXPBIAS to
	check for overflow.
	(unpack_d): Disable NaN handling when NO_NANS is defined.
	* real.c (NO_NANS_FOR_MODE): Document, and set default to 0.
	(e24toe): Make NaN handling dependent on NO_NANS_FOR_MODE(SFmode).
	(eto24e): Likewise.  Issue a warning if infinities aren't allowed
	and the number is too large.
	* config/float-ieee-nonans.h: New file.

Index: ./gcc/config/fp-bit.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/fp-bit.h,v
retrieving revision 1.4
diff -c -p -d -r1.4 fp-bit.h
*** ./gcc/config/fp-bit.h	2001/02/02 11:02:05	1.4
--- ./gcc/config/fp-bit.h	2001/02/22 17:02:17
***************
*** 1,5 ****
  /* Header file for fp-bit.c.  */
! /* Copyright (C) 2000
     Free Software Foundation, Inc.
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Header file for fp-bit.c.  */
! /* Copyright (C) 2000, 2001
     Free Software Foundation, Inc.
  
  This file is part of GNU CC.
*************** typedef unsigned int UDItype __attribute
*** 239,244 ****
--- 239,249 ----
  
  
  #define NORMAL_EXPMIN (-(EXPBIAS)+1)
+ #ifdef NO_NANS
+ #define NORMAL_EXPMAX ((EXPMAX)-(EXPBIAS))
+ #else
+ #define NORMAL_EXPMAX ((EXPMAX)-(EXPBIAS)-1)
+ #endif
  #define IMPLICIT_1 (1LL<<(FRACBITS+NGARDS))
  #define IMPLICIT_2 (1LL<<(FRACBITS+1+NGARDS))
  
Index: ./gcc/config/fp-bit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/fp-bit.c,v
retrieving revision 1.25
diff -c -p -d -r1.25 fp-bit.c
*** ./gcc/config/fp-bit.c	2001/02/02 11:02:05	1.25
--- ./gcc/config/fp-bit.c	2001/02/22 17:02:17
*************** pack_d ( fp_number_type *  src)
*** 209,214 ****
--- 209,221 ----
      {
        if (src->normal_exp < NORMAL_EXPMIN)
  	{
+ #ifdef NO_DENORMALS
+ 	  /* Go straight to a zero representation if denormals are not
+  	     supported.  The denormal handling would be harmless but
+  	     isn't unnecessary.  */
+ 	  exp = 0;
+ 	  fraction = 0;
+ #else /* NO_DENORMALS */
  	  /* This number's exponent is too low to fit into the bits
  	     available in the number, so we'll store 0 in the exponent and
  	     shift the fraction to the right to make up for it.  */
*************** pack_d ( fp_number_type *  src)
*** 244,252 ****
  	      exp += 1;
  	    }
  	  fraction >>= NGARDS;
  	}
!       else if (src->normal_exp > EXPBIAS)
  	{
  	  exp = EXPMAX;
  	  fraction = 0;
  	}
--- 251,264 ----
  	      exp += 1;
  	    }
  	  fraction >>= NGARDS;
+ #endif /* NO_DENORMALS */
  	}
!       else if (src->normal_exp > NORMAL_EXPMAX)
  	{
+ 	  /* Approximate to infinity any number with an exponent larger than
+ 	     NORMAL_EXPMAX.  This is not selected out by NO_NANS because
+ 	     there's no sensible alternative if infinities are not
+ 	     supported.  */
  	  exp = EXPMAX;
  	  fraction = 0;
  	}
*************** unpack_d (FLO_union_type * src, fp_numbe
*** 361,366 ****
--- 373,379 ----
  	  dst->fraction.ll = fraction;
  	}
      }
+ #ifndef NO_NANS
    else if (exp == EXPMAX)
      {
        /* Huge exponent*/
*************** unpack_d (FLO_union_type * src, fp_numbe
*** 384,389 ****
--- 397,403 ----
  	  dst->fraction.ll = fraction;
  	}
      }
+ #endif /* ! NO_NANS */
    else
      {
        /* Nothing strange about this number */
Index: ./gcc/real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.46
diff -c -p -d -r1.46 real.c
*** ./gcc/real.c	2001/01/24 04:30:46	1.46
--- ./gcc/real.c	2001/02/22 17:02:19
*************** netlib.att.com: netlib/cephes.   */
*** 69,74 ****
--- 69,86 ----
     XFmode `long double' data structure used by the Intel 80x86 series
     processors.
  
+    'IEEE' behaviour can be modified by the macro NO_NANS_FOR_MODE.  Some
+    floating-point formats are based on the IEEE standard but do not
+    implement the NaN and infinity functionality.  Some allow the
+    largest exponent value to be used for normal numbers instead.
+    NO_NANS_FOR_MODE (MODE) should be true if floats with mode MODE are in
+    this category.  Not defining the macro is equivalent to returning 0 in
+    every case.
+    ??? The macro is only used for SFmode floats at the moment.   The DFmode
+    handler saturates to the largest value if INFINITY is not defined: should
+    it do the same if NO_NANS_FOR_MODE (DFmode) is true, or should it report
+    an overflow?
+ 
     `DEC' refers specifically to the Digital Equipment Corp PDP-11
     and VAX floating point data structure.  This model currently
     supports no type wider than DFmode.
*************** unknown arithmetic type
*** 182,187 ****
--- 194,203 ----
  #define INFINITY
  #endif
  #endif
+ 
+ #ifndef NO_NANS_FOR_MODE
+ #define NO_NANS_FOR_MODE(MODE) 0
+ #endif
  
  /* Find a host integer type that is at least 16 bits wide,
     and another type at least twice whatever that size is.  */
*************** e24toe (pe, y)
*** 3458,3464 ****
    yy[M] = (r & 0x7f) | 0200;
    r &= ~0x807f;			/* strip sign and 7 significand bits */
  #ifdef INFINITY
!   if (r == 0x7f80)
      {
  #ifdef NANS
        if (REAL_WORDS_BIG_ENDIAN)
--- 3474,3480 ----
    yy[M] = (r & 0x7f) | 0200;
    r &= ~0x807f;			/* strip sign and 7 significand bits */
  #ifdef INFINITY
!   if (! NO_NANS_FOR_MODE (SFmode) && r == 0x7f80)
      {
  #ifdef NANS
        if (REAL_WORDS_BIG_ENDIAN)
*************** toe24 (x, y)
*** 4054,4060 ****
  #ifdef NANS
    if (eiisnan (x))
      {
!       make_nan (y, eiisneg (x), SFmode);
        return;
      }
  #endif
--- 4070,4079 ----
  #ifdef NANS
    if (eiisnan (x))
      {
!       if (NO_NANS_FOR_MODE (SFmode))
! 	warning ("32-bit floats cannot hold NaNs on this target");
!       else
! 	make_nan (y, eiisneg (x), SFmode);
        return;
      }
  #endif
*************** toe24 (x, y)
*** 4072,4078 ****
  
    i = *p++;
  /* Handle overflow cases.  */
!   if (i >= 255)
      {
  #ifdef INFINITY
        *y |= (unsigned EMUSHORT) 0x7f80;
--- 4091,4102 ----
  
    i = *p++;
  /* Handle overflow cases.  */
!   if (NO_NANS_FOR_MODE (SFmode))
!     {
!       if (i > 255)
! 	warning ("floating point overflow in expression");
!     }
!   else if (i >= 255)
      {
  #ifdef INFINITY
        *y |= (unsigned EMUSHORT) 0x7f80;
*** /dev/null	Thu Feb 22 17:04:40 2001
--- ./gcc/config/float-ieee-nonans.h	Thu Feb 22 12:30:15 2001
***************
*** 0 ****
--- 1,69 ----
+ /* float.h for an IEEE-based format that doesn't use NaNs.  FLT_MAX
+    is twice the IEEE value.  */
+ 
+ #ifndef _FLOAT_H_
+ #define _FLOAT_H_
+ 
+    /* Radix of exponent representation */
+ #undef FLT_RADIX
+ #define FLT_RADIX 2
+    /* Number of base-FLT_RADIX digits in the significand of a float */
+ #undef FLT_MANT_DIG
+ #define FLT_MANT_DIG 24
+    /* Number of decimal digits of precision in a float */
+ #undef FLT_DIG
+ #define FLT_DIG 6
+    /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */
+ #undef FLT_ROUNDS
+ #define FLT_ROUNDS 1
+    /* Difference between 1.0 and the minimum float greater than 1.0 */
+ #undef FLT_EPSILON
+ #define FLT_EPSILON 0X1P-23f
+    /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */
+ #undef FLT_MIN_EXP
+ #define FLT_MIN_EXP (-125)
+    /* Minimum normalised float */
+ #undef FLT_MIN
+ #define FLT_MIN 0X1.000002P-126f
+    /* Minimum int x such that 10**x is a normalised float */
+ #undef FLT_MIN_10_EXP
+ #define FLT_MIN_10_EXP (-37)
+    /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */
+ #undef FLT_MAX_EXP
+ #define FLT_MAX_EXP 129
+    /* Maximum float */
+ #undef FLT_MAX
+ #define FLT_MAX 0X1.FFFFFEP128f
+    /* Maximum int x such that 10**x is a representable float */
+ #undef FLT_MAX_10_EXP
+ #define FLT_MAX_10_EXP 38
+ 
+    /* Number of base-FLT_RADIX digits in the significand of a double */
+ #undef DBL_MANT_DIG
+ #define DBL_MANT_DIG 53
+    /* Number of decimal digits of precision in a double */
+ #undef DBL_DIG
+ #define DBL_DIG 15
+    /* Difference between 1.0 and the minimum double greater than 1.0 */
+ #undef DBL_EPSILON
+ #define DBL_EPSILON 2.2204460492503131e-16
+    /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */
+ #undef DBL_MIN_EXP
+ #define DBL_MIN_EXP (-1021)
+    /* Minimum normalised double */
+ #undef DBL_MIN
+ #define DBL_MIN 2.2250738585072014e-308
+    /* Minimum int x such that 10**x is a normalised double */
+ #undef DBL_MIN_10_EXP
+ #define DBL_MIN_10_EXP (-307)
+    /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */
+ #undef DBL_MAX_EXP
+ #define DBL_MAX_EXP 1024
+    /* Maximum double */
+ #undef DBL_MAX
+ #define DBL_MAX 1.7976931348623157e+308
+    /* Maximum int x such that 10**x is a representable double */
+ #undef DBL_MAX_10_EXP
+ #define DBL_MAX_10_EXP 308
+ 
+ #endif /*  _FLOAT_H___ */


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