OSDN Git Service

[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 435d0b5..ed854e0 100644 (file)
@@ -1,6 +1,6 @@
 /* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
    and support for XFmode IEEE extended real floating point arithmetic.
-   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
 
 This file is part of GNU CC.
@@ -20,14 +20,10 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-#include <stdio.h>
-#include <errno.h>
 #include "config.h"
+#include "system.h"
 #include "tree.h"
-
-#ifndef errno
-extern int errno;
-#endif
+#include "toplev.h"
 
 /* To enable support of XFmode extended real floating point, define
 LONG_DOUBLE_TYPE_SIZE 96 in the tm.h file (m68k.h or i386.h).
@@ -55,7 +51,7 @@ XFmode and TFmode transcendental functions, can be obtained by ftp from
 netlib.att.com: netlib/cephes.   */
 \f
 /* Type of computer arithmetic.
-   Only one of DEC, IBM, IEEE, or UNK should get defined.
+   Only one of DEC, IBM, IEEE, C4X, or UNK should get defined.
 
    `IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically
    to big-endian IEEE floating-point data structure.  This definition
@@ -80,6 +76,11 @@ netlib.att.com: netlib/cephes.   */
    no type wider than DFmode.  The IBM conversions were contributed by
    frank@atom.ansto.gov.au (Frank Crawford).
 
+   `C4X' refers specifically to the floating point format used on
+   Texas Instruments TMS320C3x and TMS320C4x digital signal
+   processors.  This supports QFmode (32-bit float, double) and HFmode
+   (40-bit long double) where BITS_PER_BYTE is 32.
+
    If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it)
    then `long double' and `double' are both implemented, but they
    both mean DFmode.  In this case, the software floating-point
@@ -117,13 +118,18 @@ netlib.att.com: netlib/cephes.   */
 /* IBM System/370 style */
 #define IBM 1
 #else /* it's also not an IBM */
+#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
+/* TMS320C3x/C4x style */
+#define C4X 1
+#else /* it's also not a C4X */
 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
 #define IEEE
 #else /* it's not IEEE either */
-/* UNKnown arithmetic.  We don't support this and can't go on. */
+/* UNKnown arithmetic.  We don't support this and can't go on.  */
 unknown arithmetic type
 #define UNK 1
 #endif /* not IEEE */
+#endif /* not C4X */
 #endif /* not IBM */
 #endif /* not VAX */
 
@@ -158,12 +164,12 @@ unknown arithmetic type
 
 /* Define INFINITY for support of infinity.
    Define NANS for support of Not-a-Number's (NaN's).  */
-#if !defined(DEC) && !defined(IBM)
+#if !defined(DEC) && !defined(IBM) && !defined(C4X)
 #define INFINITY
 #define NANS
 #endif
 
-/* Support of NaNs requires support of infinity. */
+/* Support of NaNs requires support of infinity.  */
 #ifdef NANS
 #ifndef INFINITY
 #define INFINITY
@@ -171,7 +177,7 @@ unknown arithmetic type
 #endif
 \f
 /* Find a host integer type that is at least 16 bits wide,
-   and another type at least twice whatever that size is. */
+   and another type at least twice whatever that size is.  */
 
 #if HOST_BITS_PER_CHAR >= 16
 #define EMUSHORT char
@@ -193,7 +199,7 @@ unknown arithmetic type
 #define EMUSHORT_SIZE HOST_BITS_PER_LONG
 #define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
 #else
-/*  You will have to modify this program to have a smaller unit size. */
+/*  You will have to modify this program to have a smaller unit size.  */
 #define EMU_NON_COMPILE
 #endif
 #endif
@@ -209,10 +215,10 @@ unknown arithmetic type
 #if HOST_BITS_PER_LONG >= EMULONG_SIZE
 #define EMULONG long
 #else
-#if HOST_BITS_PER_LONG_LONG >= EMULONG_SIZE
+#if HOST_BITS_PER_LONGLONG >= EMULONG_SIZE
 #define EMULONG long long int
 #else
-/*  You will have to modify this program to have a smaller unit size. */
+/*  You will have to modify this program to have a smaller unit size.  */
 #define EMU_NON_COMPILE
 #endif
 #endif
@@ -220,12 +226,12 @@ unknown arithmetic type
 #endif
 
 
-/* The host interface doesn't work if no 16-bit size exists. */
+/* The host interface doesn't work if no 16-bit size exists.  */
 #if EMUSHORT_SIZE != 16
 #define EMU_NON_COMPILE
 #endif
 
-/* OK to continue compilation. */
+/* OK to continue compilation.  */
 #ifndef EMU_NON_COMPILE
 
 /* Construct macros to translate between REAL_VALUE_TYPE and e type.
@@ -253,12 +259,12 @@ unknown arithmetic type
 #define MINDECEXP -4956
 #ifdef REAL_ARITHMETIC
 /* Emulator uses target format internally
-   but host stores it in host endian-ness. */
+   but host stores it in host endian-ness.  */
 
 #define GET_REAL(r,e)                                          \
 do {                                                           \
      if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
-       e53toe ((unsigned EMUSHORT*) (r), (e));                 \
+       e53toe ((unsigned EMUSHORT *) (r), (e));                        \
      else                                                      \
        {                                                       \
         unsigned EMUSHORT w[4];                                \
@@ -293,7 +299,7 @@ do {                                                                \
 
 #endif /* not REAL_ARITHMETIC */
 #endif /* not TFmode */
-#endif /* no XFmode */
+#endif /* not XFmode */
 
 
 /* Number of 16 bit words in internal format */
@@ -324,7 +330,9 @@ static void endian  PROTO((unsigned EMUSHORT *, long *,
                               enum machine_mode));
 static void eclear     PROTO((unsigned EMUSHORT *));
 static void emov       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#if 0
 static void eabs       PROTO((unsigned EMUSHORT *));
+#endif
 static void eneg       PROTO((unsigned EMUSHORT *));
 static int eisneg      PROTO((unsigned EMUSHORT *));
 static int eisinf      PROTO((unsigned EMUSHORT *));
@@ -339,7 +347,9 @@ static void emovz   PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void einan      PROTO((unsigned EMUSHORT *));
 static int eiisnan     PROTO((unsigned EMUSHORT *));
 static int eiisneg     PROTO((unsigned EMUSHORT *));
+#if 0
 static void eiinfin    PROTO((unsigned EMUSHORT *));
+#endif
 static int eiisinf     PROTO((unsigned EMUSHORT *));
 static int ecmpm       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void eshdn1     PROTO((unsigned EMUSHORT *));
@@ -378,7 +388,9 @@ static void toe53   PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void etoe24     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void toe24      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static int ecmp                PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#if 0
 static void eround     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
 static void ltoe       PROTO((HOST_WIDE_INT *, unsigned EMUSHORT *));
 static void ultoe      PROTO((unsigned HOST_WIDE_INT *, unsigned EMUSHORT *));
 static void eifrac     PROTO((unsigned EMUSHORT *, HOST_WIDE_INT *,
@@ -387,10 +399,12 @@ static void euifrac       PROTO((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
                               unsigned EMUSHORT *));
 static int eshift      PROTO((unsigned EMUSHORT *, int));
 static int enormlz     PROTO((unsigned EMUSHORT *));
+#if 0
 static void e24toasc   PROTO((unsigned EMUSHORT *, char *, int));
 static void e53toasc   PROTO((unsigned EMUSHORT *, char *, int));
 static void e64toasc   PROTO((unsigned EMUSHORT *, char *, int));
 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 *));
@@ -399,28 +413,46 @@ 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 *,
                               unsigned EMUSHORT *));
+#endif
 static void eldexp     PROTO((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
+#if 0
 static void eremain    PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
+#endif
 static void eiremain   PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void mtherr     PROTO((char *, int));
+#ifdef DEC
 static void dectoe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void etodec     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void todec      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
+#ifdef IBM
 static void ibmtoe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               enum machine_mode));
 static void etoibm     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               enum machine_mode));
 static void toibm      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               enum machine_mode));
+#endif
+#ifdef C4X
+static void c4xtoe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+                              enum machine_mode));
+static void etoc4x     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+                              enum machine_mode));
+static void toc4x      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+                              enum machine_mode));
+#endif
 static void make_nan   PROTO((unsigned EMUSHORT *, int, enum machine_mode));
+#if 0
 static void uditoe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void ditoe      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void etoudi     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void etodi      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
 static void esqrt      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
 \f
 /* Copy 32-bit numbers obtained from array containing 16-bit numbers,
    swapping ends if required, into output array of longs.  The
@@ -438,17 +470,15 @@ endian (e, x, mode)
     {
       switch (mode)
        {
-
        case TFmode:
-         /* Swap halfwords in the fourth long. */
+         /* Swap halfwords in the fourth long.  */
          th = (unsigned long) e[6] & 0xffff;
          t = (unsigned long) e[7] & 0xffff;
          t |= th << 16;
          x[3] = (long) t;
 
        case XFmode:
-
-         /* Swap halfwords in the third long. */
+         /* Swap halfwords in the third long.  */
          th = (unsigned long) e[4] & 0xffff;
          t = (unsigned long) e[5] & 0xffff;
          t |= th << 16;
@@ -456,18 +486,16 @@ endian (e, x, mode)
          /* fall into the double case */
 
        case DFmode:
-
-         /* swap halfwords in the second word */
+         /* Swap halfwords in the second word.  */
          th = (unsigned long) e[2] & 0xffff;
          t = (unsigned long) e[3] & 0xffff;
          t |= th << 16;
          x[1] = (long) t;
          /* fall into the float case */
 
-       case HFmode:
        case SFmode:
-
-         /* swap halfwords in the first word */
+       case HFmode:
+         /* Swap halfwords in the first word.  */
          th = (unsigned long) e[0] & 0xffff;
          t = (unsigned long) e[1] & 0xffff;
          t |= th << 16;
@@ -480,21 +508,18 @@ endian (e, x, mode)
     }
   else
     {
-      /* Pack the output array without swapping. */
+      /* Pack the output array without swapping.  */
 
       switch (mode)
        {
-
        case TFmode:
-
-         /* Pack the fourth long. */
+         /* Pack the fourth long.  */
          th = (unsigned long) e[7] & 0xffff;
          t = (unsigned long) e[6] & 0xffff;
          t |= th << 16;
          x[3] = (long) t;
 
        case XFmode:
-
          /* Pack the third long.
             Each element of the input REAL_VALUE_TYPE array has 16 useful bits
             in it.  */
@@ -505,18 +530,16 @@ endian (e, x, mode)
          /* fall into the double case */
 
        case DFmode:
-
-         /* pack the second long */
+         /* Pack the second long */
          th = (unsigned long) e[3] & 0xffff;
          t = (unsigned long) e[2] & 0xffff;
          t |= th << 16;
          x[1] = (long) t;
          /* fall into the float case */
 
-       case HFmode:
        case SFmode:
-
-         /* pack the first long */
+       case HFmode:
+         /* Pack the first long */
          th = (unsigned long) e[1] & 0xffff;
          t = (unsigned long) e[0] & 0xffff;
          t |= th << 16;
@@ -545,7 +568,7 @@ earith (value, icode, r1, r2)
   GET_REAL (r1, d1);
   GET_REAL (r2, d2);
 #ifdef NANS
-/*  Return NaN input back to the caller. */
+/*  Return NaN input back to the caller.  */
   if (eisnan (d1))
     {
       PUT_REAL (d1, value);
@@ -668,23 +691,36 @@ ereal_atof (s, t)
 
   switch (t)
     {
+#ifdef C4X
+    case QFmode:
+    case HFmode:
+      asctoe53 (s, tem);
+      e53toe (tem, e);
+      break;
+#else
     case HFmode:
+#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);
     }
@@ -945,7 +981,7 @@ ereal_ldexp (x, n)
 
 #ifdef REAL_ARITHMETIC
 
-/* Check for infinity in a REAL_VALUE_TYPE. */
+/* Check for infinity in a REAL_VALUE_TYPE.  */
 
 int
 target_isinf (x)
@@ -961,7 +997,7 @@ target_isinf (x)
 #endif
 }
 
-/* Check whether a REAL_VALUE_TYPE item is a NaN. */
+/* Check whether a REAL_VALUE_TYPE item is a NaN.  */
 
 int
 target_isnan (x)
@@ -979,7 +1015,7 @@ target_isnan (x)
 
 
 /* Check for a negative REAL_VALUE_TYPE number.
-   This just checks the sign bit, so that -0 counts as negative. */
+   This just checks the sign bit, so that -0 counts as negative.  */
 
 int
 target_negative (x)
@@ -1022,12 +1058,22 @@ real_value_truncate (mode, arg)
       e53toe (t, t);
       break;
 
-    case HFmode:
     case SFmode:
+#ifndef C4X
+    case HFmode:
+#endif
       etoe24 (e, t);
       e24toe (t, t);
       break;
 
+#ifdef C4X
+    case HFmode:
+    case QFmode:
+      etoe53 (e, t);
+      e53toe (t, t);
+      break;
+#endif
+
     case SImode:
       r = etrunci (arg);
       return (r);
@@ -1043,6 +1089,68 @@ real_value_truncate (mode, arg)
   return (r);
 }
 
+/* Try to change R into its exact multiplicative inverse in machine mode
+   MODE.  Return nonzero function value if successful.  */
+
+int
+exact_real_inverse (mode, r)
+     enum machine_mode mode;
+     REAL_VALUE_TYPE *r;
+{
+  unsigned EMUSHORT e[NE], einv[NE];
+  REAL_VALUE_TYPE rinv;
+  int i;
+
+  GET_REAL (r, e);
+
+  /* Test for input in range.  Don't transform IEEE special values.  */
+  if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0))
+    return 0;
+
+  /* Test for a power of 2: all significand bits zero except the MSB.
+     We are assuming the target has binary (or hex) arithmetic.  */
+  if (e[NE - 2] != 0x8000)
+    return 0;
+
+  for (i = 0; i < NE - 2; i++)
+    {
+      if (e[i] != 0)
+       return 0;
+    }
+
+  /* Compute the inverse and truncate it to the required mode.  */
+  ediv (e, eone, einv);
+  PUT_REAL (einv, &rinv);
+  rinv = real_value_truncate (mode, rinv);
+
+#ifdef CHECK_FLOAT_VALUE
+  /* This check is not redundant.  It may, for example, flush
+     a supposedly IEEE denormal value to zero.  */
+  i = 0;
+  if (CHECK_FLOAT_VALUE (mode, rinv, i))
+    return 0;
+#endif
+  GET_REAL (&rinv, einv);
+
+  /* Check the bits again, because the truncation might have
+     generated an arbitrary saturation value on overflow.  */
+  if (einv[NE - 2] != 0x8000)
+    return 0;
+
+  for (i = 0; i < NE - 2; i++)
+    {
+      if (einv[i] != 0)
+       return 0;
+    }
+
+  /* Fail if the computed inverse is out of range.  */
+  if (eisinf (einv) || eisnan (einv) || (ecmp (einv, ezero) == 0))
+    return 0;
+
+  /* Output the reciprocal and return success flag.  */
+  PUT_REAL (einv, r);
+  return 1;
+}
 #endif /* REAL_ARITHMETIC defined */
 
 /* Used for debugging--print the value of R in human-readable format
@@ -1216,7 +1324,9 @@ ereal_isneg (x)
        e53toe (&d, e)          IEEE double precision to e type
        e64toe (&d, e)          IEEE long double precision to e type
        e113toe (&d, e)         128-bit long double precision to e type
+#if 0
        eabs (e)                        absolute value
+#endif
        eadd (a, b, c)          c = b + a
        eclear (e)              e = 0
        ecmp (a, b)             Returns 1 if a > b, 0 if a == b,
@@ -1231,12 +1341,16 @@ ereal_isneg (x)
        emov (a, b)             b = a
        emul (a, b, c)          c = b * a
        eneg (e)                        e = -e
+#if 0
        eround (a, b)           b = nearest integer value to a
+#endif
        esub (a, b, c)          c = b - a
+#if 0
        e24toasc (&f, str, n)   single to ASCII string, n digits after decimal
        e53toasc (&d, str, n)   double to ASCII string, n digits after decimal
        e64toasc (&d, str, n)   80-bit long double to ASCII string
        e113toasc (&d, str, n)  128-bit long double to ASCII string
+#endif
        etoasc (e, str, n)      e to ASCII string, n digits after decimal
        etoe24 (e, &f)          convert e type to IEEE single precision
        etoe53 (e, &d)          convert e type to IEEE double precision
@@ -1274,7 +1388,9 @@ ereal_isneg (x)
         eiisnan (ai)            1 if a NaN
        eiisneg (ai)            1 if sign bit of ai != 0, else 0
         einan (ai)              set ai = NaN
+#if 0
         eiinfin (ai)            set ai = infinity
+#endif
 
   The result is always normalized and rounded to NI-4 word precision
   after each arithmetic operation.
@@ -1330,7 +1446,7 @@ ereal_isneg (x)
   ensure that these values are correct for your computer.
  
   For ANSI C compatibility, define ANSIC equal to 1.  Currently
-  this affects only the atan2 function and others that use it. */
+  this affects only the atan2 function and others that use it.  */
 
 /* Constant definitions for math error conditions.  */
 
@@ -1444,6 +1560,7 @@ emov (a, b)
 }
 
 
+#if 0
 /* Absolute value of e-type X.  */
 
 static void 
@@ -1453,6 +1570,7 @@ eabs (x)
   /* sign is top bit of last word of external format */
   x[NE - 1] &= 0x7fff;         
 }
+#endif /* 0 */
 
 /* Negate the e-type number X.  */
 
@@ -1507,7 +1625,7 @@ eisnan (x)
   /* NaN has maximum exponent */
   if ((x[NE - 1] & 0x7fff) != 0x7fff)
     return (0);
-  /* ... and non-zero significand field. */
+  /* ... and non-zero significand field.  */
   for (i = 0; i < NE - 1; i++)
     {
       if (*x++ != 0)
@@ -1519,7 +1637,7 @@ eisnan (x)
 }
 
 /*  Fill e-type number X with infinity pattern (IEEE)
-    or largest possible number (non-IEEE). */
+    or largest possible number (non-IEEE).  */
 
 static void 
 einfin (x)
@@ -1675,7 +1793,7 @@ ecleaz (xi)
     *xi++ = 0;
 }
 
-/* Clear out exploded e-type XI, but don't touch the sign. */
+/* Clear out exploded e-type XI, but don't touch the sign.  */
 
 static void 
 ecleazs (xi)
@@ -1716,7 +1834,7 @@ einan (x)
   x[M + 1] = 0xc000;
 }
 
-/* Return nonzero if exploded e-type X is a NaN. */
+/* Return nonzero if exploded e-type X is a NaN.  */
 
 static int 
 eiisnan (x)
@@ -1745,6 +1863,7 @@ eiisneg (x)
   return x[0] != 0;
 }
 
+#if 0
 /* Fill exploded e-type X with infinity pattern.
    This has maximum exponent and significand all zeros.  */
 
@@ -1756,8 +1875,9 @@ eiinfin (x)
   ecleaz (x);
   x[E] = 0x7fff;
 }
+#endif /* 0 */
 
-/* Return nonzero if exploded e-type X is infinite. */
+/* Return nonzero if exploded e-type X is infinite.  */
 
 static int 
 eiisinf (x)
@@ -2090,6 +2210,7 @@ edivm (den, num)
 
 
 /* Multiply significands */
+
 int 
 emulm (a, b)
      unsigned EMUSHORT a[], b[];
@@ -2140,7 +2261,7 @@ emulm (a, b)
 /* Radix 65536 versions of multiply and divide.  */
 
 /* Multiply significand of e-type number B
-   by 16-bit quantity A, return e-type result to C. */
+   by 16-bit quantity A, return e-type result to C.  */
 
 static void
 m16m (a, b, c)
@@ -2208,17 +2329,17 @@ edivm (den, num)
   tdenm = den[M+1];
   for (i=M; i<NI; i++)
     {
-      /* Find trial quotient digit (the radix is 65536). */
+      /* Find trial quotient digit (the radix is 65536).  */
       tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
 
-      /* Do not execute the divide instruction if it will overflow. */
+      /* 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. */
+      /* Multiply denominator by trial quotient digit.  */
       m16m ((unsigned int)tquot, den, tprod);
-      /* The quotient digit may have been overestimated. */
+      /* The quotient digit may have been overestimated.  */
       if (ecmpm (tprod, num) > 0)
        {
          tquot -= 1;
@@ -2341,7 +2462,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
   /* Normalize */
   j = enormlz (s);
 
-  /* a blank significand could mean either zero or infinity. */
+  /* a blank significand could mean either zero or infinity.  */
 #ifndef INFINITY
   if (j > NBITS)
     {
@@ -2375,10 +2496,10 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          return;
        }
     }
-  /* Round off, unless told not to by rcntrl. */
+  /* Round off, unless told not to by rcntrl.  */
   if (rcntrl == 0)
     goto mdfin;
-  /* Set up rounding parameters if the control register changed. */
+  /* Set up rounding parameters if the control register changed.  */
   if (rndprc != rlast)
     {
       ecleaz (rbit);
@@ -2392,6 +2513,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          re = rw - 1;
          rebit = 1;
          break;
+
        case 113:
          rw = 10;
          rmsk = 0x7fff;
@@ -2399,6 +2521,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          rebit = 0x8000;
          re = rw;
          break;
+
        case 64:
          rw = 7;
          rmsk = 0xffff;
@@ -2406,6 +2529,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          re = rw - 1;
          rebit = 1;
          break;
+
          /* For DEC or IBM arithmetic */
        case 56:
          rw = 6;
@@ -2414,6 +2538,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          rebit = 0x100;
          re = rw;
          break;
+
        case 53:
          rw = 6;
          rmsk = 0x7ff;
@@ -2421,6 +2546,16 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          rebit = 0x800;
          re = rw;
          break;
+
+         /* For C4x arithmetic */
+       case 32:
+         rw = 5;
+         rmsk = 0xffff;
+         rmbit = 0x8000;
+         rebit = 1;
+         re = rw - 1;
+         break;
+
        case 24:
          rw = 4;
          rmsk = 0xff;
@@ -2475,7 +2610,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
       eaddm (rbit, s);
     }
  mddone:
-/* Undo the temporary shift for denormal values. */
+/* Undo the temporary shift for denormal values.  */
   if ((exp <= 0) && (rndprc != NBITS)
       && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
     {
@@ -2544,7 +2679,7 @@ esub (a, b, c)
       return;
     }
 /* Infinity minus infinity is a NaN.
-   Test for subtracting infinities of the same sign. */
+   Test for subtracting infinities of the same sign.  */
   if (eisinf (a) && eisinf (b)
       && ((eisneg (a) ^ eisneg (b)) == 0))
     {
@@ -2557,7 +2692,7 @@ esub (a, b, c)
   eadd1 (a, b, c);
 }
 
-/* Add.  C = A + B, all e type. */
+/* Add.  C = A + B, all e type.  */
 
 static void 
 eadd (a, b, c)
@@ -2565,7 +2700,7 @@ eadd (a, b, c)
 {
 
 #ifdef NANS
-/* NaN plus anything is a NaN. */
+/* NaN plus anything is a NaN.  */
   if (eisnan (a))
     {
       emov (a, c);
@@ -2577,7 +2712,7 @@ eadd (a, b, c)
       return;
     }
 /* Infinity minus infinity is a NaN.
-   Test for adding infinities of opposite signs. */
+   Test for adding infinities of opposite signs.  */
   if (eisinf (a) && eisinf (b)
       && ((eisneg (a) ^ eisneg (b)) != 0))
     {
@@ -2716,7 +2851,7 @@ ediv (a, b, c)
   sign = eisneg(a) ^ eisneg(b);
 
 #ifdef NANS
-/* Return any NaN input. */
+/* Return any NaN input.  */
   if (eisnan (a))
     {
     emov (a, c);
@@ -2727,7 +2862,7 @@ ediv (a, b, c)
     emov (b, c);
     return;
     }
-/* Zero over zero, or infinity over infinity, is a NaN. */
+/* Zero over zero, or infinity over infinity, is a NaN.  */
   if (((ecmp (a, ezero) == 0) && (ecmp (b, ezero) == 0))
       || (eisinf (a) && eisinf (b)))
     {
@@ -2736,14 +2871,14 @@ ediv (a, b, c)
     return;
     }
 #endif
-/* Infinity over anything else is infinity. */
+/* Infinity over anything else is infinity.  */
 #ifdef INFINITY
   if (eisinf (b))
     {
       einfin (c);
       goto divsign;
     }
-/* Anything else over infinity is zero. */
+/* Anything else over infinity is zero.  */
   if (eisinf (a))
     {
       eclear (c);
@@ -2755,7 +2890,7 @@ ediv (a, b, c)
   lta = ai[E];
   ltb = bi[E];
   if (bi[E] == 0)
-    {                          /* See if numerator is zero. */
+    {                          /* See if numerator is zero.  */
       for (i = 1; i < NI - 1; i++)
        {
          if (bi[i] != 0)
@@ -2820,7 +2955,7 @@ emul (a, b, c)
   sign = eisneg(a) ^ eisneg(b);
 
 #ifdef NANS
-/* NaN times anything is the same NaN. */
+/* NaN times anything is the same NaN.  */
   if (eisnan (a))
     {
     emov (a, c);
@@ -2831,7 +2966,7 @@ emul (a, b, c)
     emov (b, c);
     return;
     }
-/* Zero times infinity is a NaN. */
+/* Zero times infinity is a NaN.  */
   if ((eisinf (a) && (ecmp (b, ezero) == 0))
       || (eisinf (b) && (ecmp (a, ezero) == 0)))
     {
@@ -2840,7 +2975,7 @@ emul (a, b, c)
     return;
     }
 #endif
-/* Infinity times anything else is infinity. */
+/* Infinity times anything else is infinity.  */
 #ifdef INFINITY
   if (eisinf (a) || eisinf (b))
     {
@@ -2917,6 +3052,11 @@ e53toe (pe, y)
   ibmtoe (pe, y, DFmode);
 
 #else
+#ifdef C4X
+
+  c4xtoe (pe, y, HFmode);
+
+#else
   register unsigned EMUSHORT r;
   register unsigned EMUSHORT *e, *p;
   unsigned EMUSHORT yy[NI];
@@ -2965,7 +3105,7 @@ e53toe (pe, y)
 #endif  /* INFINITY */
   r >>= 4;
   /* If zero exponent, then the significand is denormalized.
-     So take back the understood high significand bit. */
+     So take back the understood high significand bit.  */
 
   if (r == 0)
     {
@@ -2992,13 +3132,15 @@ e53toe (pe, y)
 #endif
   eshift (yy, -5);
   if (denorm)
-    {                          /* if zero exponent, then normalize the significand */
+    {                  
+       /* If zero exponent, then normalize the significand.  */
       if ((k = enormlz (yy)) > NBITS)
        ecleazs (yy);
       else
        yy[E] -= (unsigned EMUSHORT) (k - 1);
     }
   emovo (yy, y);
+#endif /* not C4X */
 #endif /* not IBM */
 #endif /* not DEC */
 }
@@ -3017,7 +3159,7 @@ e64toe (pe, y)
   p = yy;
   for (i = 0; i < NE - 5; i++)
     *p++ = 0;
-/* This precision is not ordinarily supported on DEC or IBM. */
+/* This precision is not ordinarily supported on DEC or IBM.  */
 #ifdef DEC
   for (i = 0; i < 5; i++)
     *p++ = *e++;
@@ -3197,7 +3339,7 @@ e113toe (pe, y)
        *p++ = *e++;
     }
 #endif
-/* If denormal, remove the implied bit; else shift down 1. */
+/* If denormal, remove the implied bit; else shift down 1.  */
   if (r == 0)
     {
       yy[M] = 0;
@@ -3221,6 +3363,13 @@ e24toe (pe, y)
   ibmtoe (pe, y, SFmode);
 
 #else
+
+#ifdef C4X
+
+  c4xtoe (pe, y, QFmode);
+
+#else
+
   register unsigned EMUSHORT r;
   register unsigned EMUSHORT *e, *p;
   unsigned EMUSHORT yy[NI];
@@ -3272,7 +3421,7 @@ e24toe (pe, y)
 #endif  /* INFINITY */
   r >>= 7;
   /* If zero exponent, then the significand is denormalized.
-     So take back the understood high significand bit. */
+     So take back the understood high significand bit.  */
   if (r == 0)
     {
       denorm = 1;
@@ -3302,6 +3451,7 @@ e24toe (pe, y)
        yy[E] -= (unsigned EMUSHORT) (k - 1);
     }
   emovo (yy, y);
+#endif /* not C4X */
 #endif /* not IBM */
 }
 
@@ -3360,7 +3510,7 @@ toe113 (a, b)
   else
     q = b + 7;                 /* point to output exponent */
 
-  /* If not denormal, delete the implied bit. */
+  /* If not denormal, delete the implied bit.  */
   if (a[E] != 0)
     {
       eshup1 (a);
@@ -3586,7 +3736,28 @@ toe53 (x, y)
   toibm (x, y, DFmode);
 }
 
-#else  /* it's neither DEC nor IBM */
+#else /* it's neither DEC nor IBM */
+#ifdef C4X
+/* Convert e-type X to C4X-format long double E.  */
+
+static void 
+etoe53 (x, e)
+     unsigned EMUSHORT *x, *e;
+{
+  etoc4x (x, e, HFmode);
+}
+
+/* Convert exploded e-type X, that has already been rounded to
+   56-bit precision, to IBM 370 double Y.  */
+
+static void 
+toe53 (x, y)
+     unsigned EMUSHORT *x, *y;
+{
+  toc4x (x, y, HFmode);
+}
+
+#else  /* it's neither DEC nor IBM nor C4X */
 
 /* Convert e-type X to IEEE double E.  */
 
@@ -3649,7 +3820,8 @@ toe53 (x, y)
 
   i = *p++;
   if (i >= (unsigned int) 2047)
-    {                          /* Saturate at largest number less than infinity. */
+    {
+      /* Saturate at largest number less than infinity.  */
 #ifdef INFINITY
       *y |= 0x7ff0;
       if (! REAL_WORDS_BIG_ENDIAN)
@@ -3709,6 +3881,7 @@ toe53 (x, y)
     }
 }
 
+#endif /* not C4X */
 #endif /* not IBM */
 #endif /* not DEC */
 
@@ -3737,6 +3910,29 @@ toe24 (x, y)
 }
 
 #else
+
+#ifdef C4X
+/* Convert e-type X to C4X float E.  */
+
+static void 
+etoe24 (x, e)
+     unsigned EMUSHORT *x, *e;
+{
+  etoc4x (x, e, QFmode);
+}
+
+/* Convert exploded e-type X, that has already been rounded to
+   float precision, to IBM 370 float Y.  */
+
+static void 
+toe24 (x, y)
+     unsigned EMUSHORT *x, *y;
+{
+  toc4x (x, y, QFmode);
+}
+
+#else
+
 /* Convert e-type X to IEEE float E.  DEC float is the same as IEEE float.  */
 
 static void 
@@ -3800,7 +3996,7 @@ toe24 (x, y)
     *y = 0x8000;               /* output sign bit */
 
   i = *p++;
-/* Handle overflow cases. */
+/* Handle overflow cases.  */
   if (i >= 255)
     {
 #ifdef INFINITY
@@ -3862,6 +4058,7 @@ toe24 (x, y)
     }
 #endif
 }
+#endif  /* not C4X */
 #endif  /* not IBM */
 
 /* Compare two e type numbers. 
@@ -3930,6 +4127,7 @@ ecmp (a, b)
     return (-msign);           /* p is littler */
 }
 
+#if 0
 /* Find e-type nearest integer to X, as floor (X + 0.5).  */
 
 static void 
@@ -3939,6 +4137,7 @@ eround (x, y)
   eadd (ehalf, x, y);
   efloor (y, y);
 }
+#endif /* 0 */
 
 /* Convert HOST_WIDE_INT LP to e type Y.  */
 
@@ -4160,7 +4359,7 @@ euifrac (x, i, frac)
       *i = (HOST_WIDE_INT) xi[M] & 0xffff;
     }
 
-  if (xi[0])  /* A negative value yields unsigned integer 0. */
+  if (xi[0])  /* A negative value yields unsigned integer 0.  */
     *i = 0L;
 
   xi[0] = 0;
@@ -4410,6 +4609,7 @@ static unsigned EMUSHORT emtens[NTEN + 1][NE] =
 };
 #endif
 
+#if 0
 /* Convert float value X to ASCII string STRING with NDIG digits after
    the decimal point.  */
 
@@ -4469,6 +4669,7 @@ e113toasc (x, string, ndigs)
   e113toe (x, w);
   etoasc (w, string, ndigs);
 }
+#endif /* 0 */
 
 /* Convert e-type X to ASCII string STRING with NDIGS digits after
    the decimal point.  */
@@ -4528,7 +4729,7 @@ etoasc (x, string, ndigs)
     }
  tnzro:
 
-  /* Test for infinity. */
+  /* Test for infinity.  */
   if (y[NE - 1] == 0x7fff)
     {
       if (sign)
@@ -4558,7 +4759,7 @@ etoasc (x, string, ndigs)
 
   if (i < 0)
     {                          /* Number is greater than 1 */
-      /* Convert significand to an integer and strip trailing decimal zeros. */
+      /* Convert significand to an integer and strip trailing decimal zeros.  */
       emov (y, u);
       u[NE - 1] = EXONE + NBITS - 1;
 
@@ -4588,7 +4789,7 @@ etoasc (x, string, ndigs)
       emov (eone, t);
       m = MAXP;
       p = &etens[0][0];
-      /* An unordered compare result shouldn't happen here. */
+      /* An unordered compare result shouldn't happen here.  */
       while (ecmp (ten, u) <= 0)
        {
          if (ecmp (p, u) <= 0)
@@ -4605,7 +4806,7 @@ etoasc (x, string, ndigs)
     }
   else
     {                          /* Number is less than 1.0 */
-      /* Pad significand with trailing decimal zeros. */
+      /* Pad significand with trailing decimal zeros.  */
       if (y[NE - 1] == 0)
        {
          while ((y[NE - 2] & 0x8000) == 0)
@@ -4663,7 +4864,7 @@ etoasc (x, string, ndigs)
       ediv (t, eone, t);
     }
  isone:
-  /* Find the first (leading) digit. */
+  /* Find the first (leading) digit.  */
   emovi (t, w);
   emovz (w, t);
   emovi (y, w);
@@ -4686,7 +4887,7 @@ etoasc (x, string, ndigs)
     *s++ = '-';
   else
     *s++ = ' ';
-  /* Examine number of digits requested by caller. */
+  /* Examine number of digits requested by caller.  */
   if (ndigs < 0)
     ndigs = 0;
   if (ndigs > NDEC)
@@ -4707,7 +4908,7 @@ etoasc (x, string, ndigs)
       *s++ = (char)digit + '0';
       *s++ = '.';
     }
-  /* Generate digits after the decimal point. */
+  /* Generate digits after the decimal point.  */
   for (k = 0; k <= ndigs; k++)
     {
       /* multiply current number by 10, without normalizing */
@@ -4725,7 +4926,7 @@ etoasc (x, string, ndigs)
   /* round off the ASCII string */
   if (digit > 4)
     {
-      /* Test for critical rounding case in ASCII output. */
+      /* Test for critical rounding case in ASCII output.  */
       if (digit == 5)
        {
          emovo (y, t);
@@ -4810,8 +5011,12 @@ asctoe53 (s, 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
 }
 
 
@@ -4846,7 +5051,7 @@ asctoe (s, y)
 }
 
 /* Convert ASCII string SS to e type Y, with a specified rounding precision
-   of OPREC bits. */
+   of OPREC bits.  */
 
 static void 
 asctoeg (ss, y, oprec)
@@ -4861,7 +5066,7 @@ asctoeg (ss, y, oprec)
   unsigned EMUSHORT nsign, *p;
   char *sp, *s, *lstr;
 
-  /* Copy the input string. */
+  /* Copy the input string.  */
   lstr = (char *) alloca (strlen (ss) + 1);
   s = ss;
   while (*s == ' ')            /* skip leading spaces */
@@ -4890,7 +5095,7 @@ asctoeg (ss, y, oprec)
       /* Ignore leading zeros */
       if ((prec == 0) && (decflg == 0) && (k == 0))
        goto donchr;
-      /* Identify and strip trailing zeros after the decimal point. */
+      /* Identify and strip trailing zeros after the decimal point.  */
       if ((trail == 0) && (decflg != 0))
        {
          sp = s;
@@ -5038,7 +5243,7 @@ read_expnt:
 
  daldone:
   nexp = exp - nexp;
-  /* Pad trailing zeros to minimize power of 10, per IEEE spec. */
+  /* Pad trailing zeros to minimize power of 10, per IEEE spec.  */
   while ((nexp > 0) && (yy[2] == 0))
     {
       emovz (yy, xt);
@@ -5080,7 +5285,7 @@ read_expnt:
       esign = -1;
       if (nexp > 4096)
        {
-         /* Punt.  Can't handle this without 2 divides. */
+         /* Punt.  Can't handle this without 2 divides.  */
          emovi (etens[0], tt);
          lexp -= tt[E];
          k = edivm (tt, yy);
@@ -5119,13 +5324,18 @@ read_expnt:
   /* Round and convert directly to the destination type */
   if (oprec == 53)
     lexp -= EXONE - 0x3ff;
+#ifdef C4X
+  else if (oprec == 24 || oprec == 32)
+    lexp -= (EXONE - 0x7f);
+#else
 #ifdef IBM
   else if (oprec == 24 || oprec == 56)
     lexp -= EXONE - (0x41 << 2);
 #else
   else if (oprec == 24)
     lexp -= EXONE - 0177;
-#endif
+#endif /* IBM */
+#endif /* C4X */
 #ifdef DEC
   else if (oprec == 56)
     lexp -= EXONE - 0201;
@@ -5149,6 +5359,12 @@ read_expnt:
       toibm (yy, y, DFmode);
       break;
 #endif
+#ifdef C4X
+    case 32:
+      toc4x (yy, y, HFmode);
+      break;
+#endif
+
     case 53:
       toe53 (yy, y);
       break;
@@ -5240,6 +5456,7 @@ efloor (x, y)
 }
 
 
+#if 0
 /* Return S and EXP such that  S * 2^EXP = X and .5 <= S < 1.
    For example, 1.1 = 0.55 * 2^1.  */
 
@@ -5264,6 +5481,7 @@ efrexp (x, exp, s)
   emovo (xi, s);
   *exp = (int) (li - 0x3ffe);
 }
+#endif
 
 /* Return e type Y = X * 2^PWR2.  */
 
@@ -5286,6 +5504,7 @@ eldexp (x, pwr2, y)
 }
 
 
+#if 0
 /* C = remainder after dividing B by A, all e type values.
    Least significant integer quotient bits left in EQUOT.  */
 
@@ -5321,6 +5540,7 @@ eremain (a, b, c)
     num[0] = 0xffff;
   emovo (num, c);
 }
+#endif
 
 /*  Return quotient of exploded e-types NUM / DEN in EQUOT,
     remainder in NUM.  */
@@ -5636,11 +5856,259 @@ toibm (x, y, mode)
 }
 #endif /* IBM */
 
+
+#ifdef C4X
+/* Convert C4X single/double precision to e type.  */
+
+static void 
+c4xtoe (d, e, mode)
+     unsigned EMUSHORT *d;
+     unsigned EMUSHORT *e;
+     enum machine_mode mode;
+{
+  unsigned EMUSHORT y[NI];
+  int r;
+  int rndsav;
+  int isnegative;
+  int size;
+  int i;
+  int carry;
+
+  /* Short-circuit the zero case. */
+  if ((d[0] == 0x8000)
+      && (d[1] == 0x0000)
+      && ((mode == QFmode) || ((d[2] == 0x0000) && (d[3] == 0x0000))))
+    {
+      e[0] = 0;
+      e[1] = 0;
+      e[2] = 0;
+      e[3] = 0;
+      e[4] = 0;
+      e[5] = 0;
+      return;
+    }
+
+  ecleaz (y);                  /* start with a zero */
+  r = d[0];                    /* get sign/exponent part */
+  if (r & (unsigned int) 0x0080)
+  {
+     y[0] = 0xffff;            /* fill in our sign */
+     isnegative = TRUE;
+  }
+  else
+  {
+     isnegative = FALSE;
+  }
+     
+  r >>= 8;                     /* Shift exponent word down 8 bits.  */
+  if (r & 0x80)                        /* Make the exponent negative if it is. */
+  {
+     r = r | (~0 & ~0xff);
+  }
+
+  if (isnegative)
+  {
+     /* Now do the high order mantissa.  We don't "or" on the high bit
+       because it is 2 (not 1) and is handled a little differently
+       below.  */
+     y[M] = d[0] & 0x7f;       
+
+     y[M+1] = d[1];
+     if (mode != QFmode)       /* There are only 2 words in QFmode.  */
+     {
+       y[M+2] = d[2];          /* Fill in the rest of our mantissa.  */
+       y[M+3] = d[3];
+       size = 4;
+     }
+     else
+     {
+       size = 2;
+     }
+     eshift(y, -8);
+
+     /* Now do the two's complement on the data.  */
+
+     carry = 1;        /* Initially add 1 for the two's complement. */
+     for (i=size + M; i > M; i--)
+     {
+       if (carry && (y[i] == 0x0000))
+       {
+          /* We overflowed into the next word, carry is the same.  */
+          y[i] = carry ? 0x0000 : 0xffff;
+       }
+       else
+       {
+          /* No overflow, just invert and add carry.  */
+          y[i] = ((~y[i]) + carry) & 0xffff;
+          carry = 0;
+       }
+     }
+
+     if (carry)
+     {
+       eshift(y, -1);
+       y[M+1] |= 0x8000;
+       r++;
+     }
+     y[1] = r + EXONE;
+  }
+  else
+  {
+    /* Add our e type exponent offset to form our exponent.  */
+     r += EXONE;
+     y[1] = r;                 
+
+     /* Now do the high order mantissa strip off the exponent and sign
+       bits and add the high 1 bit.  */
+     y[M] = d[0] & 0x7f | 0x80;        
+
+     y[M+1] = d[1];
+     if (mode != QFmode)       /* There are only 2 words in QFmode.  */
+     {
+       y[M+2] = d[2];          /* Fill in the rest of our mantissa.  */
+       y[M+3] = d[3];
+     }
+     eshift(y, -8);
+  }
+
+  emovo (y, e);
+}
+
+
+/* Convert e type to C4X single/double precision.  */
+
+static void 
+etoc4x (x, d, mode)
+     unsigned EMUSHORT *x, *d;
+     enum machine_mode mode;
+{
+  unsigned EMUSHORT xi[NI];
+  EMULONG exp;
+  int rndsav;
+
+  emovi (x, xi);
+
+  /* Adjust exponent for offsets. */
+  exp = (EMULONG) xi[E] - (EXONE - 0x7f);
+
+  /* Round off to nearest or even. */
+  rndsav = rndprc;
+  rndprc = mode == QFmode ? 24 : 32;
+  emdnorm (xi, 0, 0, exp, 64);
+  rndprc = rndsav;
+  toc4x (xi, d, mode);
+}
+
+static void 
+toc4x (x, y, mode)
+     unsigned EMUSHORT *x, *y;
+     enum machine_mode mode;
+{
+  int i;
+  int r;
+  int v;
+  int carry;
+  
+  /* Short-circuit the zero case */
+  if ((x[0] == 0)      /* Zero exponent and sign */
+      && (x[1] == 0)
+      && (x[M] == 0)   /* The rest is for zero mantissa */
+      && (x[M+1] == 0)
+      /* Only check for double if necessary */
+      && ((mode == QFmode) || ((x[M+2] == 0) && (x[M+3] == 0))))
+    {
+      /* We have a zero.  Put it into the output and return. */
+      *y++ = 0x8000;
+      *y++ = 0x0000;
+      if (mode != QFmode)
+        {
+          *y++ = 0x0000;
+          *y++ = 0x0000;
+        }
+      return;
+    }
+  
+  *y = 0;
+  
+  /* Negative number require a two's complement conversion of the
+     mantissa. */
+  if (x[0])
+    {
+      *y = 0x0080;
+      
+      i = ((int) x[1]) - 0x7f;
+      
+      /* Now add 1 to the inverted data to do the two's complement. */
+      if (mode != QFmode)
+       v = 4 + M;
+      else
+       v = 2 + M;
+      carry = 1;
+      while (v > M)
+       {
+         if (x[v] == 0x0000)
+           {
+             x[v] = carry ? 0x0000 : 0xffff;
+           }
+         else
+           {
+             x[v] = ((~x[v]) + carry) & 0xffff;
+             carry = 0;
+           }
+         v--;
+       }
+      
+      /* The following is a special case.  The C4X negative float requires
+        a zero in the high bit (because the format is (2 - x) x 2^m), so
+        if a one is in that bit, we have to shift left one to get rid
+        of it.  This only occurs if the number is -1 x 2^m. */
+      if (x[M+1] & 0x8000)
+       {
+         /* This is the case of -1 x 2^m, we have to rid ourselves of the
+            high sign bit and shift the exponent. */
+         eshift(x, 1);
+         i--;
+       }
+    }
+  else
+    {
+      i = ((int) x[1]) - 0x7f;
+    }
+
+  if ((i < -128) || (i > 127))
+    {
+      y[0] |= 0xff7f;
+      y[1] = 0xffff;
+      if (mode != QFmode)
+       {
+         y[2] = 0xffff;
+         y[3] = 0xffff;
+       }
+#ifdef ERANGE
+      errno = ERANGE;
+#endif
+      return;
+    }
+  
+  y[0] |= ((i & 0xff) << 8);
+  
+  eshift (x, 8);
+  
+  y[0] |= x[M] & 0x7f;
+  y[1] = x[M + 1];
+  if (mode != QFmode)
+    {
+      y[2] = x[M + 2];
+      y[3] = x[M + 3];
+    }
+}
+#endif /* C4X */
+
 /* Output a binary NaN bit pattern in the target machine's format.  */
 
 /* If special NaN bit patterns are required, define them in tm.h
    as arrays of unsigned 16-bit shorts.  Otherwise, use the default
-   patterns here. */
+   patterns here.  */
 #ifdef TFMODE_NAN
 TFMODE_NAN;
 #else
@@ -5692,8 +6160,8 @@ make_nan (nan, sign, mode)
   switch (mode)
     {
 /* Possibly the `reserved operand' patterns on a VAX can be
-   used like NaN's, but probably not in the same way as IEEE. */
-#if !defined(DEC) && !defined(IBM)
+   used like NaN's, but probably not in the same way as IEEE.  */
+#if !defined(DEC) && !defined(IBM) && !defined(C4X)
     case TFmode:
       n = 8;
       if (REAL_WORDS_BIG_ENDIAN)
@@ -5701,6 +6169,7 @@ make_nan (nan, sign, mode)
       else
        p = TFlittlenan;
       break;
+
     case XFmode:
       n = 6;
       if (REAL_WORDS_BIG_ENDIAN)
@@ -5708,6 +6177,7 @@ make_nan (nan, sign, mode)
       else
        p = XFlittlenan;
       break;
+
     case DFmode:
       n = 4;
       if (REAL_WORDS_BIG_ENDIAN)
@@ -5715,8 +6185,9 @@ make_nan (nan, sign, mode)
       else
        p = DFlittlenan;
       break;
-    case HFmode:
+
     case SFmode:
+    case HFmode:
       n = 2;
       if (REAL_WORDS_BIG_ENDIAN)
        p = SFbignan;
@@ -5724,6 +6195,7 @@ make_nan (nan, sign, mode)
        p = SFlittlenan;
       break;
 #endif
+
     default:
       abort ();
     }
@@ -5735,13 +6207,12 @@ make_nan (nan, sign, mode)
     *nan = (sign << 15) | *p;
 }
 
-/* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
-   This is the inverse of the function `etarsingle' invoked by
+/* This is the inverse of the function `etarsingle' invoked by
    REAL_VALUE_TO_TARGET_SINGLE.  */
 
 REAL_VALUE_TYPE
-ereal_from_float (f)
-     HOST_WIDE_INT f;
+ereal_unto_float (f)
+     long f;
 {
   REAL_VALUE_TYPE r;
   unsigned EMUSHORT s[2];
@@ -5767,9 +6238,76 @@ ereal_from_float (f)
 }
 
 
+/* This is the inverse of the function `etardouble' invoked by
+   REAL_VALUE_TO_TARGET_DOUBLE.  */
+
+REAL_VALUE_TYPE
+ereal_unto_double (d)
+     long d[];
+{
+  REAL_VALUE_TYPE r;
+  unsigned EMUSHORT s[4];
+  unsigned EMUSHORT e[NE];
+
+  /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces.  */
+  if (REAL_WORDS_BIG_ENDIAN)
+    {
+      s[0] = (unsigned EMUSHORT) (d[0] >> 16);
+      s[1] = (unsigned EMUSHORT) d[0];
+      s[2] = (unsigned EMUSHORT) (d[1] >> 16);
+      s[3] = (unsigned EMUSHORT) d[1];
+    }
+  else
+    {
+      /* Target float words are little-endian.  */
+      s[0] = (unsigned EMUSHORT) d[0];
+      s[1] = (unsigned EMUSHORT) (d[0] >> 16);
+      s[2] = (unsigned EMUSHORT) d[1];
+      s[3] = (unsigned EMUSHORT) (d[1] >> 16);
+    }
+  /* Convert target double to E-type. */
+  e53toe (s, e);
+  /* Output E-type to REAL_VALUE_TYPE. */
+  PUT_REAL (e, &r);
+  return r;
+}
+
+
+/* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
+   This is somewhat like ereal_unto_float, but the input types
+   for these are different.  */
+
+REAL_VALUE_TYPE
+ereal_from_float (f)
+     HOST_WIDE_INT f;
+{
+  REAL_VALUE_TYPE r;
+  unsigned EMUSHORT s[2];
+  unsigned EMUSHORT e[NE];
+
+  /* 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 (REAL_WORDS_BIG_ENDIAN)
+    {
+      s[0] = (unsigned EMUSHORT) (f >> 16);
+      s[1] = (unsigned EMUSHORT) f;
+    }
+  else
+    {
+      s[0] = (unsigned EMUSHORT) f;
+      s[1] = (unsigned EMUSHORT) (f >> 16);
+    }
+  /* Convert and promote the target float to E-type.  */
+  e24toe (s, e);
+  /* Output E-type to REAL_VALUE_TYPE.  */
+  PUT_REAL (e, &r);
+  return r;
+}
+
+
 /* Convert a DFmode target `double' value to a REAL_VALUE_TYPE.
-   This is the inverse of the function `etardouble' invoked by
-   REAL_VALUE_TO_TARGET_DOUBLE.
+   This is somewhat like ereal_unto_double, but the input types
+   for these are different.
 
    The DFmode is stored as an array of HOST_WIDE_INT in the target's
    data format, with no holes in the bit packing.  The first element
@@ -5813,21 +6351,22 @@ ereal_from_double (d)
       s[3] = (unsigned EMUSHORT) (d[0] >> 48);
 #endif
     }
-  /* Convert target double to E-type. */
+  /* Convert target double to E-type.  */
   e53toe (s, e);
-  /* Output E-type to REAL_VALUE_TYPE. */
+  /* Output E-type to REAL_VALUE_TYPE.  */
   PUT_REAL (e, &r);
   return r;
 }
 
 
+#if 0
 /* 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 REAL_WORDS_BIG_ENDIAN.  */
 
 static void
 uditoe (di, e)
-     unsigned EMUSHORT *di;  /* Address of the 64-bit int. */
+     unsigned EMUSHORT *di;  /* Address of the 64-bit int.  */
      unsigned EMUSHORT *e;
 {
   unsigned EMUSHORT yi[NI];
@@ -5852,11 +6391,11 @@ uditoe (di, e)
   emovo (yi, e);
 }
 
-/* Convert target computer signed 64-bit integer to e-type. */
+/* Convert target computer signed 64-bit integer to e-type.  */
 
 static void
 ditoe (di, e)
-     unsigned EMUSHORT *di;  /* Address of the 64-bit int. */
+     unsigned EMUSHORT *di;  /* Address of the 64-bit int.  */
      unsigned EMUSHORT *e;
 {
   unsigned EMULONG acc;
@@ -5901,7 +6440,7 @@ ditoe (di, e)
 }
 
 
-/* Convert e-type to unsigned 64-bit int. */
+/* Convert e-type to unsigned 64-bit int.  */
 
 static void 
 etoudi (x, i)
@@ -5984,7 +6523,7 @@ noshift:
 }
 
 
-/* Convert e-type to signed 64-bit int. */
+/* Convert e-type to signed 64-bit int.  */
 
 static void 
 etodi (x, i)
@@ -6082,7 +6621,7 @@ etodi (x, i)
 }
 
 
-/* Longhand square root routine. */
+/* Longhand square root routine.  */
 
 
 static int esqinited = 0;
@@ -6124,7 +6663,7 @@ esqrt (x, y)
       return;
     }
 #endif
-  /* Bring in the arg and renormalize if it is denormal. */
+  /* Bring in the arg and renormalize if it is denormal.  */
   emovi (x, xx);
   m = (EMULONG) xx[1];         /* local long word exponent */
   if (m == 0)
@@ -6153,7 +6692,7 @@ esqrt (x, y)
       /* bring in next word of arg */
       if (j < NE)
        num[NI - 1] = xx[j + 3];
-      /* Do additional bit on last outer loop, for roundoff. */
+      /* Do additional bit on last outer loop, for roundoff.  */
       if (nlups <= 8)
        n = nlups + 1;
       for (i = 0; i < n; i++)
@@ -6179,18 +6718,19 @@ esqrt (x, y)
       j += 1;
     }
 
-  /* Adjust for extra, roundoff loop done. */
+  /* Adjust for extra, roundoff loop done.  */
   exp += (NBITS - 1) - rndprc;
 
-  /* Sticky bit = 1 if the remainder is nonzero. */
+  /* Sticky bit = 1 if the remainder is nonzero.  */
   k = 0;
   for (i = 3; i < NI; i++)
     k |= (int) num[i];
 
-  /* Renormalize and round off. */
+  /* Renormalize and round off.  */
   emdnorm (sq, k, 0, exp, 64);
   emovo (sq, y);
 }
+#endif
 #endif /* EMU_NON_COMPILE not defined */
 \f
 /* Return the binary precision of the significand for a given
@@ -6208,6 +6748,11 @@ significand_size (mode)
 switch (GET_MODE_BITSIZE (mode))
   {
   case 32:
+#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
+    return 56;
+#endif
+
     return 24;
 
   case 64:
@@ -6220,10 +6765,14 @@ switch (GET_MODE_BITSIZE (mode))
 #if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
     return 56;
 #else
+#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
+    return 56;
+#else
     abort ();
 #endif
 #endif
 #endif
+#endif
 
   case 96:
     return 64;