OSDN Git Service

(expand_units): Remove decl of unused variable.
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 57769b4..16d9ebc 100644 (file)
@@ -1,8 +1,7 @@
 /* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
-and support for XFmode IEEE extended real floating point arithmetic.
-Contributed by Stephen L. Moshier (moshier@world.std.com).
-
-   Copyright (C) 1993 Free Software Foundation, Inc.
+   and support for XFmode IEEE extended real floating point arithmetic.
+   Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+   Contributed by Stephen L. Moshier (moshier@world.std.com).
 
 This file is part of GNU CC.
 
@@ -57,7 +56,7 @@ _Methods and Programs for Mathematical Functions_, Prentice-Hall
 or Simon & Schuster Int'l, 1989.  A library of XFmode elementary
 transcendental functions can be obtained by ftp from
 research.att.com: netlib/cephes/ldouble.shar.Z  */
-
+\f
 /* Type of computer arithmetic.
  * Only one of DEC, IBM, MIEEE, IBMPC, or UNK should get defined.
  */
@@ -92,7 +91,19 @@ research.att.com: netlib/cephes/ldouble.shar.Z  */
 
    The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
    and may deactivate XFmode since `long double' is used to refer
-   to both modes.    */
+   to both modes.
+
+   The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,
+   contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,
+   separate the floating point unit's endian-ness from that of
+   the integer addressing.  This permits one to define a big-endian
+   FPU on a little-endian machine (e.g., ARM).  An extension to
+   BYTES_BIG_ENDIAN may be required for some machines in the future.
+   These optional macros may be defined in tm.h.  In real.h, they
+   default to WORDS_BIG_ENDIAN, etc., so there is no need to define
+   them for any normal host or target machine on which the floats
+   and the integers have the same endian-ness.   */
+
 
 /* The following converts gcc macros into the ones used by this file.  */
 
@@ -109,7 +120,7 @@ research.att.com: netlib/cephes/ldouble.shar.Z  */
 #define IBM 1
 #else /* it's also not an IBM */
 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#if WORDS_BIG_ENDIAN
+#if FLOAT_WORDS_BIG_ENDIAN
 /* Motorola IEEE, high order words come first (Sun workstation): */
 #define MIEEE 1
 #else /* not big-endian */
@@ -139,7 +150,7 @@ unknown arithmetic type
 #define IBM 1
 #else /* it's also not an IBM */
 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#ifdef HOST_WORDS_BIG_ENDIAN
+#if HOST_FLOAT_WORDS_BIG_ENDIAN
 #define MIEEE 1
 #else /* not big-endian */
 #define IBMPC 1
@@ -166,7 +177,7 @@ unknown arithmetic type
 #define INFINITY
 #endif
 #endif
-
+\f
 /* Find a host integer type that is at least 16 bits wide,
    and another type at least twice whatever that size is. */
 
@@ -252,7 +263,7 @@ unknown arithmetic type
 /* Emulator uses target format internally
    but host stores it in host endian-ness. */
 
-#if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN
+#if HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_WORDS_BIG_ENDIAN
 #define GET_REAL(r,e) e53toe ((r), (e))
 #define PUT_REAL(e,r) etoe53 ((e), (r))
 
@@ -310,7 +321,7 @@ do { EMUSHORT w[4];         \
 void warning ();
 extern int extra_warnings;
 int ecmp (), enormlz (), eshift ();
-int eisneg (), eisinf (), eisnan (), eiisinf (), eiisnan ();
+int eisneg (), eisinf (), eisnan (), eiisinf (), eiisnan (), eiisneg ();
 void eadd (), esub (), emul (), ediv ();
 void eshup1 (), eshup8 (), eshup6 (), eshdn1 (), eshdn8 (), eshdn6 ();
 void eabs (), eneg (), emov (), eclear (), einfin (), efloor ();
@@ -325,9 +336,10 @@ void mtherr (), make_nan ();
 void enan ();
 extern unsigned EMUSHORT ezero[], ehalf[], eone[], etwo[];
 extern unsigned EMUSHORT elog2[], esqrt2[];
-
-/* Pack output array with 32-bit numbers obtained from
-   array containing 16-bit numbers, swapping ends if required. */
+\f
+/* Copy 32-bit numbers obtained from array containing 16-bit numbers,
+   swapping ends if required, into output array of longs.  The
+   result is normally passed to fprintf by the ASM_OUTPUT_ macros.   */
 void 
 endian (e, x, mode)
      unsigned EMUSHORT e[];
@@ -336,7 +348,7 @@ endian (e, x, mode)
 {
   unsigned long th, t;
 
-#if WORDS_BIG_ENDIAN
+#if FLOAT_WORDS_BIG_ENDIAN
   switch (mode)
     {
 
@@ -477,7 +489,7 @@ earith (value, icode, r1, r2)
       if (ecmp (d2, ezero) == 0)
        {
 #ifdef NANS
-       enan (v);
+       enan (v, eisneg (d1) ^ eisneg (d2));
        break;
 #else
        abort ();
@@ -517,7 +529,7 @@ etrunci (x)
 {
   unsigned EMUSHORT f[NE], g[NE];
   REAL_VALUE_TYPE r;
-  long l;
+  HOST_WIDE_INT l;
 
   GET_REAL (&x, g);
 #ifdef NANS
@@ -540,7 +552,7 @@ etruncui (x)
 {
   unsigned EMUSHORT f[NE], g[NE];
   REAL_VALUE_TYPE r;
-  unsigned long l;
+  unsigned HOST_WIDE_INT l;
 
   GET_REAL (&x, g);
 #ifdef NANS
@@ -603,10 +615,6 @@ ereal_negate (x)
   REAL_VALUE_TYPE r;
 
   GET_REAL (&x, e);
-#ifdef NANS
-  if (eisnan (e))
-    return (x);
-#endif
   eneg (e);
   PUT_REAL (e, &r);
   return (r);
@@ -616,12 +624,12 @@ ereal_negate (x)
 /* Round real toward zero to HOST_WIDE_INT
  * implements REAL_VALUE_FIX (x).
  */
-long
+HOST_WIDE_INT
 efixi (x)
      REAL_VALUE_TYPE x;
 {
   unsigned EMUSHORT f[NE], g[NE];
-  long l;
+  HOST_WIDE_INT l;
 
   GET_REAL (&x, f);
 #ifdef NANS
@@ -639,12 +647,12 @@ efixi (x)
  * implements  REAL_VALUE_UNSIGNED_FIX (x).
  * Negative input returns zero.
  */
-unsigned long
+unsigned HOST_WIDE_INT
 efixui (x)
      REAL_VALUE_TYPE x;
 {
   unsigned EMUSHORT f[NE], g[NE];
-  unsigned long l;
+  unsigned HOST_WIDE_INT l;
 
   GET_REAL (&x, f);
 #ifdef NANS
@@ -664,10 +672,10 @@ efixui (x)
 void 
 ereal_from_int (d, i, j)
      REAL_VALUE_TYPE *d;
-     long i, j;
+     HOST_WIDE_INT i, j;
 {
   unsigned EMUSHORT df[NE], dg[NE];
-  long low, high;
+  HOST_WIDE_INT low, high;
   int sign;
 
   sign = 0;
@@ -682,7 +690,7 @@ ereal_from_int (d, i, j)
       else
        high += 1;
     }
-  eldexp (eone, HOST_BITS_PER_LONG, df);
+  eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
   ultoe (&high, dg);
   emul (dg, df, dg);
   ultoe (&low, df);
@@ -698,14 +706,14 @@ ereal_from_int (d, i, j)
 void 
 ereal_from_uint (d, i, j)
      REAL_VALUE_TYPE *d;
-     unsigned long i, j;
+     unsigned HOST_WIDE_INT i, j;
 {
   unsigned EMUSHORT df[NE], dg[NE];
-  unsigned long low, high;
+  unsigned HOST_WIDE_INT low, high;
 
   low = i;
   high = j;
-  eldexp (eone, HOST_BITS_PER_LONG, df);
+  eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
   ultoe (&high, dg);
   emul (dg, df, dg);
   ultoe (&low, df);
@@ -718,7 +726,7 @@ ereal_from_uint (d, i, j)
  */
 void 
 ereal_to_int (low, high, rr)
-     long *low, *high;
+     HOST_WIDE_INT *low, *high;
      REAL_VALUE_TYPE rr;
 {
   unsigned EMUSHORT d[NE], df[NE], dg[NE], dh[NE];
@@ -741,7 +749,7 @@ ereal_to_int (low, high, rr)
       eneg (d);
       s = 1;
     }
-  eldexp (eone, HOST_BITS_PER_LONG, df);
+  eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
   ediv (df, d, dg);            /* dg = d / 2^32 is the high word */
   euifrac (dg, high, dh);
   emul (df, dh, dg);           /* fractional part is the low word */
@@ -816,19 +824,14 @@ target_isnan (x)
 
 
 /* Check for a negative REAL_VALUE_TYPE number.
- * this means strictly less than zero, not -0.
+ * This just checks the sign bit, so that -0 counts as negative.
  */
 
 int
 target_negative (x)
      REAL_VALUE_TYPE x;
 {
-  unsigned EMUSHORT e[NE];
-
-  GET_REAL (&x, e);
-  if (ecmp (e, ezero) == -1)
-    return (1);
-  return (0);
+  return ereal_isneg (x);
 }
 
 /* Expansion of REAL_VALUE_TRUNCATE.
@@ -874,8 +877,11 @@ real_value_truncate (mode, arg)
       r = etrunci (arg);
       return (r);
 
+    /* If an unsupported type was requested, presume that
+       the machine files know something useful to do with
+       the unmodified value.  */
     default:
-      abort ();
+      return (arg);
     }
   PUT_REAL (t, &r);
   return (r);
@@ -883,6 +889,20 @@ real_value_truncate (mode, arg)
 
 #endif /* REAL_ARITHMETIC defined */
 
+/* Used for debugging--print the value of R in human-readable format
+   on stderr.  */
+
+void
+debug_real (r)
+     REAL_VALUE_TYPE r;
+{
+  char dstr[30];
+
+  REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
+  fprintf (stderr, "%s", dstr);
+}  
+
+\f
 /* Target values are arrays of host longs. A long is guaranteed
    to be at least 32 bits wide. */
 
@@ -970,7 +990,7 @@ ereal_isneg (x)
 }
 
 /* End of REAL_ARITHMETIC interface */
-
+\f
 /*                                                     ieee.c
  *
  *    Extended precision IEEE binary floating point arithmetic routines
@@ -1021,8 +1041,8 @@ ereal_isneg (x)
  *     ediv (a, b, c)          c = b / a
  *     efloor (a, b)           truncate to integer, toward -infinity
  *     efrexp (a, exp, s)      extract exponent and significand
- *     eifrac (e, &l, frac)    e to long integer and e type fraction
- *     euifrac (e, &l, frac)   e to unsigned long integer and e type fraction
+ *     eifrac (e, &l, frac)    e to HOST_WIDE_INT and e type fraction
+ *     euifrac (e, &l, frac)   e to unsigned HOST_WIDE_INT and e type fraction
  *     einfin (e)              set e to infinity, leaving its sign alone
  *     eldexp (a, n, b)        multiply by 2**n
  *     emov (a, b)             b = a
@@ -1038,8 +1058,8 @@ ereal_isneg (x)
  *     etoe24 (e, &f)          convert e type to IEEE single precision
  *     etoe53 (e, &d)          convert e type to IEEE double precision
  *     etoe64 (e, &d)          convert e type to IEEE long double precision
- *     ltoe (&l, e)            long (32 bit) integer to e type
- *     ultoe (&l, e)           unsigned long (32 bit) integer to e type
+ *     ltoe (&l, e)            HOST_WIDE_INT to e type
+ *     ultoe (&l, e)           unsigned HOST_WIDE_INT to e type
  *      eisneg (e)              1 if sign bit of e != 0, else 0
  *      eisinf (e)              1 if e has maximum exponent (non-IEEE)
  *                             or is infinite (IEEE)
@@ -1069,6 +1089,7 @@ ereal_isneg (x)
  *     esubm (ai, bi)          subtract significands, bi = bi - ai
  *      eiisinf (ai)            1 if infinite
  *      eiisnan (ai)            1 if a NaN
+ *     eiisneg (ai)            1 if sign bit of ai != 0, else 0
  *      einan (ai)              set ai = NaN
  *      eiinfin (ai)            set ai = infinity
  *
@@ -1322,27 +1343,19 @@ eneg (x)
      unsigned EMUSHORT x[];
 {
 
-#ifdef NANS
-  if (eisnan (x))
-    return;
-#endif
   x[NE - 1] ^= 0x8000;         /* Toggle the sign bit */
 }
 
 
 
-/* Return 1 if external format number is negative,
- * else return zero, including when it is a NaN.
+/* Return 1 if sign bit of external format number is nonzero,
+ * else return zero.
  */
 int 
 eisneg (x)
      unsigned EMUSHORT x[];
 {
 
-#ifdef NANS
-  if (eisnan (x))
-    return (0);
-#endif
   if (x[NE - 1] & 0x8000)
     return (1);
   else
@@ -1441,15 +1454,16 @@ einfin (x)
    The exponent is 7fff, the leading mantissa word is c000.  */
 
 void 
-enan (x)
+enan (x, sign)
      register unsigned EMUSHORT *x;
+     int sign;
 {
   register int i;
 
   for (i = 0; i < NE - 2; i++)
     *x++ = 0;
   *x++ = 0xc000;
-  *x = 0x7fff;
+  *x = (sign << 15) | 0x7fff;
 }
 
 
@@ -1509,6 +1523,7 @@ emovo (a, b)
 {
   register unsigned EMUSHORT *p, *q;
   unsigned EMUSHORT i;
+  int j;
 
   p = a;
   q = b + (NE - 1);            /* point to output exponent */
@@ -1524,7 +1539,7 @@ emovo (a, b)
 #ifdef NANS
       if (eiisnan (a))
        {
-         enan (b);
+         enan (b, eiisneg (a));
          return;
        }
 #endif
@@ -1535,7 +1550,7 @@ emovo (a, b)
   /* skip over guard word */
   ++p;
   /* move the significand */
-  for (i = 0; i < NE - 1; i++)
+  for (j = 0; j < NE - 1; j++)
     *q-- = *p++;
 }
 
@@ -1618,6 +1633,16 @@ eiisnan (x)
   return (0);
 }
 
+/* Return nonzero if sign of internal format number is nonzero.  */
+
+int 
+eiisneg (x)
+     unsigned EMUSHORT x[];
+{
+
+  return x[0] != 0;
+}
+
 /* Fill internal format number with infinity pattern.
    This has maximum exponent and significand all zeros.  */
 
@@ -2043,151 +2068,153 @@ emulm (a, b)
 /* Multiply significand of e-type number b
 by 16-bit quantity a, e-type result to c. */
 
-void m16m( a, b, c )
-unsigned short a;
-unsigned short b[], c[];
+void
+m16m (a, b, c)
+     unsigned short a;
+     unsigned short b[], c[];
 {
-register unsigned short *pp;
-register unsigned long carry;
-unsigned short *ps;
-unsigned short p[NI];
-unsigned long aa, m;
-int i;
-
-aa = a;
-pp = &p[NI-2];
-*pp++ = 0;
-*pp = 0;
-ps = &b[NI-1];
-
-for( i=M+1; i<NI; i++ )
+  register unsigned short *pp;
+  register unsigned long carry;
+  unsigned short *ps;
+  unsigned short p[NI];
+  unsigned long aa, m;
+  int i;
+
+  aa = a;
+  pp = &p[NI-2];
+  *pp++ = 0;
+  *pp = 0;
+  ps = &b[NI-1];
+
+  for (i=M+1; i<NI; i++)
+    {
+      if (*ps == 0)
        {
-       if( *ps == 0 )
-               {
-               --ps;
-               --pp;
-               *(pp-1) = 0;
-               }
-       else
-               {
-               m = (unsigned long) aa * *ps--;
-               carry = (m & 0xffff) + *pp;
-               *pp-- = (unsigned short )carry;
-               carry = (carry >> 16) + (m >> 16) + *pp;
-               *pp = (unsigned short )carry;
-               *(pp-1) = carry >> 16;
-               }
+         --ps;
+         --pp;
+         *(pp-1) = 0;
+       }
+      else
+       {
+         m = (unsigned long) aa * *ps--;
+         carry = (m & 0xffff) + *pp;
+         *pp-- = (unsigned short)carry;
+         carry = (carry >> 16) + (m >> 16) + *pp;
+         *pp = (unsigned short)carry;
+         *(pp-1) = carry >> 16;
        }
-for( i=M; i<NI; i++ )
-       c[i] = p[i];
+    }
+  for (i=M; i<NI; i++)
+    c[i] = p[i];
 }
 
 
 /* Divide significands. Neither the numerator nor the denominator
-is permitted to have its high guard word nonzero.  */
-
+   is permitted to have its high guard word nonzero.  */
 
-int edivm( den, num )
-unsigned short den[], num[];
+int
+edivm (den, num)
+     unsigned short den[], num[];
 {
-int i;
-register unsigned short *p;
-unsigned long tnum;
-unsigned short j, tdenm, tquot;
-unsigned short tprod[NI+1];
+  int i;
+  register unsigned short *p;
+  unsigned long tnum;
+  unsigned short j, tdenm, tquot;
+  unsigned short tprod[NI+1];
 
-p = &equot[0];
-*p++ = num[0];
-*p++ = num[1];
+  p = &equot[0];
+  *p++ = num[0];
+  *p++ = num[1];
 
-for( i=M; i<NI; i++ )
-       {
-       *p++ = 0;
-       }
-eshdn1( num );
-tdenm = den[M+1];
-for( i=M; i<NI; i++ )
-       {
-       /* Find trial quotient digit (the radix is 65536). */
-       tnum = (((unsigned long) num[M]) << 16) + num[M+1];
-
-       /* Do not execute the divide instruction if it will overflow. */
-        if( (tdenm * 0xffffL) < tnum )
-               tquot = 0xffff;
-       else
-               tquot = tnum / tdenm;
-       /* Multiply denominator by trial quotient digit. */
-       m16m( tquot, den, tprod );
-       /* The quotient digit may have been overestimated. */
-       if( ecmpm( tprod, num ) > 0 )
-               {
-               tquot -= 1;
-               esubm( den, tprod );
-               if( ecmpm( tprod, num ) > 0 )
-                       {
-                       tquot -= 1;
-                       esubm( den, tprod );
-                       }
-               }
-       esubm( tprod, num );
-       equot[i] = tquot;
-       eshup6(num);
-       }
-/* test for nonzero remainder after roundoff bit */
-p = &num[M];
-j = 0;
-for( i=M; i<NI; i++ )
+  for (i=M; i<NI; i++)
+    {
+      *p++ = 0;
+    }
+  eshdn1 (num);
+  tdenm = den[M+1];
+  for (i=M; i<NI; i++)
+    {
+      /* Find trial quotient digit (the radix is 65536). */
+      tnum = (((unsigned long) num[M]) << 16) + num[M+1];
+
+      /* Do not execute the divide instruction if it will overflow. */
+      if ((tdenm * 0xffffL) < tnum)
+       tquot = 0xffff;
+      else
+       tquot = tnum / tdenm;
+      /* Multiply denominator by trial quotient digit. */
+      m16m (tquot, den, tprod);
+      /* The quotient digit may have been overestimated. */
+      if (ecmpm (tprod, num) > 0)
        {
-       j |= *p++;
+         tquot -= 1;
+         esubm (den, tprod);
+         if (ecmpm (tprod, num) > 0)
+           {
+             tquot -= 1;
+             esubm (den, tprod);
+           }
        }
-if( j )
-       j = 1;
+      esubm (tprod, num);
+      equot[i] = tquot;
+      eshup6(num);
+    }
+  /* test for nonzero remainder after roundoff bit */
+  p = &num[M];
+  j = 0;
+  for (i=M; i<NI; i++)
+    {
+      j |= *p++;
+    }
+  if (j)
+    j = 1;
 
-for( i=0; i<NI; i++ )
-       num[i] = equot[i];
+  for (i=0; i<NI; i++)
+    num[i] = equot[i];
 
-return( (int )j );
+  return ((int)j);
 }
 
 
 
 /* Multiply significands */
-int emulm( a, b )
-unsigned short a[], b[];
+int
+emulm (a, b)
+     unsigned short a[], b[];
 {
-unsigned short *p, *q;
-unsigned short pprod[NI];
-unsigned short j;
-int i;
-
-equot[0] = b[0];
-equot[1] = b[1];
-for( i=M; i<NI; i++ )
-       equot[i] = 0;
-
-j = 0;
-p = &a[NI-1];
-q = &equot[NI-1];
-for( i=M+1; i<NI; i++ )
+  unsigned short *p, *q;
+  unsigned short pprod[NI];
+  unsigned short j;
+  int i;
+
+  equot[0] = b[0];
+  equot[1] = b[1];
+  for (i=M; i<NI; i++)
+    equot[i] = 0;
+
+  j = 0;
+  p = &a[NI-1];
+  q = &equot[NI-1];
+  for (i=M+1; i<NI; i++)
+    {
+      if (*p == 0)
        {
-       if( *p == 0 )
-               {
-               --p;
-               }
-       else
-               {
-               m16m( *p--, b, pprod );
-               eaddm(pprod, equot);
-               }
-       j |= *q;
-       eshdn6(equot);
+         --p;
        }
+      else
+       {
+         m16m (*p--, b, pprod);
+         eaddm(pprod, equot);
+       }
+      j |= *q;
+      eshdn6(equot);
+    }
 
-for( i=0; i<NI; i++ )
-       b[i] = equot[i];
+  for (i=0; i<NI; i++)
+    b[i] = equot[i];
 
-/* return flag for lost nonzero bits */
-return( (int)j );
+  /* return flag for lost nonzero bits */
+  return ((int)j);
 }
 #endif
 
@@ -2454,7 +2481,7 @@ esub (a, b, c)
       && ((eisneg (a) ^ eisneg (b)) == 0))
     {
       mtherr ("esub", INVALID);
-      enan (c);
+      enan (c, 0);
       return;
     }
 #endif
@@ -2492,7 +2519,7 @@ eadd (a, b, c)
       && ((eisneg (a) ^ eisneg (b)) != 0))
     {
       mtherr ("esub", INVALID);
-      enan (c);
+      enan (c, 0);
       return;
     }
 #endif
@@ -2635,7 +2662,7 @@ ediv (a, b, c)
       || (eisinf (a) && eisinf (b)))
     {
     mtherr ("ediv", INVALID);
-    enan (c);
+    enan (c, eisneg (a) ^ eisneg (b));
     return;
     }
 #endif
@@ -2743,7 +2770,7 @@ emul (a, b, c)
       || (eisinf (b) && (ecmp (a, ezero) == 0)))
     {
     mtherr ("emul", INVALID);
-    enan (c);
+    enan (c, eisneg (a) ^ eisneg (b));
     return;
     }
 #endif
@@ -2854,14 +2881,14 @@ e53toe (pe, y)
       if (((pe[3] & 0xf) != 0) || (pe[2] != 0)
          || (pe[1] != 0) || (pe[0] != 0))
        {
-         enan (y);
+         enan (y, yy[0] != 0);
          return;
        }
 #else
       if (((pe[0] & 0xf) != 0) || (pe[1] != 0)
          || (pe[2] != 0) || (pe[3] != 0))
        {
-         enan (y);
+         enan (y, yy[0] != 0);
          return;
        }
 #endif
@@ -2954,7 +2981,7 @@ e64toe (pe, y)
        {
          if (pe[i] != 0)
            {
-             enan (y);
+             enan (y, (*p & 0x8000) != 0);
              return;
            }
        }
@@ -2963,7 +2990,7 @@ e64toe (pe, y)
        {
          if (pe[i] != 0)
            {
-             enan (y);
+             enan (y, (*p & 0x8000) != 0);
              return;
            }
        }
@@ -3010,7 +3037,7 @@ e113toe (pe, y)
        {
          if (pe[i] != 0)
            {
-             enan (y);
+             enan (y, yy[0] != 0);
              return;
            }
        }
@@ -3019,7 +3046,7 @@ e113toe (pe, y)
        {
          if (pe[i] != 0)
            {
-             enan (y);
+             enan (y, yy[0] != 0);
              return;
            }
        }
@@ -3099,13 +3126,13 @@ e24toe (pe, y)
 #ifdef MIEEE
       if (((pe[0] & 0x7f) != 0) || (pe[1] != 0))
        {
-         enan (y);
+         enan (y, yy[0] != 0);
          return;
        }
 #else
       if (((pe[1] & 0x7f) != 0) || (pe[0] != 0))
        {
-         enan (y);
+         enan (y, yy[0] != 0);
          return;
        }
 #endif
@@ -3162,7 +3189,7 @@ etoe113 (x, e)
 #ifdef NANS
   if (eisnan (x))
     {
-      make_nan (e, TFmode);
+      make_nan (e, eisneg (x), TFmode);
       return;
     }
 #endif
@@ -3192,7 +3219,7 @@ toe113 (a, b)
 #ifdef NANS
   if (eiisnan (a))
     {
-      make_nan (b, TFmode);
+      make_nan (b, eiisneg (a), TFmode);
       return;
     }
 #endif
@@ -3244,7 +3271,7 @@ etoe64 (x, e)
 #ifdef NANS
   if (eisnan (x))
     {
-      make_nan (e, XFmode);
+      make_nan (e, eisneg (x), XFmode);
       return;
     }
 #endif
@@ -3275,7 +3302,7 @@ toe64 (a, b)
 #ifdef NANS
   if (eiisnan (a))
     {
-      make_nan (b, XFmode);
+      make_nan (b, eiisneg (a), XFmode);
       return;
     }
 #endif
@@ -3370,7 +3397,7 @@ etoe53 (x, e)
 #ifdef NANS
   if (eisnan (x))
     {
-      make_nan (e, DFmode);
+      make_nan (e, eisneg (x), DFmode);
       return;
     }
 #endif
@@ -3401,7 +3428,7 @@ toe53 (x, y)
 #ifdef NANS
   if (eiisnan (x))
     {
-      make_nan (y, DFmode);
+      make_nan (y, eiisneg (x), DFmode);
       return;
     }
 #endif
@@ -3509,7 +3536,7 @@ etoe24 (x, e)
 #ifdef NANS
   if (eisnan (x))
     {
-      make_nan (e, SFmode);
+      make_nan (e, eisneg (x), SFmode);
       return;
     }
 #endif
@@ -3539,7 +3566,7 @@ toe24 (x, y)
 #ifdef NANS
   if (eiisnan (x))
     {
-      make_nan (y, SFmode);
+      make_nan (y, eiisneg (x), SFmode);
       return;
     }
 #endif
@@ -3704,35 +3731,35 @@ eround (x, y)
 
 
 /*
-; convert long integer to e type
+; convert HOST_WIDE_INT to e type
 ;
-;      long l;
+;      HOST_WIDE_INT l;
 ;      unsigned EMUSHORT x[NE];
 ;      ltoe (&l, x);
 ; note &l is the memory address of l
 */
 void 
 ltoe (lp, y)
-     long *lp;                 /* lp is the memory address of a long integer */
-     unsigned EMUSHORT *y;             /* y is the address of a short */
+     HOST_WIDE_INT *lp;
+     unsigned EMUSHORT *y;
 {
   unsigned EMUSHORT yi[NI];
-  unsigned long ll;
+  unsigned HOST_WIDE_INT ll;
   int k;
 
   ecleaz (yi);
   if (*lp < 0)
     {
       /* make it positive */
-      ll = (unsigned long) (-(*lp));
+      ll = (unsigned HOST_WIDE_INT) (-(*lp));
       yi[0] = 0xffff;          /* put correct sign in the e type number */
     }
   else
     {
-      ll = (unsigned long) (*lp);
+      ll = (unsigned HOST_WIDE_INT) (*lp);
     }
   /* move the long integer to yi significand area */
-#if HOST_BITS_PER_LONG == 64
+#if HOST_BITS_PER_WIDE_INT == 64
   yi[M] = (unsigned EMUSHORT) (ll >> 48);
   yi[M + 1] = (unsigned EMUSHORT) (ll >> 32);
   yi[M + 2] = (unsigned EMUSHORT) (ll >> 16);
@@ -3752,27 +3779,27 @@ ltoe (lp, y)
 }
 
 /*
-; convert unsigned long integer to e type
+; convert unsigned HOST_WIDE_INT to e type
 ;
-;      unsigned long l;
+;      unsigned HOST_WIDE_INT l;
 ;      unsigned EMUSHORT x[NE];
 ;      ltox (&l, x);
 ; note &l is the memory address of l
 */
 void 
 ultoe (lp, y)
-     unsigned long *lp;                /* lp is the memory address of a long integer */
-     unsigned EMUSHORT *y;             /* y is the address of a short */
+     unsigned HOST_WIDE_INT *lp;
+     unsigned EMUSHORT *y;
 {
   unsigned EMUSHORT yi[NI];
-  unsigned long ll;
+  unsigned HOST_WIDE_INT ll;
   int k;
 
   ecleaz (yi);
   ll = *lp;
 
   /* move the long integer to ayi significand area */
-#if HOST_BITS_PER_LONG == 64
+#if HOST_BITS_PER_WIDE_INT == 64
   yi[M] = (unsigned EMUSHORT) (ll >> 48);
   yi[M + 1] = (unsigned EMUSHORT) (ll >> 32);
   yi[M + 2] = (unsigned EMUSHORT) (ll >> 16);
@@ -3792,25 +3819,22 @@ ultoe (lp, y)
 }
 
 
-/*
-;      Find long integer and fractional parts
-
-;      long i;
-;      unsigned EMUSHORT x[NE], frac[NE];
-;      xifrac (x, &i, frac);
+/* Find signed HOST_WIDE_INT integer and floating point fractional
+   parts of e-type (packed internal format) floating point input X.
+   The integer output I has the sign of the input, except that
+   positive overflow is permitted if FIXUNS_TRUNC_LIKE_FIX_TRUNC.
+   The output e-type fraction FRAC is the positive fractional
+   part of abs (X).  */
 
-  The integer output has the sign of the input.  The fraction is
-the positive fractional part of abs (x).
-*/
 void 
 eifrac (x, i, frac)
      unsigned EMUSHORT *x;
-     long *i;
+     HOST_WIDE_INT *i;
      unsigned EMUSHORT *frac;
 {
   unsigned EMUSHORT xi[NI];
   int j, k;
-  unsigned long ll;
+  unsigned HOST_WIDE_INT ll;
 
   emovi (x, xi);
   k = (int) xi[E] - (EXONE - 1);
@@ -3821,14 +3845,24 @@ eifrac (x, i, frac)
       emovo (xi, frac);
       return;
     }
-  if (k > (HOST_BITS_PER_LONG - 1))
+  if (k > (HOST_BITS_PER_WIDE_INT - 1))
     {
       /* long integer overflow: output large integer
         and correct fraction  */
       if (xi[0])
-       *i = ((unsigned long) 1) << (HOST_BITS_PER_LONG - 1);
+       *i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1);
       else
-       *i = (((unsigned long) 1) << (HOST_BITS_PER_LONG - 1)) - 1;
+       {
+#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
+         /* In this case, let it overflow and convert as if unsigned.  */
+         euifrac (x, &ll, frac);
+         *i = (HOST_WIDE_INT) ll;
+         return;
+#else
+         /* In other cases, return the largest positive integer.  */
+         *i = (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1)) - 1;
+#endif
+       }
       eshift (xi, k);
       if (extra_warnings)
        warning ("overflow on truncation to integer");
@@ -3855,7 +3889,7 @@ eifrac (x, i, frac)
       {
         /* shift not more than 16 bits */
           eshift (xi, k);
-        *i = (long) xi[M] & 0xffff;
+        *i = (HOST_WIDE_INT) xi[M] & 0xffff;
         if (xi[0])
          *i = -(*i);
       }
@@ -3871,17 +3905,17 @@ eifrac (x, i, frac)
 }
 
 
-/* Find unsigned long integer and fractional parts.
+/* Find unsigned HOST_WIDE_INT integer and floating point fractional parts.
    A negative e type input yields integer output = 0
    but correct fraction.  */
 
 void 
 euifrac (x, i, frac)
      unsigned EMUSHORT *x;
-     unsigned long *i;
+     unsigned HOST_WIDE_INT *i;
      unsigned EMUSHORT *frac;
 {
-  unsigned long ll;
+  unsigned HOST_WIDE_INT ll;
   unsigned EMUSHORT xi[NI];
   int j, k;
 
@@ -3894,7 +3928,7 @@ euifrac (x, i, frac)
       emovo (xi, frac);
       return;
     }
-  if (k > HOST_BITS_PER_LONG)
+  if (k > HOST_BITS_PER_WIDE_INT)
     {
       /* Long integer overflow: output large integer
         and correct fraction.
@@ -3925,7 +3959,7 @@ euifrac (x, i, frac)
     {
       /* shift not more than 16 bits */
       eshift (xi, k);
-      *i = (long) xi[M] & 0xffff;
+      *i = (HOST_WIDE_INT) xi[M] & 0xffff;
     }
 
   if (xi[0])  /* A negative value yields unsigned integer 0. */
@@ -4476,7 +4510,7 @@ etoasc (x, string, ndigs)
     }
   else
     {
-      *s++ = (char )digit + '0';
+      *s++ = (char)digit + '0';
       *s++ = '.';
     }
   /* Generate digits after the decimal point. */
@@ -4626,9 +4660,8 @@ asctoe (s, y)
   asctoeg (s, y, NBITS);
 }
 
-/* Space to make a copy of the input string: */
-static char lstr[82];
 
+/* ASCII to e type, with specified rounding precision = oprec. */
 void 
 asctoeg (ss, y, oprec)
      char *ss;
@@ -4640,19 +4673,16 @@ asctoeg (ss, y, oprec)
   int k, trail, c, rndsav;
   EMULONG lexp;
   unsigned EMUSHORT nsign, *p;
-  char *sp, *s;
+  char *sp, *s, *lstr;
 
   /* Copy the input string. */
+  lstr = (char *) alloca (strlen (ss) + 1);
   s = ss;
   while (*s == ' ')            /* skip leading spaces */
     ++s;
   sp = lstr;
-  for (k = 0; k < 79; k++)
-    {
-      if ((*sp++ = *s++) == '\0')
-       break;
-    }
-  *sp = '\0';
+  while ((*sp++ = *s++) != '\0')
+    ;
   s = lstr;
 
   rndsav = rndprc;
@@ -4713,7 +4743,11 @@ asctoeg (ss, y, oprec)
        }
       else
        {
+         /* Mark any lost non-zero digit.  */
          lost |= k;
+         /* Count lost digits before the decimal point.  */
+         if (decflg == 0)
+           nexp -= 1;
        }
       prec += 1;
       goto donchr;
@@ -5047,7 +5081,7 @@ efrexp (x, exp, s)
 
 
 /* unsigned EMUSHORT x[], y[];
- * long pwr2;
+ * int pwr2;
  *
  * eldexp (x, pwr2, y);
  *
@@ -5082,12 +5116,12 @@ eremain (a, b, c)
   unsigned EMUSHORT den[NI], num[NI];
 
 #ifdef NANS
-  if ( eisinf (b)
-       || (ecmp (a, ezero) == 0)
-       || eisnan (a)
-       || eisnan (b))
+  if (eisinf (b)
+      || (ecmp (a, ezero) == 0)
+      || eisnan (a)
+      || eisnan (b))
     {
-      enan (c);
+      enan (c, 0);
       return;
     }
 #endif
@@ -5552,14 +5586,14 @@ unsigned EMUSHORT SFnan[2] = {0, 0xffc0};
 
 
 void
-make_nan (nan, mode)
+make_nan (nan, sign, mode)
 unsigned EMUSHORT *nan;
+int sign;
 enum machine_mode mode;
 {
-  int i, n;
+  int n;
   unsigned EMUSHORT *p;
 
-  n = 0;
   switch (mode)
     {
 /* Possibly the `reserved operand' patterns on a VAX can be
@@ -5585,8 +5619,14 @@ enum machine_mode mode;
     default:
       abort ();
     }
-  for (i=0; i < n; i++)
+#ifdef MIEEE
+  *nan++ = (sign << 15) | *p++;
+#endif
+  while (--n != 0)
     *nan++ = *p++;
+#ifndef MIEEE
+  *nan = (sign << 15) | *p;
+#endif
 }
 
 /* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
@@ -5603,7 +5643,7 @@ ereal_from_float (f)
 
   /* Convert 32 bit integer to array of 16 bit pieces in target machine order.
    This is the inverse operation to what the function `endian' does.  */
-#if WORDS_BIG_ENDIAN
+#if FLOAT_WORDS_BIG_ENDIAN
   s[0] = (unsigned EMUSHORT) (f >> 16);
   s[1] = (unsigned EMUSHORT) f;
 #else
@@ -5622,7 +5662,7 @@ ereal_from_float (f)
    This is the inverse of the function `etardouble' invoked by
    REAL_VALUE_TO_TARGET_DOUBLE.
 
-   The DFmode is stored as an array of longs (i.e., HOST_WIDE_INTs)
+   The DFmode is stored as an array of long ints
    with 32 bits of the value per each long.  The first element
    of the input array holds the bits that would come first in the
    target computer's memory.  */
@@ -5637,7 +5677,7 @@ ereal_from_double (d)
 
   /* Convert array of 32 bit pieces to equivalent array of 16 bit pieces.
    This is the inverse of `endian'.   */
-#if WORDS_BIG_ENDIAN
+#if FLOAT_WORDS_BIG_ENDIAN
   s[0] = (unsigned EMUSHORT) (d[0] >> 16);
   s[1] = (unsigned EMUSHORT) d[0];
   s[2] = (unsigned EMUSHORT) (d[1] >> 16);
@@ -5656,7 +5696,9 @@ ereal_from_double (d)
 }
 
 
-/* Convert target computer unsigned 64-bit integer to e-type. */
+/* Convert target computer unsigned 64-bit integer to e-type.
+   The endian-ness of DImode follows the convention for integers,
+   so we use WORDS_BIG_ENDIAN here, not FLOAT_WORDS_BIG_ENDIAN.  */
 
 void
 uditoe (di, e)
@@ -5929,16 +5971,13 @@ esqrt (x, y)
   i = ecmp (x, ezero);
   if (i <= 0)
     {
-#ifdef NANS
-      if (i == -2)
+      if (i == -1)
        {
-         enan (y);
-         return;
+         mtherr ("esqrt", DOMAIN);
+         eclear (y);
        }
-#endif
-      eclear (y);
-      if (i < 0)
-       mtherr ("esqrt", DOMAIN);
+      else
+       emov (x, y);
       return;
     }