OSDN Git Service

Add fix test from irix_stdio_dummy_va_list
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 31b60cf..087f103 100644 (file)
@@ -1,6 +1,7 @@
 /* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
    and support for XFmode IEEE extended real floating point arithmetic.
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
 
 This file is part of GNU CC.
@@ -17,16 +18,14 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+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"
+#include "tm_p.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).
@@ -44,23 +43,19 @@ The emulator defaults to the host's floating point format so that
 its decimal conversion functions can be used if desired (see
 real.h).
 
-The first part of this file interfaces gcc to ieee.c, which is a
-floating point arithmetic suite that was not written with gcc in
-mind.  The interface is followed by ieee.c itself and related
-items. Avoid changing ieee.c unless you have suitable test
-programs available.  A special version of the PARANOIA floating
-point arithmetic tester, modified for this purpose, can be found
-on usc.edu : /pub/C-numanal/ieeetest.zoo.  Some tutorial
-information on ieee.c is given in my book: S. L. Moshier,
-_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  */
+The first part of this file interfaces gcc to a floating point
+arithmetic suite that was not written with gcc in mind.  Avoid
+changing the low-level arithmetic routines unless you have suitable
+test programs available.  A special version of the PARANOIA floating
+point arithmetic tester, modified for this purpose, can be found on
+usc.edu: /pub/C-numanal/ieeetest.zoo.  Other tests, and libraries of
+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 FLOAT_WORDS_BIG_ENDIAN is non-zero, refers generically
+   `IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically
    to big-endian IEEE floating-point data structure.  This definition
    should work in SFmode `float' type and DFmode `double' type on
    virtually all big-endian IEEE machines.  If LONG_DOUBLE_TYPE_SIZE
@@ -68,7 +63,7 @@ research.att.com: netlib/cephes/ldouble.shar.Z  */
    XFmode (`long double' type) data structure used by the Motorola
    680x0 series processors.
 
-   `IEEE', when FLOAT_WORDS_BIG_ENDIAN is zero, refers generally to
+   `IEEE', when REAL_WORDS_BIG_ENDIAN is zero, refers generally to
    little-endian IEEE machines. In this case, if LONG_DOUBLE_TYPE_SIZE
    has been defined to be 96, then IEEE also invokes the particular
    XFmode `long double' data structure used by the Intel 80x86 series
@@ -83,16 +78,26 @@ research.att.com: netlib/cephes/ldouble.shar.Z  */
    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. Unlike IEEE
+   floats, C4x floats are not rounded to be even. The C4x conversions
+   were contributed by m.hayes@elec.canterbury.ac.nz (Michael Hayes) and
+   Haj.Ten.Brugge@net.HCC.nl (Herman ten Brugge).
+
    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
    support available here is activated by writing
       #define REAL_ARITHMETIC
-   in tm.h. 
+   in tm.h.
 
    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.  Defining INTEL_EXTENDED_IEEE_FORMAT at the same 
+   time enables 80387-style 80-bit floats in a 128-bit padded
+   image, as seen on IA-64.
 
    The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,
    contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,
@@ -120,16 +125,23 @@ research.att.com: netlib/cephes/ldouble.shar.Z  */
 /* 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 */
 
+#define REAL_WORDS_BIG_ENDIAN FLOAT_WORDS_BIG_ENDIAN
+
 #else
 /* REAL_ARITHMETIC not defined means that the *host's* data
    structure will be used.  It may differ by endian-ness from the
@@ -153,16 +165,18 @@ unknown arithmetic type
 #endif /* not IBM */
 #endif /* not VAX */
 
+#define REAL_WORDS_BIG_ENDIAN HOST_FLOAT_WORDS_BIG_ENDIAN
+
 #endif /* REAL_ARITHMETIC not defined */
 
 /* 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
@@ -170,7 +184,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
@@ -192,7 +206,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
@@ -208,10 +222,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
@@ -219,12 +233,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.
@@ -232,56 +246,67 @@ unknown arithmetic type
    A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
    in memory, with no holes.  */
 
-#if LONG_DOUBLE_TYPE_SIZE == 96
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 96 || \
+    (defined(INTEL_EXTENDED_IEEE_FORMAT) && MAX_LONG_DOUBLE_TYPE_SIZE == 128)
 /* Number of 16 bit words in external e type format */
-#define NE 6
-#define MAXDECEXP 4932
-#define MINDECEXP -4956
-#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
-#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
-#else /* no XFmode */
-#if LONG_DOUBLE_TYPE_SIZE == 128
-#define NE 10
-#define MAXDECEXP 4932
-#define MINDECEXP -4977
-#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
-#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
+# define NE 6
+# define MAXDECEXP 4932
+# define MINDECEXP -4956
+# define GET_REAL(r,e)  memcpy ((char *)(e), (char *)(r), 2*NE)
+# define PUT_REAL(e,r)                                         \
+       do {                                                    \
+         memcpy ((char *)(r), (char *)(e), 2*NE);              \
+         if (2*NE < sizeof(*r))                                \
+           memset ((char *)(r) + 2*NE, 0, sizeof(*r) - 2*NE);  \
+       } while (0)
+# else /* no XFmode */
+#  if MAX_LONG_DOUBLE_TYPE_SIZE == 128
+#   define NE 10
+#   define MAXDECEXP 4932
+#   define MINDECEXP -4977
+#   define GET_REAL(r,e) memcpy ((char *)(e), (char *)(r), 2*NE)
+#   define PUT_REAL(e,r)                                       \
+       do {                                                    \
+         memcpy ((char *)(r), (char *)(e), 2*NE);              \
+         if (2*NE < sizeof(*r))                                \
+           memset ((char *)(r) + 2*NE, 0, sizeof(*r) - 2*NE);  \
+       } while (0)
 #else
 #define NE 6
 #define MAXDECEXP 4932
 #define MINDECEXP -4956
 #ifdef REAL_ARITHMETIC
 /* Emulator uses target format internally
-   but host stores it in host endian-ness. */
-
-#define GET_REAL(r,e)                                          \
-do {                                                           \
-     if (HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_WORDS_BIG_ENDIAN)        \
-       e53toe ((unsigned EMUSHORT*) (r), (e));                 \
-     else                                                      \
-       {                                                       \
-        unsigned EMUSHORT w[4];                                \
-        w[3] = ((EMUSHORT *) r)[0];                            \
-        w[2] = ((EMUSHORT *) r)[1];                            \
-        w[1] = ((EMUSHORT *) r)[2];                            \
-        w[0] = ((EMUSHORT *) r)[3];                            \
-        e53toe (w, (e));                                       \
-       }                                                       \
+   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));                                \
+     else                                                              \
+       {                                                               \
+        unsigned EMUSHORT w[4];                                        \
+         memcpy (&w[3], ((EMUSHORT *) r), sizeof (EMUSHORT));          \
+         memcpy (&w[2], ((EMUSHORT *) r) + 1, sizeof (EMUSHORT));      \
+         memcpy (&w[1], ((EMUSHORT *) r) + 2, sizeof (EMUSHORT));      \
+         memcpy (&w[0], ((EMUSHORT *) r) + 3, sizeof (EMUSHORT));      \
+        e53toe (w, (e));                                               \
+       }                                                               \
    } while (0)
 
-#define PUT_REAL(e,r)                                          \
-do {                                                           \
-     if (HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_WORDS_BIG_ENDIAN)        \
-       etoe53 ((e), (unsigned EMUSHORT *) (r));                        \
-     else                                                      \
-       {                                                       \
-        unsigned EMUSHORT w[4];                                \
-        etoe53 ((e), w);                                       \
-        *((EMUSHORT *) r) = w[3];                              \
-        *((EMUSHORT *) r + 1) = w[2];                          \
-        *((EMUSHORT *) r + 2) = w[1];                          \
-        *((EMUSHORT *) r + 3) = w[0];                          \
-       }                                                       \
+#define PUT_REAL(e,r)                                                  \
+do {                                                                   \
+     if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN)         \
+       etoe53 ((e), (unsigned EMUSHORT *) (r));                                \
+     else                                                              \
+       {                                                               \
+        unsigned EMUSHORT w[4];                                        \
+        etoe53 ((e), w);                                               \
+         memcpy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT));          \
+         memcpy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT));      \
+         memcpy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT));      \
+         memcpy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT));      \
+       }                                                               \
    } while (0)
 
 #else /* not REAL_ARITHMETIC */
@@ -292,7 +317,7 @@ do {                                                                \
 
 #endif /* not REAL_ARITHMETIC */
 #endif /* not TFmode */
-#endif /* no XFmode */
+#endif /* not XFmode */
 
 
 /* Number of 16 bit words in internal format */
@@ -315,117 +340,158 @@ do {                                                            \
 /* The exponent of 1.0 */
 #define EXONE (0x3fff)
 
+#if defined(HOST_EBCDIC)
+/* bit 8 is significant in EBCDIC */
+#define CHARMASK 0xff
+#else
+#define CHARMASK 0x7f
+#endif
+
 extern int extra_warnings;
 extern unsigned EMUSHORT ezero[], ehalf[], eone[], etwo[];
 extern unsigned EMUSHORT elog2[], esqrt2[];
 
-static void endian     PROTO((unsigned EMUSHORT *, long *,
+static void endian     PARAMS ((unsigned EMUSHORT *, long *,
                               enum machine_mode));
-static void eclear     PROTO((unsigned EMUSHORT *));
-static void emov       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void eabs       PROTO((unsigned EMUSHORT *));
-static void eneg       PROTO((unsigned EMUSHORT *));
-static int eisneg      PROTO((unsigned EMUSHORT *));
-static int eisinf      PROTO((unsigned EMUSHORT *));
-static int eisnan      PROTO((unsigned EMUSHORT *));
-static void einfin     PROTO((unsigned EMUSHORT *));
-static void enan       PROTO((unsigned EMUSHORT *, int));
-static void emovi      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void emovo      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void ecleaz     PROTO((unsigned EMUSHORT *));
-static void ecleazs    PROTO((unsigned EMUSHORT *));
-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 *));
-static void eiinfin    PROTO((unsigned EMUSHORT *));
-static int eiisinf     PROTO((unsigned EMUSHORT *));
-static int ecmpm       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void eshdn1     PROTO((unsigned EMUSHORT *));
-static void eshup1     PROTO((unsigned EMUSHORT *));
-static void eshdn8     PROTO((unsigned EMUSHORT *));
-static void eshup8     PROTO((unsigned EMUSHORT *));
-static void eshup6     PROTO((unsigned EMUSHORT *));
-static void eshdn6     PROTO((unsigned EMUSHORT *));
-static void eaddm      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));\f
-static void esubm      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void m16m       PROTO((unsigned int, unsigned short *,
+static void eclear     PARAMS ((unsigned EMUSHORT *));
+static void emov       PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#if 0
+static void eabs       PARAMS ((unsigned EMUSHORT *));
+#endif
+static void eneg       PARAMS ((unsigned EMUSHORT *));
+static int eisneg      PARAMS ((unsigned EMUSHORT *));
+static int eisinf      PARAMS ((unsigned EMUSHORT *));
+static int eisnan      PARAMS ((unsigned EMUSHORT *));
+static void einfin     PARAMS ((unsigned EMUSHORT *));
+#ifdef NANS
+static void enan       PARAMS ((unsigned EMUSHORT *, int));
+static void einan      PARAMS ((unsigned EMUSHORT *));
+static int eiisnan     PARAMS ((unsigned EMUSHORT *));
+static int eiisneg     PARAMS ((unsigned EMUSHORT *));
+static void make_nan   PARAMS ((unsigned EMUSHORT *, int, enum machine_mode));
+#endif
+static void emovi      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void emovo      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void ecleaz     PARAMS ((unsigned EMUSHORT *));
+static void ecleazs    PARAMS ((unsigned EMUSHORT *));
+static void emovz      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#if 0
+static void eiinfin    PARAMS ((unsigned EMUSHORT *));
+#endif
+#ifdef INFINITY
+static int eiisinf     PARAMS ((unsigned EMUSHORT *));
+#endif
+static int ecmpm       PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void eshdn1     PARAMS ((unsigned EMUSHORT *));
+static void eshup1     PARAMS ((unsigned EMUSHORT *));
+static void eshdn8     PARAMS ((unsigned EMUSHORT *));
+static void eshup8     PARAMS ((unsigned EMUSHORT *));
+static void eshup6     PARAMS ((unsigned EMUSHORT *));
+static void eshdn6     PARAMS ((unsigned EMUSHORT *));
+static void eaddm      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));\f
+static void esubm      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void m16m       PARAMS ((unsigned int, unsigned short *,
                               unsigned short *));
-static int edivm       PROTO((unsigned short *, unsigned short *));
-static int emulm       PROTO((unsigned short *, unsigned short *));
-static void emdnorm    PROTO((unsigned EMUSHORT *, int, int, EMULONG, int));
-static void esub       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static int edivm       PARAMS ((unsigned short *, unsigned short *));
+static int emulm       PARAMS ((unsigned short *, unsigned short *));
+static void emdnorm    PARAMS ((unsigned EMUSHORT *, int, int, EMULONG, int));
+static void esub       PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
-static void eadd       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void eadd       PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
-static void eadd1      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void eadd1      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
-static void ediv       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void ediv       PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
-static void emul       PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void emul       PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
-static void e53toe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void e64toe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void e113toe    PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void e24toe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe113    PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void toe113     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe64     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void toe64      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe53     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-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 *));
-static void eround     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-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 *,
+static void e53toe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void e64toe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+static void e113toe    PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
+static void e24toe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe113    PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe113     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe64     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe64      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe53     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe53      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe24     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe24      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static int ecmp                PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#if 0
+static void eround     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
+static void ltoe       PARAMS ((HOST_WIDE_INT *, unsigned EMUSHORT *));
+static void ultoe      PARAMS ((unsigned HOST_WIDE_INT *, unsigned EMUSHORT *));
+static void eifrac     PARAMS ((unsigned EMUSHORT *, HOST_WIDE_INT *,
                               unsigned EMUSHORT *));
-static void euifrac    PROTO((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
+static void euifrac    PARAMS ((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
                               unsigned EMUSHORT *));
-static int eshift      PROTO((unsigned EMUSHORT *, int));
-static int enormlz     PROTO((unsigned EMUSHORT *));
-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));
-static void etoasc     PROTO((unsigned EMUSHORT *, char *, int));
-static void asctoe24   PROTO((char *, unsigned EMUSHORT *));
-static void asctoe53   PROTO((char *, unsigned EMUSHORT *));
-static void asctoe64   PROTO((char *, unsigned EMUSHORT *));
-static void asctoe113  PROTO((char *, unsigned EMUSHORT *));
-static void asctoe     PROTO((char *, unsigned EMUSHORT *));
-static void asctoeg    PROTO((char *, unsigned EMUSHORT *, int));
-static void efloor     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void efrexp     PROTO((unsigned EMUSHORT *, int *,
+static int eshift      PARAMS ((unsigned EMUSHORT *, int));
+static int enormlz     PARAMS ((unsigned EMUSHORT *));
+#if 0
+static void e24toasc   PARAMS ((unsigned EMUSHORT *, char *, int));
+static void e53toasc   PARAMS ((unsigned EMUSHORT *, char *, int));
+static void e64toasc   PARAMS ((unsigned EMUSHORT *, char *, int));
+static void e113toasc  PARAMS ((unsigned EMUSHORT *, char *, int));
+#endif /* 0 */
+static void etoasc     PARAMS ((unsigned EMUSHORT *, char *, int));
+static void asctoe24   PARAMS ((const char *, unsigned EMUSHORT *));
+static void asctoe53   PARAMS ((const char *, unsigned EMUSHORT *));
+static void asctoe64   PARAMS ((const char *, unsigned EMUSHORT *));
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+static void asctoe113  PARAMS ((const char *, unsigned EMUSHORT *));
+#endif
+static void asctoe     PARAMS ((const char *, unsigned EMUSHORT *));
+static void asctoeg    PARAMS ((const char *, unsigned EMUSHORT *, int));
+static void efloor     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#if 0
+static void efrexp     PARAMS ((unsigned EMUSHORT *, int *,
                               unsigned EMUSHORT *));
-static void eldexp     PROTO((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
-static void eremain    PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+#endif
+static void eldexp     PARAMS ((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
+#if 0
+static void eremain    PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               unsigned EMUSHORT *));
-static void eiremain   PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void mtherr     PROTO((char *, int));
-static void dectoe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etodec     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void todec      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void ibmtoe     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+#endif
+static void eiremain   PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void mtherr     PARAMS ((const char *, int));
+#ifdef DEC
+static void dectoe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etodec     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void todec      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
+#ifdef IBM
+static void ibmtoe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               enum machine_mode));
-static void etoibm     PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void etoibm     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               enum machine_mode));
-static void toibm      PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void toibm      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
                               enum machine_mode));
-static void make_nan   PROTO((unsigned EMUSHORT *, int, enum machine_mode));
-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
+#ifdef C4X
+static void c4xtoe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
+                              enum machine_mode));
+static void etoc4x     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
+                              enum machine_mode));
+static void toc4x      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
+                              enum machine_mode));
+#endif
+#if 0
+static void uditoe     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void ditoe      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoudi     PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etodi      PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void esqrt      PARAMS ((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
    result is normally passed to fprintf by the ASM_OUTPUT_ macros.   */
 
-static void 
+static void
 endian (e, x, mode)
      unsigned EMUSHORT e[];
      long x[];
@@ -433,21 +499,21 @@ endian (e, x, mode)
 {
   unsigned long th, t;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
       switch (mode)
        {
-
        case TFmode:
-         /* Swap halfwords in the fourth long. */
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+         /* 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;
+#endif
 
        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;
@@ -455,22 +521,20 @@ 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;
-         x[0] = t;
+         x[0] = (long) t;
          break;
 
        default:
@@ -479,21 +543,20 @@ 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. */
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+         /* Pack the fourth long.  */
          th = (unsigned long) e[7] & 0xffff;
          t = (unsigned long) e[6] & 0xffff;
          t |= th << 16;
          x[3] = (long) t;
+#endif
 
        case XFmode:
-
          /* Pack the third long.
             Each element of the input REAL_VALUE_TYPE array has 16 useful bits
             in it.  */
@@ -504,22 +567,20 @@ 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;
-         x[0] = t;
+         x[0] = (long) t;
          break;
 
        default:
@@ -531,7 +592,7 @@ endian (e, x, mode)
 
 /* This is the implementation of the REAL_ARITHMETIC macro.  */
 
-void 
+void
 earith (value, icode, r1, r2)
      REAL_VALUE_TYPE *value;
      int icode;
@@ -544,7 +605,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);
@@ -610,7 +671,7 @@ PUT_REAL (v, value);
 /* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT.
    implements REAL_VALUE_RNDZINT (x) (etrunci (x)).  */
 
-REAL_VALUE_TYPE 
+REAL_VALUE_TYPE
 etrunci (x)
      REAL_VALUE_TYPE x;
 {
@@ -633,7 +694,7 @@ etrunci (x)
 /* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT;
    implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x)).  */
 
-REAL_VALUE_TYPE 
+REAL_VALUE_TYPE
 etruncui (x)
      REAL_VALUE_TYPE x;
 {
@@ -653,13 +714,13 @@ etruncui (x)
 }
 
 
-/* This is the REAL_VALUE_ATOF function.  It converts a decimal string to
-   binary, rounding off as indicated by the machine_mode argument.  Then it
-   promotes the rounded value to REAL_VALUE_TYPE.  */
+/* This is the REAL_VALUE_ATOF function.  It converts a decimal or hexadecimal
+   string to binary, rounding off as indicated by the machine_mode argument.
+   Then it promotes the rounded value to REAL_VALUE_TYPE.  */
 
-REAL_VALUE_TYPE 
+REAL_VALUE_TYPE
 ereal_atof (s, t)
-     char *s;
+     const char *s;
      enum machine_mode t;
 {
   unsigned EMUSHORT tem[NE], e[NE];
@@ -667,23 +728,39 @@ 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:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
       asctoe113 (s, tem);
       e113toe (tem, e);
       break;
+#endif
+      /* FALLTHRU */
+
+    case XFmode:
+      asctoe64 (s, tem);
+      e64toe (tem, e);
+      break;
+
     default:
       asctoe (s, e);
     }
@@ -694,7 +771,7 @@ ereal_atof (s, t)
 
 /* Expansion of REAL_NEGATE.  */
 
-REAL_VALUE_TYPE 
+REAL_VALUE_TYPE
 ereal_negate (x)
      REAL_VALUE_TYPE x;
 {
@@ -756,15 +833,18 @@ efixui (x)
 
 /* REAL_VALUE_FROM_INT macro.  */
 
-void 
-ereal_from_int (d, i, j)
+void
+ereal_from_int (d, i, j, mode)
      REAL_VALUE_TYPE *d;
      HOST_WIDE_INT i, j;
+     enum machine_mode mode;
 {
   unsigned EMUSHORT df[NE], dg[NE];
   HOST_WIDE_INT low, high;
   int sign;
 
+  if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+    abort ();
   sign = 0;
   low = i;
   if ((high = j) < 0)
@@ -784,20 +864,58 @@ ereal_from_int (d, i, j)
   eadd (df, dg, dg);
   if (sign)
     eneg (dg);
+
+  /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
+     Avoid double-rounding errors later by rounding off now from the
+     extra-wide internal format to the requested precision.  */
+  switch (GET_MODE_BITSIZE (mode))
+    {
+    case 32:
+      etoe24 (dg, df);
+      e24toe (df, dg);
+      break;
+
+    case 64:
+      etoe53 (dg, df);
+      e53toe (df, dg);
+      break;
+
+    case 96:
+      etoe64 (dg, df);
+      e64toe (df, dg);
+      break;
+
+    case 128:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+      etoe113 (dg, df);
+      e113toe (df, dg);
+#else
+      etoe64 (dg, df);
+      e64toe (df, dg);
+#endif
+      break;
+
+    default:
+      abort ();
+  }
+
   PUT_REAL (dg, d);
 }
 
 
 /* REAL_VALUE_FROM_UNSIGNED_INT macro.   */
 
-void 
-ereal_from_uint (d, i, j)
+void
+ereal_from_uint (d, i, j, mode)
      REAL_VALUE_TYPE *d;
      unsigned HOST_WIDE_INT i, j;
+     enum machine_mode mode;
 {
   unsigned EMUSHORT df[NE], dg[NE];
   unsigned HOST_WIDE_INT low, high;
 
+  if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+    abort ();
   low = i;
   high = j;
   eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
@@ -805,13 +923,48 @@ ereal_from_uint (d, i, j)
   emul (dg, df, dg);
   ultoe (&low, df);
   eadd (df, dg, dg);
+
+  /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
+     Avoid double-rounding errors later by rounding off now from the
+     extra-wide internal format to the requested precision.  */
+  switch (GET_MODE_BITSIZE (mode))
+    {
+    case 32:
+      etoe24 (dg, df);
+      e24toe (df, dg);
+      break;
+
+    case 64:
+      etoe53 (dg, df);
+      e53toe (df, dg);
+      break;
+
+    case 96:
+      etoe64 (dg, df);
+      e64toe (df, dg);
+      break;
+
+    case 128:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+      etoe113 (dg, df);
+      e113toe (df, dg);
+#else
+      etoe64 (dg, df);
+      e64toe (df, dg);
+#endif
+      break;
+
+    default:
+      abort ();
+  }
+
   PUT_REAL (dg, d);
 }
 
 
 /* REAL_VALUE_TO_INT macro.  */
 
-void 
+void
 ereal_to_int (low, high, rr)
      HOST_WIDE_INT *low, *high;
      REAL_VALUE_TYPE rr;
@@ -878,15 +1031,15 @@ 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)
-     REAL_VALUE_TYPE x;
+     REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
 {
+#ifdef INFINITY
   unsigned EMUSHORT e[NE];
 
-#ifdef INFINITY
   GET_REAL (&x, e);
   return (eisinf (e));
 #else
@@ -894,16 +1047,15 @@ 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)
-     REAL_VALUE_TYPE x;
+     REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
 {
+#ifdef NANS
   unsigned EMUSHORT e[NE];
 
-#ifdef NANS
   GET_REAL (&x, e);
   return (eisnan (e));
 #else
@@ -913,7 +1065,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)
@@ -942,9 +1094,12 @@ real_value_truncate (mode, arg)
   switch (mode)
     {
     case TFmode:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
       etoe113 (e, t);
       e113toe (t, t);
       break;
+#endif
+      /* FALLTHRU */
 
     case XFmode:
       etoe64 (e, t);
@@ -956,12 +1111,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);
@@ -977,6 +1142,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
@@ -990,15 +1217,24 @@ debug_real (r)
 
   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. */
+/* The following routines convert REAL_VALUE_TYPE to the various floating
+   point formats that are meaningful to supported computers.
+
+   The results are returned in 32-bit pieces, each piece stored in a `long'.
+   This is so they can be printed by statements like
+
+      fprintf (file, "%lx, %lx", L[0],  L[1]);
+
+   that will work on both narrow- and wide-word host computers.  */
 
-/* 128-bit long double */
+/* Convert R to a 128-bit long double precision value.  The output array L
+   contains four 32-bit pieces of the result, in the order they would appear
+   in memory.  */
 
-void 
+void
 etartdouble (r, l)
      REAL_VALUE_TYPE r;
      long l[];
@@ -1010,9 +1246,11 @@ etartdouble (r, l)
   endian (e, l, TFmode);
 }
 
-/* 80-bit long double */
+/* Convert R to a double extended precision value.  The output array L
+   contains three 32-bit pieces of the result, in the order they would
+   appear in memory.  */
 
-void 
+void
 etarldouble (r, l)
      REAL_VALUE_TYPE r;
      long l[];
@@ -1024,7 +1262,10 @@ etarldouble (r, l)
   endian (e, l, XFmode);
 }
 
-void 
+/* Convert R to a double precision value.  The output array L contains two
+   32-bit pieces of the result, in the order they would appear in memory.  */
+
+void
 etardouble (r, l)
      REAL_VALUE_TYPE r;
      long l[];
@@ -1036,6 +1277,9 @@ etardouble (r, l)
   endian (e, l, DFmode);
 }
 
+/* Convert R to a single precision float value stored in the least-significant
+   bits of a `long'.  */
+
 long
 etarsingle (r)
      REAL_VALUE_TYPE r;
@@ -1049,6 +1293,11 @@ etarsingle (r)
   return ((long) l);
 }
 
+/* Convert X to a decimal ASCII string S for output to an assembly
+   language file.  Note, there is no standard way to spell infinity or
+   a NaN, so these values may require special treatment in the tm.h
+   macros.  */
+
 void
 ereal_to_decimal (x, s)
      REAL_VALUE_TYPE x;
@@ -1060,6 +1309,9 @@ ereal_to_decimal (x, s)
   etoasc (e, s, 20);
 }
 
+/* Compare X and Y.  Return 1 if X > Y, 0 if X == Y, -1 if X < Y,
+   or -2 if either is a NaN.   */
+
 int
 ereal_cmp (x, y)
      REAL_VALUE_TYPE x, y;
@@ -1071,6 +1323,8 @@ ereal_cmp (x, y)
   return (ecmp (ex, ey));
 }
 
+/*  Return 1 if the sign bit of X is set, else return 0.  */
+
 int
 ereal_isneg (x)
      REAL_VALUE_TYPE x;
@@ -1090,7 +1344,7 @@ ereal_isneg (x)
   short integers.  The arguments of the routines are pointers to
   the arrays.
 
-  External e type data structure, simulates Intel 8087 chip
+  External e type data structure, similar to Intel 8087 chip
   temporary real format but possibly with a larger significand:
 
        NE-1 significand words  (least significant word first,
@@ -1099,7 +1353,7 @@ ereal_isneg (x)
                                top bit is the sign)
 
 
-  Internal data structure of a number (a "word" is 16 bits):
+  Internal exploded e-type data structure of a number (a "word" is 16 bits):
 
   ei[0]        sign word       (0 for positive, 0xffff for negative)
   ei[1]        biased exponent (value = EXONE for the number 1.0)
@@ -1109,11 +1363,11 @@ ereal_isneg (x)
                                 most significant word first,
                                 most significant bit is set)
   ei[NI-1]     low guard word  (0x8000 bit is rounding place)
-               Routines for external format numbers
+
+
+
+               Routines for external format e-type numbers
+
        asctoe (string, e)      ASCII string to extended double e type
        asctoe64 (string, &d)   ASCII string to long double
        asctoe53 (string, &d)   ASCII string to double
@@ -1123,7 +1377,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,
@@ -1138,12 +1394,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
@@ -1154,10 +1414,10 @@ ereal_isneg (x)
        eisinf (e)              1 if e has maximum exponent (non-IEEE)
                                or is infinite (IEEE)
         eisnan (e)              1 if e is a NaN
 
-               Routines for internal format numbers
+
+               Routines for internal format exploded e-type numbers
+
        eaddm (ai, bi)          add significands, bi = bi + ai
        ecleaz (ei)             ei = 0
        ecleazs (ei)            set ei = 0 but leave its sign alone
@@ -1181,19 +1441,21 @@ 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.
 
   Exception flags are NOT fully supported.
+
   Signaling NaN's are NOT supported; they are treated the same
   as quiet NaN's.
+
   Define INFINITY for support of infinity; otherwise a
   saturation arithmetic is implemented.
+
   Define NANS for support of Not-a-Number items; otherwise the
   arithmetic will never produce a NaN output, and might be confused
   by a NaN input.
@@ -1201,7 +1463,7 @@ ereal_isneg (x)
   either a or b is a NaN. This means asking `if (ecmp (a,b) < 0)'
   may not be legitimate. Use `if (ecmp (a,b) == -1)' for `less than'
   if in doubt.
+
   Denormals are always supported here where appropriate (e.g., not
   for conversion to DEC numbers).  */
 
@@ -1214,30 +1476,30 @@ ereal_isneg (x)
   mode, most floating point constants are given as arrays
   of octal integers to eliminate decimal to binary conversion
   errors that might be introduced by the compiler.
+
   For computers, such as IBM PC, that follow the IEEE
   Standard for Binary Floating Point Arithmetic (ANSI/IEEE
-  Std 754-1985), the symbol IBMPC or MIEEE should be defined.
+  Std 754-1985), the symbol IEEE should be defined.
   These numbers have 53-bit significands.  In this mode, constants
   are provided as arrays of hexadecimal 16 bit integers.
-  [This has been changed to instead check the preprocessor macros IEEE
-  and FLOAT_WORDS_BIG_ENDIAN].
+  The endian-ness of generated values is controlled by
+  REAL_WORDS_BIG_ENDIAN.
+
   To accommodate other types of computer arithmetic, all
   constants are also provided in a normal decimal radix
   which one can hope are correctly converted to a suitable
   format by the available C language compiler.  To invoke
   this mode, the symbol UNK is defined.
+
   An important difference among these modes is a predefined
   set of machine arithmetic constants for each.  The numbers
   MACHEP (the machine roundoff error), MAXNUM (largest number
   represented), and several other parameters are preset by
   the configuration symbol.  Check the file const.c to
   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.  */
 
@@ -1251,7 +1513,7 @@ ereal_isneg (x)
 
 /*  e type constants used by high precision check routines */
 
-#if LONG_DOUBLE_TYPE_SIZE == 128
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !defined(INTEL_EXTENDED_IEEE_FORMAT)
 /* 0.0 */
 unsigned EMUSHORT ezero[NE] =
  {0x0000, 0x0000, 0x0000, 0x0000,
@@ -1320,17 +1582,15 @@ unsigned EMUSHORT epi[NE] =
  {0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
 #endif
 
-
-
 /* Control register for rounding precision.
    This can be set to 113 (if NE=10), 80 (if NE=6), 64, 56, 53, or 24 bits.  */
 
 int rndprc = NBITS;
 extern int rndprc;
 
-/*  Clear out entire external format number.  */
+/*  Clear out entire e-type number X.  */
 
-static void 
+static void
 eclear (x)
      register unsigned EMUSHORT *x;
 {
@@ -1340,11 +1600,9 @@ eclear (x)
     *x++ = 0;
 }
 
+/* Move e-type number from A to B.  */
 
-
-/* Move external format number from a to b.  */
-
-static void 
+static void
 emov (a, b)
      register unsigned EMUSHORT *a, *b;
 {
@@ -1355,19 +1613,21 @@ emov (a, b)
 }
 
 
-/* Absolute value of external format number.  */
+#if 0
+/* Absolute value of e-type X.  */
 
-static void 
+static void
 eabs (x)
      unsigned EMUSHORT x[];
 {
   /* sign is top bit of last word of external format */
-  x[NE - 1] &= 0x7fff;         
+  x[NE - 1] &= 0x7fff;
 }
+#endif /* 0 */
 
-/* Negate external format number.  */
+/* Negate the e-type number X.  */
 
-static void 
+static void
 eneg (x)
      unsigned EMUSHORT x[];
 {
@@ -1375,11 +1635,9 @@ eneg (x)
   x[NE - 1] ^= 0x8000;         /* Toggle the sign bit */
 }
 
+/* Return 1 if sign bit of e-type number X is nonzero, else zero.  */
 
-
-/* Return 1 if sign bit of external format number is nonzero, else zero.  */
-
-static int 
+static int
 eisneg (x)
      unsigned EMUSHORT x[];
 {
@@ -1390,10 +1648,9 @@ eisneg (x)
     return (0);
 }
 
+/* Return 1 if e-type number X is infinity, else return zero.  */
 
-/* Return 1 if external format number is infinity, else return zero.  */
-
-static int 
+static int
 eisinf (x)
      unsigned EMUSHORT x[];
 {
@@ -1408,13 +1665,12 @@ eisinf (x)
     return (0);
 }
 
-
 /* Check if e-type number is not a number.  The bit pattern is one that we
    defined, so we know for sure how to detect it.  */
 
-static int 
+static int
 eisnan (x)
-     unsigned EMUSHORT x[];
+     unsigned EMUSHORT x[] ATTRIBUTE_UNUSED;
 {
 #ifdef NANS
   int i;
@@ -1422,7 +1678,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)
@@ -1433,10 +1689,10 @@ eisnan (x)
   return (0);
 }
 
-/*  Fill external format number with infinity pattern (IEEE)
-    or largest possible number (non-IEEE). */
+/*  Fill e-type number X with infinity pattern (IEEE)
+    or largest possible number (non-IEEE).  */
 
-static void 
+static void
 einfin (x)
      register unsigned EMUSHORT *x;
 {
@@ -1475,12 +1731,12 @@ einfin (x)
 #endif
 }
 
-
 /* Output an e-type NaN.
    This generates Intel's quiet NaN pattern for extended real.
    The exponent is 7fff, the leading mantissa word is c000.  */
 
-static void 
+#ifdef NANS
+static void
 enan (x, sign)
      register unsigned EMUSHORT *x;
      int sign;
@@ -1492,11 +1748,11 @@ enan (x, sign)
   *x++ = 0xc000;
   *x = (sign << 15) | 0x7fff;
 }
+#endif /* NANS */
 
+/* Move in an e-type number A, converting it to exploded e-type B.  */
 
-/* Move in external format number, converting it to internal format.  */
-
-static void 
+static void
 emovi (a, b)
      unsigned EMUSHORT *a, *b;
 {
@@ -1541,10 +1797,9 @@ emovi (a, b)
   *q = 0;
 }
 
+/* Move out exploded e-type number A, converting it to e type B.  */
 
-/* Move internal format number out, converting it to external format.  */
-
-static void 
+static void
 emovo (a, b)
      unsigned EMUSHORT *a, *b;
 {
@@ -1581,9 +1836,9 @@ emovo (a, b)
     *q-- = *p++;
 }
 
-/* Clear out internal format number.  */
+/* Clear out exploded e-type number XI.  */
 
-static void 
+static void
 ecleaz (xi)
      register unsigned EMUSHORT *xi;
 {
@@ -1593,10 +1848,9 @@ ecleaz (xi)
     *xi++ = 0;
 }
 
+/* Clear out exploded e-type XI, but don't touch the sign.  */
 
-/* Same, but don't touch the sign. */
-
-static void 
+static void
 ecleazs (xi)
      register unsigned EMUSHORT *xi;
 {
@@ -1607,11 +1861,9 @@ ecleazs (xi)
     *xi++ = 0;
 }
 
+/* Move exploded e-type number from A to B.  */
 
-
-/* Move internal format number from a to b.  */
-
-static void 
+static void
 emovz (a, b)
      register unsigned EMUSHORT *a, *b;
 {
@@ -1623,10 +1875,11 @@ emovz (a, b)
   *b = 0;
 }
 
-/* Generate internal format NaN.
+/* Generate exploded e-type NaN.
    The explicit pattern for this is maximum exponent and
    top two significant bits set.  */
 
+#ifdef NANS
 static void
 einan (x)
      unsigned EMUSHORT x[];
@@ -1636,10 +1889,12 @@ einan (x)
   x[E] = 0x7fff;
   x[M + 1] = 0xc000;
 }
+#endif /* NANS */
 
-/* Return nonzero if internal format number is a NaN. */
+/* Return nonzero if exploded e-type X is a NaN.  */
 
-static int 
+#ifdef NANS
+static int
 eiisnan (x)
      unsigned EMUSHORT x[];
 {
@@ -1655,18 +1910,22 @@ eiisnan (x)
     }
   return (0);
 }
+#endif /* NANS */
 
-/* Return nonzero if sign of internal format number is nonzero.  */
+/* Return nonzero if sign of exploded e-type X is nonzero.  */
 
-static int 
+#ifdef NANS
+static int
 eiisneg (x)
      unsigned EMUSHORT x[];
 {
 
   return x[0] != 0;
 }
+#endif /* NANS */
 
-/* Fill internal format number with infinity pattern.
+#if 0
+/* Fill exploded e-type X with infinity pattern.
    This has maximum exponent and significand all zeros.  */
 
 static void
@@ -1677,10 +1936,12 @@ eiinfin (x)
   ecleaz (x);
   x[E] = 0x7fff;
 }
+#endif /* 0 */
 
-/* Return nonzero if internal format number is infinite. */
+/* Return nonzero if exploded e-type X is infinite.  */
 
-static int 
+#ifdef INFINITY
+static int
 eiisinf (x)
      unsigned EMUSHORT x[];
 {
@@ -1693,9 +1954,9 @@ eiisinf (x)
     return (1);
   return (0);
 }
+#endif /* INFINITY */
 
-
-/* Compare significands of numbers in internal format.
+/* Compare significands of numbers in internal exploded e-type format.
    Guard words are included in the comparison.
 
    Returns     +1 if a > b
@@ -1724,10 +1985,9 @@ ecmpm (a, b)
     return (-1);
 }
 
+/* Shift significand of exploded e-type X down by 1 bit.  */
 
-/* Shift significand down by 1 bit.  */
-
-static void 
+static void
 eshdn1 (x)
      register unsigned EMUSHORT *x;
 {
@@ -1749,11 +2009,9 @@ eshdn1 (x)
     }
 }
 
+/* Shift significand of exploded e-type X up by 1 bit.  */
 
-
-/* Shift significand up by 1 bit.  */
-
-static void 
+static void
 eshup1 (x)
      register unsigned EMUSHORT *x;
 {
@@ -1776,9 +2034,9 @@ eshup1 (x)
 }
 
 
-/* Shift significand down by 8 bits.  */
+/* Shift significand of exploded e-type X down by 8 bits.  */
 
-static void 
+static void
 eshdn8 (x)
      register unsigned EMUSHORT *x;
 {
@@ -1797,9 +2055,9 @@ eshdn8 (x)
     }
 }
 
-/* Shift significand up by 8 bits.  */
+/* Shift significand of exploded e-type X up by 8 bits.  */
 
-static void 
+static void
 eshup8 (x)
      register unsigned EMUSHORT *x;
 {
@@ -1819,9 +2077,9 @@ eshup8 (x)
     }
 }
 
-/* Shift significand up by 16 bits.  */
+/* Shift significand of exploded e-type X up by 16 bits.  */
 
-static void 
+static void
 eshup6 (x)
      register unsigned EMUSHORT *x;
 {
@@ -1837,9 +2095,9 @@ eshup6 (x)
   *p = 0;
 }
 
-/* Shift significand down by 16 bits.  */
+/* Shift significand of exploded e-type X down by 16 bits.  */
 
-static void 
+static void
 eshdn6 (x)
      register unsigned EMUSHORT *x;
 {
@@ -1854,10 +2112,10 @@ eshdn6 (x)
 
   *(--p) = 0;
 }
-\f
-/* Add significands.  x + y replaces y.  */
 
-static void 
+/* Add significands of exploded e-type X and Y.  X + Y replaces Y.  */
+
+static void
 eaddm (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -1881,9 +2139,9 @@ eaddm (x, y)
     }
 }
 
-/* Subtract significands.  y - x replaces y.  */
+/* Subtract significands of exploded e-type X and Y.  Y - X replaces Y.  */
 
-static void 
+static void
 esubm (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -1917,7 +2175,7 @@ static unsigned EMUSHORT equot[NI];
 
 /* Divide significands */
 
-int 
+int
 edivm (den, num)
      unsigned EMUSHORT den[], num[];
 {
@@ -2014,7 +2272,8 @@ edivm (den, num)
 
 
 /* Multiply significands */
-int 
+
+int
 emulm (a, b)
      unsigned EMUSHORT a[], b[];
 {
@@ -2061,22 +2320,21 @@ emulm (a, b)
 
 #else
 
-/* Radix 65536 versions of multiply and divide  */
+/* Radix 65536 versions of multiply and divide.  */
 
-
-/* Multiply significand of e-type number b
-   by 16-bit quantity a, e-type result to c. */
+/* Multiply significand of e-type number B
+   by 16-bit quantity A, return e-type result to C.  */
 
 static void
 m16m (a, b, c)
      unsigned int a;
-     unsigned short b[], c[];
+     unsigned EMUSHORT b[], c[];
 {
-  register unsigned short *pp;
-  register unsigned long carry;
-  unsigned short *ps;
-  unsigned short p[NI];
-  unsigned long aa, m;
+  register unsigned EMUSHORT *pp;
+  register unsigned EMULONG carry;
+  unsigned EMUSHORT *ps;
+  unsigned EMUSHORT p[NI];
+  unsigned EMULONG aa, m;
   int i;
 
   aa = a;
@@ -2095,11 +2353,11 @@ m16m (a, b, c)
        }
       else
        {
-         m = (unsigned long) aa * *ps--;
+         m = (unsigned EMULONG) aa * *ps--;
          carry = (m & 0xffff) + *pp;
-         *pp-- = (unsigned short)carry;
+         *pp-- = (unsigned EMUSHORT)carry;
          carry = (carry >> 16) + (m >> 16) + *pp;
-         *pp = (unsigned short)carry;
+         *pp = (unsigned EMUSHORT)carry;
          *(pp-1) = carry >> 16;
        }
     }
@@ -2107,19 +2365,19 @@ m16m (a, b, c)
     c[i] = p[i];
 }
 
-
-/* Divide significands. Neither the numerator nor the denominator
-   is permitted to have its high guard word nonzero.  */
+/* Divide significands of exploded e-types NUM / DEN.  Neither the
+   numerator NUM nor the denominator DEN is permitted to have its high guard
+   word nonzero.  */
 
 static int
 edivm (den, num)
-     unsigned short den[], num[];
+     unsigned EMUSHORT den[], num[];
 {
   int i;
-  register unsigned short *p;
-  unsigned long tnum;
-  unsigned short j, tdenm, tquot;
-  unsigned short tprod[NI+1];
+  register unsigned EMUSHORT *p;
+  unsigned EMULONG tnum;
+  unsigned EMUSHORT j, tdenm, tquot;
+  unsigned EMUSHORT tprod[NI+1];
 
   p = &equot[0];
   *p++ = num[0];
@@ -2133,17 +2391,17 @@ edivm (den, 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];
+      /* 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. */
-      if ((tdenm * 0xffffL) < tnum)
+      /* Do not execute the divide instruction if it will overflow.  */
+      if ((tdenm * (unsigned long)0xffff) < 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;
@@ -2174,16 +2432,15 @@ edivm (den, num)
   return ((int)j);
 }
 
+/* Multiply significands of exploded e-type A and B, result in B.  */
 
-
-/* Multiply significands */
 static int
 emulm (a, b)
-     unsigned short a[], b[];
+     unsigned EMUSHORT a[], b[];
 {
-  unsigned short *p, *q;
-  unsigned short pprod[NI];
-  unsigned short j;
+  unsigned EMUSHORT *p, *q;
+  unsigned EMUSHORT pprod[NI];
+  unsigned EMUSHORT j;
   int i;
 
   equot[0] = b[0];
@@ -2220,26 +2477,26 @@ emulm (a, b)
 
 /* Normalize and round off.
 
-  The internal format number to be rounded is "s".
-  Input "lost" indicates whether or not the number is exact.
-  This is the so-called sticky bit.
-  Input "subflg" indicates whether the number was obtained
-  by a subtraction operation.  In that case if lost is nonzero
+  The internal format number to be rounded is S.
+  Input LOST is 0 if the value is exact.  This is the so-called sticky bit.
+
+  Input SUBFLG indicates whether the number was obtained
+  by a subtraction operation.  In that case if LOST is nonzero
   then the number is slightly smaller than indicated.
-  Input "exp" is the biased exponent, which may be negative.
-  the exponent field of "s" is ignored but is replaced by
-  "exp" as adjusted by normalization and rounding.
-  Input "rcntrl" is the rounding control.
+
+  Input EXP is the biased exponent, which may be negative.
+  the exponent field of S is ignored but is replaced by
+  EXP as adjusted by normalization and rounding.
+
+  Input RCNTRL is the rounding control.  If it is nonzero, the
+  returned value will be rounded to RNDPRC bits.
 
   For future reference:  In order for emdnorm to round off denormal
    significands at the right point, the input exponent must be
    adjusted to be the actual value it would have after conversion to
    the final floating point type.  This adjustment has been
    implemented for all type conversions (etoe53, etc.) and decimal
-   conversions, but not for the arithmetic functions (eadd, etc.). 
+   conversions, but not for the arithmetic functions (eadd, etc.).
    Data types having standard 15-bit exponents are not affected by
    this, but SFmode and DFmode are affected. For example, ediv with
    rndprc = 24 will not round correctly to 24-bit precision if the
@@ -2253,7 +2510,7 @@ static unsigned EMUSHORT rebit = 0;
 static int re = 0;
 static unsigned EMUSHORT rbit[NI];
 
-static void 
+static void
 emdnorm (s, lost, subflg, exp, rcntrl)
      unsigned EMUSHORT s[];
      int lost;
@@ -2267,7 +2524,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)
     {
@@ -2301,10 +2558,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);
@@ -2318,6 +2575,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          re = rw - 1;
          rebit = 1;
          break;
+
        case 113:
          rw = 10;
          rmsk = 0x7fff;
@@ -2325,6 +2583,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          rebit = 0x8000;
          re = rw;
          break;
+
        case 64:
          rw = 7;
          rmsk = 0xffff;
@@ -2332,6 +2591,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          re = rw - 1;
          rebit = 1;
          break;
+
          /* For DEC or IBM arithmetic */
        case 56:
          rw = 6;
@@ -2340,6 +2600,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
          rebit = 0x100;
          re = rw;
          break;
+
        case 53:
          rw = 6;
          rmsk = 0x7ff;
@@ -2347,6 +2608,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;
@@ -2360,8 +2631,10 @@ emdnorm (s, lost, subflg, exp, rcntrl)
     }
 
   /* Shift down 1 temporarily if the data structure has an implied
-     most significant bit and the number is denormal.  */
-  if ((exp <= 0) && (rndprc != 64) && (rndprc != NBITS))
+     most significant bit and the number is denormal.
+     Intel long double denormals also lose one bit of precision.  */
+  if ((exp <= 0) && (rndprc != NBITS)
+      && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
     {
       lost |= s[NI - 1] & 1;
       eshdn1 (s);
@@ -2383,6 +2656,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
   s[rw] &= ~rmsk;
   if ((r & rmbit) != 0)
     {
+#ifndef C4X
       if (r == rmbit)
        {
          if (lost == 0)
@@ -2396,10 +2670,13 @@ emdnorm (s, lost, subflg, exp, rcntrl)
                goto mddone;
            }
        }
+#endif
       eaddm (rbit, s);
     }
  mddone:
-  if ((exp <= 0) && (rndprc != 64) && (rndprc != NBITS))
+/* Undo the temporary shift for denormal values.  */
+  if ((exp <= 0) && (rndprc != NBITS)
+      && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
     {
       eshup1 (s);
     }
@@ -2445,13 +2722,11 @@ emdnorm (s, lost, subflg, exp, rcntrl)
     s[1] = (unsigned EMUSHORT) exp;
 }
 
-
-
-/*  Subtract external format numbers.  */
+/*  Subtract.  C = B - A, all e type numbers.  */
 
 static int subflg = 0;
 
-static void 
+static void
 esub (a, b, c)
      unsigned EMUSHORT *a, *b, *c;
 {
@@ -2468,7 +2743,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))
     {
@@ -2481,16 +2756,15 @@ esub (a, b, c)
   eadd1 (a, b, c);
 }
 
+/* Add.  C = A + B, all e type.  */
 
-/* Add.  */
-
-static void 
+static void
 eadd (a, b, c)
      unsigned EMUSHORT *a, *b, *c;
 {
 
 #ifdef NANS
-/* NaN plus anything is a NaN. */
+/* NaN plus anything is a NaN.  */
   if (eisnan (a))
     {
       emov (a, c);
@@ -2502,7 +2776,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))
     {
@@ -2515,7 +2789,9 @@ eadd (a, b, c)
   eadd1 (a, b, c);
 }
 
-static void 
+/* Arithmetic common to both addition and subtraction.  */
+
+static void
 eadd1 (a, b, c)
      unsigned EMUSHORT *a, *b, *c;
 {
@@ -2575,7 +2851,7 @@ eadd1 (a, b, c)
              return;
            }
          /* if same sign, result is double */
-         /* double denomalized tiny number */
+         /* double denormalized tiny number */
          if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
            {
              eshup1 (bi);
@@ -2586,8 +2862,15 @@ eadd1 (a, b, c)
            {
              if (bi[j] != 0)
                {
-                 /* This could overflow, but let emovo take care of that. */
                  ltb += 1;
+                 if (ltb >= 0x7fff)
+                   {
+                     eclear (c);
+                     if (ai[0] != 0)
+                       eneg (c);
+                     einfin (c);
+                     return;
+                   }
                  break;
                }
            }
@@ -2617,20 +2900,22 @@ eadd1 (a, b, c)
   emovo (bi, c);
 }
 
+/* Divide: C = B/A, all e type.  */
 
-
-/* Divide.  */
-
-static void 
+static void
 ediv (a, b, c)
      unsigned EMUSHORT *a, *b, *c;
 {
   unsigned EMUSHORT ai[NI], bi[NI];
-  int i;
+  int i, sign;
   EMULONG lt, lta, ltb;
 
+/* IEEE says if result is not a NaN, the sign is "-" if and only if
+   operands have opposite signs -- but flush -0 to 0 later if not IEEE.  */
+  sign = eisneg(a) ^ eisneg(b);
+
 #ifdef NANS
-/* Return any NaN input. */
+/* Return any NaN input.  */
   if (eisnan (a))
     {
     emov (a, c);
@@ -2641,31 +2926,27 @@ 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)))
     {
     mtherr ("ediv", INVALID);
-    enan (c, eisneg (a) ^ eisneg (b));
+    enan (c, sign);
     return;
     }
 #endif
-/* Infinity over anything else is infinity. */
+/* Infinity over anything else is infinity.  */
 #ifdef INFINITY
   if (eisinf (b))
     {
-      if (eisneg (a) ^ eisneg (b))
-       *(c + (NE - 1)) = 0x8000;
-      else
-       *(c + (NE - 1)) = 0;
       einfin (c);
-      return;
+      goto divsign;
     }
-/* Anything else over infinity is zero. */
+/* Anything else over infinity is zero.  */
   if (eisinf (a))
     {
       eclear (c);
-      return;
+      goto divsign;
     }
 #endif
   emovi (a, ai);
@@ -2673,7 +2954,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)
@@ -2683,7 +2964,7 @@ ediv (a, b, c)
            }
        }
       eclear (c);
-      return;
+      goto divsign;
     }
  dnzro1:
 
@@ -2697,15 +2978,11 @@ ediv (a, b, c)
              goto dnzro2;
            }
        }
-      if (ai[0] == bi[0])
-       *(c + (NE - 1)) = 0;
-      else
-       *(c + (NE - 1)) = 0x8000;
 /* Divide by zero is not an invalid operation.
    It is a divide-by-zero operation!   */
       einfin (c);
       mtherr ("ediv", SING);
-      return;
+      goto divsign;
     }
  dnzro2:
 
@@ -2713,28 +2990,36 @@ ediv (a, b, c)
   /* calculate exponent */
   lt = ltb - lta + EXONE;
   emdnorm (bi, i, 0, lt, 64);
-  /* set the sign */
-  if (ai[0] == bi[0])
-    bi[0] = 0;
-  else
-    bi[0] = 0Xffff;
   emovo (bi, c);
-}
 
+ divsign:
 
+  if (sign
+#ifndef IEEE
+      && (ecmp (c, ezero) != 0)
+#endif
+      )
+     *(c+(NE-1)) |= 0x8000;
+  else
+     *(c+(NE-1)) &= ~0x8000;
+}
 
-/* Multiply.  */
+/* Multiply e-types A and B, return e-type product C.   */
 
-static void 
+static void
 emul (a, b, c)
      unsigned EMUSHORT *a, *b, *c;
 {
   unsigned EMUSHORT ai[NI], bi[NI];
-  int i, j;
+  int i, j, sign;
   EMULONG lt, lta, ltb;
 
+/* IEEE says if result is not a NaN, the sign is "-" if and only if
+   operands have opposite signs -- but flush -0 to 0 later if not IEEE.  */
+  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);
@@ -2745,25 +3030,21 @@ 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)))
     {
     mtherr ("emul", INVALID);
-    enan (c, eisneg (a) ^ eisneg (b));
+    enan (c, sign);
     return;
     }
 #endif
-/* Infinity times anything else is infinity. */
+/* Infinity times anything else is infinity.  */
 #ifdef INFINITY
   if (eisinf (a) || eisinf (b))
     {
-      if (eisneg (a) ^ eisneg (b))
-       *(c + (NE - 1)) = 0x8000;
-      else
-       *(c + (NE - 1)) = 0;
       einfin (c);
-      return;
+      goto mulsign;
     }
 #endif
   emovi (a, ai);
@@ -2781,7 +3062,7 @@ emul (a, b, c)
            }
        }
       eclear (c);
-      return;
+      goto mulsign;
     }
  mnzer1:
 
@@ -2796,7 +3077,7 @@ emul (a, b, c)
            }
        }
       eclear (c);
-      return;
+      goto mulsign;
     }
  mnzer2:
 
@@ -2805,18 +3086,21 @@ emul (a, b, c)
   /* calculate exponent */
   lt = lta + ltb - (EXONE - 1);
   emdnorm (bi, j, 0, lt, 64);
-  /* calculate sign of product */
-  if (ai[0] == bi[0])
-    bi[0] = 0;
-  else
-    bi[0] = 0xffff;
   emovo (bi, c);
-}
-
 
+ mulsign:
 
+  if (sign
+#ifndef IEEE
+      && (ecmp (c, ezero) != 0)
+#endif
+      )
+     *(c+(NE-1)) |= 0x8000;
+  else
+     *(c+(NE-1)) &= ~0x8000;
+}
 
-/* Convert IEEE double precision to e type.  */
+/* Convert double precision PE to e-type Y.  */
 
 static void
 e53toe (pe, y)
@@ -2824,7 +3108,7 @@ e53toe (pe, y)
 {
 #ifdef DEC
 
-  dectoe (pe, y);              /* see etodec.c */
+  dectoe (pe, y);
 
 #else
 #ifdef IBM
@@ -2832,6 +3116,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];
@@ -2840,7 +3129,7 @@ e53toe (pe, y)
   e = pe;
   denorm = 0;                  /* flag if denormalized number */
   ecleaz (yy);
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     e += 3;
   r = *e;
   yy[0] = 0;
@@ -2852,7 +3141,7 @@ e53toe (pe, y)
   if (r == 0x7ff0)
     {
 #ifdef NANS
-      if (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        {
          if (((pe[3] & 0xf) != 0) || (pe[2] != 0)
              || (pe[1] != 0) || (pe[0] != 0))
@@ -2880,7 +3169,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)
     {
@@ -2891,7 +3180,7 @@ e53toe (pe, y)
   yy[E] = r;
   p = &yy[M + 1];
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     {
       *p++ = *(--e);
       *p++ = *(--e);
@@ -2907,18 +3196,22 @@ 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 */
 }
 
-static void 
+/* Convert double extended precision float PE to e type Y.  */
+
+static void
 e64toe (pe, y)
      unsigned EMUSHORT *pe, *y;
 {
@@ -2930,7 +3223,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++;
@@ -2943,16 +3236,35 @@ e64toe (pe, y)
     *p-- = *e++;
 #endif
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     {
       for (i = 0; i < 5; i++)
        *p++ = *e++;
+
+      /* For denormal long double Intel format, shift significand up one
+        -- but only if the top significand bit is zero.  A top bit of 1
+        is "pseudodenormal" when the exponent is zero.  */
+      if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
+       {
+         unsigned EMUSHORT temp[NI];
+
+         emovi(yy, temp);
+         eshup1(temp);
+         emovo(temp,y);
+         return;
+       }
     }
   else
     {
       p = &yy[0] + (NE - 1);
+#ifdef ARM_EXTENDED_IEEE_FORMAT
+      /* For ARMs, the exponent is in the lowest 15 bits of the word.  */
+      *p-- = (e[0] & 0x8000) | (e[1] & 0x7ffff);
+      e += 2;
+#else
       *p-- = *e++;
       ++e;
+#endif
       for (i = 0; i < 4; i++)
        *p-- = *e++;
     }
@@ -2960,10 +3272,10 @@ e64toe (pe, y)
 #ifdef INFINITY
   /* Point to the exponent field and check max exponent cases.  */
   p = &yy[NE - 1];
-  if (*p == 0x7fff)
+  if ((*p & 0x7fff) == 0x7fff)
     {
 #ifdef NANS
-      if (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        {
          for (i = 0; i < 4; i++)
            {
@@ -2978,14 +3290,32 @@ e64toe (pe, y)
        }
       else
        {
-         for (i = 1; i <= 4; i++)
+#ifdef ARM_EXTENDED_IEEE_FORMAT
+         for (i = 2; i <= 5; i++)
+           {
+             if (pe[i] != 0)
+               {
+                 enan (y, (*p & 0x8000) != 0);
+                 return;
+               }
+           }
+#else /* not ARM */
+         /* In Motorola extended precision format, the most significant
+            bit of an infinity mantissa could be either 1 or 0.  It is
+            the lower order bits that tell whether the value is a NaN.  */
+         if ((pe[2] & 0x7fff) != 0)
+           goto bigend_nan;
+
+         for (i = 3; i <= 5; i++)
            {
              if (pe[i] != 0)
                {
+bigend_nan:
                  enan (y, (*p & 0x8000) != 0);
                  return;
                }
            }
+#endif /* not ARM */
        }
 #endif /* NANS */
       eclear (y);
@@ -3001,8 +3331,10 @@ e64toe (pe, y)
     *q++ = *p++;
 }
 
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+/* Convert 128-bit long double precision float PE to e type Y.  */
 
-static void 
+static void
 e113toe (pe, y)
      unsigned EMUSHORT *pe, *y;
 {
@@ -3015,7 +3347,7 @@ e113toe (pe, y)
   denorm = 0;
   ecleaz (yy);
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     e += 7;
 #endif
   r = *e;
@@ -3027,7 +3359,7 @@ e113toe (pe, y)
   if (r == 0x7fff)
     {
 #ifdef NANS
-      if (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        {
          for (i = 0; i < 7; i++)
            {
@@ -3060,7 +3392,7 @@ e113toe (pe, y)
   yy[E] = r;
   p = &yy[M + 1];
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     {
       for (i = 0; i < 7; i++)
        *p++ = *(--e);
@@ -3072,7 +3404,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;
@@ -3084,11 +3416,11 @@ e113toe (pe, y)
     }
   emovo (yy, y);
 }
+#endif
 
+/* Convert single precision float PE to e type Y.  */
 
-/* Convert IEEE single precision to e type.  */
-
-static void 
+static void
 e24toe (pe, y)
      unsigned EMUSHORT *pe, *y;
 {
@@ -3097,6 +3429,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];
@@ -3106,7 +3445,7 @@ e24toe (pe, y)
   denorm = 0;                  /* flag if denormalized number */
   ecleaz (yy);
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     e += 1;
 #endif
 #ifdef DEC
@@ -3122,7 +3461,7 @@ e24toe (pe, y)
   if (r == 0x7f80)
     {
 #ifdef NANS
-      if (FLOAT_WORDS_BIG_ENDIAN)
+      if (REAL_WORDS_BIG_ENDIAN)
        {
          if (((pe[0] & 0x7f) != 0) || (pe[1] != 0))
            {
@@ -3148,7 +3487,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;
@@ -3161,7 +3500,7 @@ e24toe (pe, y)
   *p++ = *(--e);
 #endif
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     *p++ = *(--e);
   else
     {
@@ -3178,11 +3517,13 @@ e24toe (pe, y)
        yy[E] -= (unsigned EMUSHORT) (k - 1);
     }
   emovo (yy, y);
+#endif /* not C4X */
 #endif /* not IBM */
 }
 
+/* Convert e-type X to IEEE 128-bit long double format E.  */
 
-static void 
+static void
 etoe113 (x, e)
      unsigned EMUSHORT *x, *e;
 {
@@ -3208,13 +3549,16 @@ etoe113 (x, e)
   rndprc = 113;
   emdnorm (xi, 0, 0, exp, 64);
   rndprc = rndsav;
+#ifdef INFINITY
  nonorm:
+#endif
   toe113 (xi, e);
 }
 
-/* Move out internal format to ieee long double */
+/* Convert exploded e-type X, that has already been rounded to
+   113-bit precision, to IEEE 128-bit long double format Y.  */
 
-static void 
+static void
 toe113 (a, b)
      unsigned EMUSHORT *a, *b;
 {
@@ -3229,19 +3573,19 @@ toe113 (a, b)
     }
 #endif
   p = a;
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     q = 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);
     }
   /* combine sign and exponent */
   i = *p++;
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
       if (i)
        *q++ = *p++ | 0x8000;
@@ -3258,7 +3602,7 @@ toe113 (a, b)
   /* skip over guard word */
   ++p;
   /* move the significand */
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
       for (i = 0; i < 7; i++)
        *q++ = *p++;
@@ -3270,7 +3614,9 @@ toe113 (a, b)
     }
 }
 
-static void 
+/* Convert e-type X to IEEE double extended format E.  */
+
+static void
 etoe64 (x, e)
      unsigned EMUSHORT *x, *e;
 {
@@ -3297,14 +3643,16 @@ etoe64 (x, e)
   rndprc = 64;
   emdnorm (xi, 0, 0, exp, 64);
   rndprc = rndsav;
+#ifdef INFINITY
  nonorm:
+#endif
   toe64 (xi, e);
 }
 
+/* Convert exploded e-type X, that has already been rounded to
+   64-bit precision, to IEEE double extended format Y.  */
 
-/* Move out internal format to ieee long double. */
-
-static void 
+static void
 toe64 (a, b)
      unsigned EMUSHORT *a, *b;
 {
@@ -3318,6 +3666,9 @@ toe64 (a, b)
       return;
     }
 #endif
+  /* Shift denormal long double Intel format significand down one bit.  */
+  if ((a[E] == 0) && ! REAL_WORDS_BIG_ENDIAN)
+    eshdn1 (a);
   p = a;
 #ifdef IBM
   q = b;
@@ -3326,15 +3677,16 @@ toe64 (a, b)
   q = b + 4;
 #endif
 #ifdef IEEE
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     q = b;
   else
     {
       q = b + 4;                       /* point to output exponent */
-#if LONG_DOUBLE_TYPE_SIZE == 96
-      /* Clear the last two bytes of 12-byte Intel format */
+      /* Clear the last two bytes of 12-byte Intel format.  q is pointing
+        into an array of size 6 (e.g. x[NE]), so the last two bytes are
+        always there, and there are never more bytes, even when we are using
+        INTEL_EXTENDED_IEEE_FORMAT.  */
       *(q+1) = 0;
-#endif
     }
 #endif
 
@@ -3354,13 +3706,19 @@ toe64 (a, b)
     *q-- = *p++;
 #endif
 #ifdef IEEE
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
+#ifdef ARM_EXTENDED_IEEE_FORMAT
+      /* The exponent is in the lowest 15 bits of the first word.  */
+      *q++ = i ? 0x8000 : 0;
+      *q++ = *p++;
+#else
       if (i)
        *q++ = *p++ | 0x8000;
       else
        *q++ = *p++;
       *q++ = 0;
+#endif
     }
   else
     {
@@ -3382,7 +3740,7 @@ toe64 (a, b)
     *q-- = *p++;
 #endif
 #ifdef IEEE
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
       for (i = 0; i < 4; i++)
        *q++ = *p++;
@@ -3406,19 +3764,22 @@ toe64 (a, b)
 #endif
 }
 
-
-/* e type to IEEE double precision.  */
+/* e type to double precision.  */
 
 #ifdef DEC
+/* Convert e-type X to DEC-format double E.  */
 
-static void 
+static void
 etoe53 (x, e)
      unsigned EMUSHORT *x, *e;
 {
   etodec (x, e);               /* see etodec.c */
 }
 
-static void 
+/* Convert exploded e-type X, that has already been rounded to
+   56-bit double precision, to DEC double Y.  */
+
+static void
 toe53 (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -3427,24 +3788,51 @@ toe53 (x, y)
 
 #else
 #ifdef IBM
+/* Convert e-type X to IBM 370-format double E.  */
 
-static void 
+static void
 etoe53 (x, e)
      unsigned EMUSHORT *x, *e;
 {
   etoibm (x, e, DFmode);
 }
 
-static void 
+/* 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;
 {
   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 
+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.  */
+
+static void
 etoe53 (x, e)
      unsigned EMUSHORT *x, *e;
 {
@@ -3471,12 +3859,16 @@ etoe53 (x, e)
   rndprc = 53;
   emdnorm (xi, 0, 0, exp, 64);
   rndprc = rndsav;
+#ifdef INFINITY
  nonorm:
+#endif
   toe53 (xi, e);
 }
 
+/* Convert exploded e-type X, that has already been rounded to
+   53-bit precision, to IEEE double Y.  */
 
-static void 
+static void
 toe53 (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -3492,7 +3884,7 @@ toe53 (x, y)
 #endif
   p = &x[0];
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     y += 3;
 #endif
   *y = 0;                      /* output high order */
@@ -3501,10 +3893,11 @@ 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 (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        {
          *(--y) = 0;
          *(--y) = 0;
@@ -3519,7 +3912,7 @@ toe53 (x, y)
        }
 #else
       *y |= (unsigned EMUSHORT) 0x7fef;
-      if (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        {
          *(--y) = 0xffff;
          *(--y) = 0xffff;
@@ -3546,7 +3939,7 @@ toe53 (x, y)
     }
   i |= *p++ & (unsigned EMUSHORT) 0x0f;        /* *p = xi[M] */
   *y |= (unsigned EMUSHORT) i; /* high order output already has sign bit set */
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     {
       *(--y) = *p++;
       *(--y) = *p++;
@@ -3561,23 +3954,28 @@ toe53 (x, y)
     }
 }
 
+#endif /* not C4X */
 #endif /* not IBM */
 #endif /* not DEC */
 
 
 
-/* e type to IEEE single precision.  */
+/* e type to single precision.  */
 
 #ifdef IBM
+/* Convert e-type X to IBM 370 float E.  */
 
-static void 
+static void
 etoe24 (x, e)
      unsigned EMUSHORT *x, *e;
 {
   etoibm (x, e, SFmode);
 }
 
-static void 
+/* 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;
 {
@@ -3586,7 +3984,31 @@ toe24 (x, y)
 
 #else
 
-static void 
+#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
 etoe24 (x, e)
      unsigned EMUSHORT *x, *e;
 {
@@ -3613,11 +4035,16 @@ etoe24 (x, e)
   rndprc = 24;
   emdnorm (xi, 0, 0, exp, 64);
   rndprc = rndsav;
+#ifdef INFINITY
  nonorm:
+#endif
   toe24 (xi, e);
 }
 
-static void 
+/* Convert exploded e-type X, that has already been rounded to
+   float precision, to IEEE float Y.  */
+
+static void
 toe24 (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -3633,7 +4060,7 @@ toe24 (x, y)
 #endif
   p = &x[0];
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     y += 1;
 #endif
 #ifdef DEC
@@ -3644,7 +4071,7 @@ toe24 (x, y)
     *y = 0x8000;               /* output sign bit */
 
   i = *p++;
-/* Handle overflow cases. */
+/* Handle overflow cases.  */
   if (i >= 255)
     {
 #ifdef INFINITY
@@ -3653,7 +4080,7 @@ toe24 (x, y)
       *(--y) = 0;
 #endif
 #ifdef IEEE
-      if (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        *(--y) = 0;
       else
        {
@@ -3667,7 +4094,7 @@ toe24 (x, y)
       *(--y) = 0xffff;
 #endif
 #ifdef IEEE
-      if (! FLOAT_WORDS_BIG_ENDIAN)
+      if (! REAL_WORDS_BIG_ENDIAN)
        *(--y) = 0xffff;
       else
        {
@@ -3691,12 +4118,13 @@ toe24 (x, y)
       eshift (x, 8);
     }
   i |= *p++ & (unsigned EMUSHORT) 0x7f;        /* *p = xi[M] */
-  *y |= i;                     /* high order output already has sign bit set */
+  /* High order output already has sign bit set.  */
+  *y |= i;
 #ifdef DEC
   *(--y) = *p;
 #endif
 #ifdef IEEE
-  if (! FLOAT_WORDS_BIG_ENDIAN)
+  if (! REAL_WORDS_BIG_ENDIAN)
     *(--y) = *p;
   else
     {
@@ -3705,15 +4133,16 @@ toe24 (x, y)
     }
 #endif
 }
+#endif  /* not C4X */
 #endif  /* not IBM */
 
-/* Compare two e type numbers. 
+/* Compare two e type numbers.
    Return +1 if a > b
            0 if a == b
           -1 if a < b
           -2 if either a or b is a NaN.  */
 
-static int 
+static int
 ecmp (a, b)
      unsigned EMUSHORT *a, *b;
 {
@@ -3765,8 +4194,6 @@ ecmp (a, b)
 
   return (0);                  /* equality */
 
-
-
  diff:
 
   if (*(--p) > *(--q))
@@ -3775,25 +4202,21 @@ ecmp (a, b)
     return (-msign);           /* p is littler */
 }
 
+#if 0
+/* Find e-type nearest integer to X, as floor (X + 0.5).  */
 
-
-
-/* Find nearest integer to x = floor (x + 0.5).  */
-
-static void 
+static void
 eround (x, y)
      unsigned EMUSHORT *x, *y;
 {
   eadd (ehalf, x, y);
   efloor (y, y);
 }
+#endif /* 0 */
 
+/* Convert HOST_WIDE_INT LP to e type Y.  */
 
-
-
-/* Convert HOST_WIDE_INT to e type.  */
-
-static void 
+static void
 ltoe (lp, y)
      HOST_WIDE_INT *lp;
      unsigned EMUSHORT *y;
@@ -3833,9 +4256,9 @@ ltoe (lp, y)
   emovo (yi, y);               /* output the answer */
 }
 
-/* Convert unsigned HOST_WIDE_INT to e type.  */
+/* Convert unsigned HOST_WIDE_INT LP to e type Y.  */
 
-static void 
+static void
 ultoe (lp, y)
      unsigned HOST_WIDE_INT *lp;
      unsigned EMUSHORT *y;
@@ -3868,14 +4291,14 @@ ultoe (lp, y)
 }
 
 
-/* Find signed HOST_WIDE_INT integer and floating point fractional
-   parts of e-type (packed internal format) floating point input X.
+/* Find signed HOST_WIDE_INT integer and floating point fractional
+   part FRAC 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).  */
 
-static void 
+static void
 eifrac (x, i, frac)
      unsigned EMUSHORT *x;
      HOST_WIDE_INT *i;
@@ -3954,11 +4377,11 @@ eifrac (x, i, frac)
 }
 
 
-/* Find unsigned HOST_WIDE_INT integer and floating point fractional parts.
-   A negative e type input yields integer output = 0
-   but correct fraction.  */
+/* Find unsigned HOST_WIDE_INT integer I and floating point fractional part
+   FRAC of e-type X.  A negative input yields integer output = 0 but
+   correct fraction.  */
 
-static void 
+static void
 euifrac (x, i, frac)
      unsigned EMUSHORT *x;
      unsigned HOST_WIDE_INT *i;
@@ -4011,7 +4434,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;
@@ -4025,11 +4448,9 @@ euifrac (x, i, frac)
   emovo (xi, frac);
 }
 
+/* Shift the significand of exploded e-type X up or down by SC bits.  */
 
-
-/* Shift significand area up or down by the number of bits given by SC.  */
-
-static int 
+static int
 eshift (x, sc)
      unsigned EMUSHORT *x;
      int sc;
@@ -4092,12 +4513,10 @@ eshift (x, sc)
   return ((int) lost);
 }
 
+/* Shift normalize the significand area of exploded e-type X.
+   Return the shift count (up = positive).  */
 
-
-/* Shift normalize the significand area pointed to by argument.
-   Shift count (up = positive) is returned.  */
-
-static int 
+static int
 enormlz (x)
      unsigned EMUSHORT x[];
 {
@@ -4163,16 +4582,12 @@ enormlz (x)
   return (sc);
 }
 
-
-
-
-/* Convert e type number to decimal format ASCII string.
-   The constants are for 64 bit precision.  */
+/* Powers of ten used in decimal <-> binary conversions.  */
 
 #define NTEN 12
 #define MAXP 4096
 
-#if LONG_DOUBLE_TYPE_SIZE == 128
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !defined(INTEL_EXTENDED_IEEE_FORMAT)
 static unsigned EMUSHORT etens[NTEN + 1][NE] =
 {
   {0x6576, 0x4a92, 0x804a, 0x153f,
@@ -4269,7 +4684,11 @@ static unsigned EMUSHORT emtens[NTEN + 1][NE] =
 };
 #endif
 
-static void 
+#if 0
+/* Convert float value X to ASCII string STRING with NDIG digits after
+   the decimal point.  */
+
+static void
 e24toasc (x, string, ndigs)
      unsigned EMUSHORT x[];
      char *string;
@@ -4281,8 +4700,10 @@ e24toasc (x, string, ndigs)
   etoasc (w, string, ndigs);
 }
 
+/* Convert double value X to ASCII string STRING with NDIG digits after
+   the decimal point.  */
 
-static void 
+static void
 e53toasc (x, string, ndigs)
      unsigned EMUSHORT x[];
      char *string;
@@ -4294,8 +4715,10 @@ e53toasc (x, string, ndigs)
   etoasc (w, string, ndigs);
 }
 
+/* Convert double extended value X to ASCII string STRING with NDIG digits
+   after the decimal point.  */
 
-static void 
+static void
 e64toasc (x, string, ndigs)
      unsigned EMUSHORT x[];
      char *string;
@@ -4307,7 +4730,10 @@ e64toasc (x, string, ndigs)
   etoasc (w, string, ndigs);
 }
 
-static void 
+/* Convert 128-bit long double value X to ASCII string STRING with NDIG digits
+   after the decimal point.  */
+
+static void
 e113toasc (x, string, ndigs)
      unsigned EMUSHORT x[];
      char *string;
@@ -4318,11 +4744,14 @@ 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.  */
 
 static char wstring[80];       /* working storage for ASCII output */
 
-static void 
+static void
 etoasc (x, string, ndigs)
      unsigned EMUSHORT x[];
      char *string;
@@ -4371,11 +4800,11 @@ etoasc (x, string, ndigs)
          if (y[k] != 0)
            goto tnzro;         /* denormalized number */
        }
-      goto isone;              /* legal all zeros */
+      goto isone;              /* valid all zeros */
     }
  tnzro:
 
-  /* Test for infinity. */
+  /* Test for infinity.  */
   if (y[NE - 1] == 0x7fff)
     {
       if (sign)
@@ -4405,7 +4834,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;
 
@@ -4435,7 +4864,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)
@@ -4452,7 +4881,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)
@@ -4510,7 +4939,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);
@@ -4533,7 +4962,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)
@@ -4554,7 +4983,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 */
@@ -4572,19 +5001,21 @@ 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);
          if (ecmp (t, ezero) != 0)
            goto roun;          /* round to nearest */
+#ifndef C4X
          if ((*(s - 1) & 1) == 0)
            goto doexp;         /* round to even */
+#endif
        }
       /* Round up and propagate carry-outs */
     roun:
       --s;
-      k = *s & 0x7f;
+      k = *s & CHARMASK;
       /* Carry out to most significant digit? */
       if (k == '.')
        {
@@ -4629,96 +5060,109 @@ etoasc (x, string, ndigs)
 }
 
 
-/* Convert ASCII string to quadruple precision floating point
+/* Convert ASCII string to floating point.
 
-   Numeric input is free field decimal number with max of 15 digits with or
-   without decimal point entered as ASCII from teletype.  Entering E after
-   the number followed by a second number causes the second number to be
-   interpreted as a power of 10 to be multiplied by the first number
-   (i.e., "scientific" notation).  */
+   Numeric input is a free format decimal number of any length, with
+   or without decimal point.  Entering E after the number followed by an
+   integer number causes the second number to be interpreted as a power of
+   10 to be multiplied by the first number (i.e., "scientific" notation).  */
 
-/* ASCII to single */
+/* Convert ASCII string S to single precision float value Y.  */
 
-static void 
+static void
 asctoe24 (s, y)
-     char *s;
+     const char *s;
      unsigned EMUSHORT *y;
 {
   asctoeg (s, y, 24);
 }
 
 
-/* ASCII to double */
+/* Convert ASCII string S to double precision value Y.  */
 
-static void 
+static void
 asctoe53 (s, y)
-     char *s;
+     const char *s;
      unsigned EMUSHORT *y;
 {
 #if defined(DEC) || defined(IBM)
   asctoeg (s, y, 56);
 #else
+#if defined(C4X)
+  asctoeg (s, y, 32);
+#else
   asctoeg (s, y, 53);
 #endif
+#endif
 }
 
 
-/* ASCII to long double */
+/* Convert ASCII string S to double extended value Y.  */
 
-static void 
+static void
 asctoe64 (s, y)
-     char *s;
+     const char *s;
      unsigned EMUSHORT *y;
 {
   asctoeg (s, y, 64);
 }
 
-/* ASCII to 128-bit long double */
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+/* Convert ASCII string S to 128-bit long double Y.  */
 
-static void 
+static void
 asctoe113 (s, y)
-     char *s;
+     const char *s;
      unsigned EMUSHORT *y;
 {
   asctoeg (s, y, 113);
 }
+#endif
 
-/* ASCII to super double */
+/* Convert ASCII string S to e type Y.  */
 
-static void 
+static void
 asctoe (s, y)
-     char *s;
+     const char *s;
      unsigned EMUSHORT *y;
 {
   asctoeg (s, y, NBITS);
 }
 
+/* Convert ASCII string SS to e type Y, with a specified rounding precision
+   of OPREC bits.  BASE is 16 for C99 hexadecimal floating constants.  */
 
-/* ASCII to e type, with specified rounding precision = oprec. */
-
-static void 
+static void
 asctoeg (ss, y, oprec)
-     char *ss;
+     const char *ss;
      unsigned EMUSHORT *y;
      int oprec;
 {
   unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
   int esign, decflg, sgnflg, nexp, exp, prec, lost;
-  int k, trail, c, rndsav;
+  int i, k, trail, c, rndsav;
   EMULONG lexp;
-  unsigned EMUSHORT nsign, *p;
+  unsigned EMUSHORT nsign;
   char *sp, *s, *lstr;
+  int base = 10;
 
-  /* Copy the input string. */
+  /* Copy the input string.  */
   lstr = (char *) alloca (strlen (ss) + 1);
-  s = ss;
-  while (*s == ' ')            /* skip leading spaces */
-    ++s;
+
+  while (*ss == ' ')           /* skip leading spaces */
+    ++ss;
+
   sp = lstr;
-  while ((*sp++ = *s++) != '\0')
+  while ((*sp++ = *ss++) != '\0')
     ;
   s = lstr;
 
+  if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+    {
+      base = 16;
+      s += 2;
+    }
+
   rndsav = rndprc;
   rndprc = NBITS;              /* Set to full precision */
   lost = 0;
@@ -4732,24 +5176,33 @@ asctoeg (ss, y, oprec)
   trail = 0;
 
  nxtcom:
-  k = *s - '0';
-  if ((k >= 0) && (k <= 9))
+  if (*s >= '0' && *s <= '9')
+    k = *s - '0';
+  else if (*s >= 'a' && *s <= 'f')
+    k = 10 + *s - 'a';
+  else
+    k = 10 + *s - 'A';
+  if ((k >= 0) && (k < base))
     {
       /* 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;
-         while ((*sp >= '0') && (*sp <= '9'))
+         while ((*sp >= '0' && *sp <= '9')
+                || (base == 16 && ((*sp >= 'a' && *sp <= 'f')
+                                   || (*sp >= 'A' && *sp <= 'F'))))
            ++sp;
          /* Check for syntax error */
-         c = *sp & 0x7f;
-         if ((c != 'e') && (c != 'E') && (c != '\0')
+         c = *sp & CHARMASK;
+         if ((base != 10 || ((c != 'e') && (c != 'E')))
+             && (base != 16 || ((c != 'p') && (c != 'P')))
+             && (c != '\0')
              && (c != '\n') && (c != '\r') && (c != ' ')
              && (c != ','))
-           goto error;
+           goto unexpected_char_error;
          --sp;
          while (*sp == '0')
            *sp-- = 'z';
@@ -4765,13 +5218,28 @@ asctoeg (ss, y, oprec)
 
       if (yy[2] == 0)
        {
-         if (decflg)
-           nexp += 1;          /* count digits after decimal point */
-         eshup1 (yy);          /* multiply current number by 10 */
-         emovz (yy, xt);
-         eshup1 (xt);
-         eshup1 (xt);
-         eaddm (xt, yy);
+         if (base == 16)
+           {
+             if (decflg)
+               nexp += 4;      /* count digits after decimal point */
+
+             eshup1 (yy);      /* multiply current number by 16 */
+             eshup1 (yy);
+             eshup1 (yy);
+             eshup1 (yy);
+           }
+         else
+           {
+             if (decflg)
+               nexp += 1;              /* count digits after decimal point */
+
+             eshup1 (yy);              /* multiply current number by 10 */
+             emovz (yy, xt);
+             eshup1 (xt);
+             eshup1 (xt);
+             eaddm (xt, yy);
+           }
+         /* Insert the current digit.  */
          ecleaz (xt);
          xt[NI - 2] = (unsigned EMUSHORT) k;
          eaddm (xt, yy);
@@ -4782,7 +5250,12 @@ asctoeg (ss, y, oprec)
          lost |= k;
          /* Count lost digits before the decimal point.  */
          if (decflg == 0)
-           nexp -= 1;
+           {
+             if (base == 10)
+               nexp -= 1;
+             else
+               nexp -= 4;
+           }
        }
       prec += 1;
       goto donchr;
@@ -4794,21 +5267,23 @@ asctoeg (ss, y, oprec)
       break;
     case 'E':
     case 'e':
+    case 'P':
+    case 'p':
       goto expnt;
     case '.':                  /* decimal point */
       if (decflg)
-       goto error;
+       goto unexpected_char_error;
       ++decflg;
       break;
     case '-':
       nsign = 0xffff;
       if (sgnflg)
-       goto error;
+       goto unexpected_char_error;
       ++sgnflg;
       break;
     case '+':
       if (sgnflg)
-       goto error;
+       goto unexpected_char_error;
       ++sgnflg;
       break;
     case ',':
@@ -4821,7 +5296,7 @@ asctoeg (ss, y, oprec)
     case 'I':
       goto infinite;
     default:
-    error:
+    unexpected_char_error:
 #ifdef NANS
       einan (yy);
 #else
@@ -4836,7 +5311,15 @@ asctoeg (ss, y, oprec)
 
   /* Exponent interpretation */
  expnt:
+  /* 0.0eXXX is zero, regardless of XXX.  Check for the 0.0. */
+  for (k = 0; k < NI; k++)
+    {
+      if (yy[k] != 0)
+       goto read_expnt;
+    }
+  goto aexit;
 
+read_expnt:
   esign = 1;
   exp = 0;
   ++s;
@@ -4852,24 +5335,19 @@ asctoeg (ss, y, oprec)
     {
       exp *= 10;
       exp += *s++ - '0';
-      if (exp > -(MINDECEXP))
-       {
-         if (esign < 0)
-           goto zero;
-         else
-           goto infinite;
-       }
+      if (exp > 999999)
+       break;
     }
   if (esign < 0)
     exp = -exp;
-  if (exp > MAXDECEXP)
+  if ((exp > MAXDECEXP) && (base == 10))
     {
  infinite:
       ecleaz (yy);
       yy[E] = 0x7fff;          /* infinity */
       goto aexit;
     }
-  if (exp < MINDECEXP)
+  if ((exp < MINDECEXP) && (base == 10))
     {
  zero:
       ecleaz (yy);
@@ -4877,8 +5355,27 @@ asctoeg (ss, y, oprec)
     }
 
  daldone:
+  if (base == 16)
+    {
+      /* Base 16 hexadecimal floating constant.  */
+      if ((k = enormlz (yy)) > NBITS)
+       {
+         ecleaz (yy);
+         goto aexit;
+       }
+      /* Adjust the exponent.  NEXP is the number of hex digits,
+         EXP is a power of 2.  */
+      lexp = (EXONE - 1 + NBITS) - k + yy[E] + exp - nexp;
+      if (lexp > 0x7fff)
+       goto infinite;
+      if (lexp < 0)
+       goto zero;
+      yy[E] = lexp;
+      goto expdon;
+    }
+
   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);
@@ -4898,6 +5395,7 @@ asctoeg (ss, y, oprec)
     }
   lexp = (EXONE - 1 + NBITS) - k;
   emdnorm (yy, lost, 0, lexp, 64);
+  lost = 0;
 
   /* Convert to external format:
 
@@ -4920,7 +5418,7 @@ asctoeg (ss, y, oprec)
       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);
@@ -4928,14 +5426,14 @@ asctoeg (ss, y, oprec)
          nexp -= 4096;
        }
     }
-  p = &etens[NTEN][0];
   emov (eone, xt);
   exp = 1;
+  i = NTEN;
   do
     {
       if (exp & nexp)
-       emul (p, xt, xt);
-      p -= NE;
+       emul (etens[i], xt, xt);
+      i--;
       exp = exp + exp;
     }
   while (exp <= MAXP);
@@ -4953,25 +5451,31 @@ asctoeg (ss, y, oprec)
       k = emulm (tt, yy);
       lexp -= EXONE - 1;
     }
+  lost = k;
 
  expdon:
 
   /* 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;
 #endif
   rndprc = oprec;
-  emdnorm (yy, k, 0, lexp, 64);
+  emdnorm (yy, lost, 0, lexp, 64);
 
  aexit:
 
@@ -4989,6 +5493,12 @@ asctoeg (ss, y, oprec)
       toibm (yy, y, DFmode);
       break;
 #endif
+#ifdef C4X
+    case 32:
+      toc4x (yy, y, HFmode);
+      break;
+#endif
+
     case 53:
       toe53 (yy, y);
       break;
@@ -5009,7 +5519,8 @@ asctoeg (ss, y, oprec)
 
 
 
-/* y = largest integer not greater than x (truncated toward minus infinity)  */
+/* Return Y = largest integer not greater than X (truncated toward minus
+   infinity).  */
 
 static unsigned EMUSHORT bmask[] =
 {
@@ -5032,7 +5543,7 @@ static unsigned EMUSHORT bmask[] =
   0x0000,
 };
 
-static void 
+static void
 efloor (x, y)
      unsigned EMUSHORT x[], y[];
 {
@@ -5079,11 +5590,11 @@ efloor (x, y)
 }
 
 
-/* Returns s and exp such that  s * 2**exp = x and .5 <= s < 1.
-   For example, 1.1 = 0.55 * 2**1
-   Handles denormalized numbers properly using long integer exp.  */
+#if 0
+/* Return S and EXP such that  S * 2^EXP = X and .5 <= S < 1.
+   For example, 1.1 = 0.55 * 2^1.  */
 
-static void 
+static void
 efrexp (x, exp, s)
      unsigned EMUSHORT x[];
      int *exp;
@@ -5093,6 +5604,7 @@ efrexp (x, exp, s)
   EMULONG li;
 
   emovi (x, xi);
+  /*  Handle denormalized numbers properly using long integer exponent.  */
   li = (EMULONG) ((EMUSHORT) xi[1]);
 
   if (li == 0)
@@ -5103,12 +5615,11 @@ efrexp (x, exp, s)
   emovo (xi, s);
   *exp = (int) (li - 0x3ffe);
 }
+#endif
 
+/* Return e type Y = X * 2^PWR2.  */
 
-
-/* Return y = x * 2**pwr2.  */
-
-static void 
+static void
 eldexp (x, pwr2, y)
      unsigned EMUSHORT x[];
      int pwr2;
@@ -5127,10 +5638,11 @@ eldexp (x, pwr2, y)
 }
 
 
-/* c = remainder after dividing b by a
-   Least significant integer quotient bits left in equot[].  */
+#if 0
+/* C = remainder after dividing B by A, all e type values.
+   Least significant integer quotient bits left in EQUOT.  */
 
-static void 
+static void
 eremain (a, b, c)
      unsigned EMUSHORT a[], b[], c[];
 {
@@ -5162,8 +5674,12 @@ eremain (a, b, c)
     num[0] = 0xffff;
   emovo (num, c);
 }
+#endif
+
+/*  Return quotient of exploded e-types NUM / DEN in EQUOT,
+    remainder in NUM.  */
 
-static void 
+static void
 eiremain (den, num)
      unsigned EMUSHORT den[], num[];
 {
@@ -5183,9 +5699,7 @@ eiremain (den, num)
          j = 1;
        }
       else
-       {
          j = 0;
-       }
       eshup1 (equot);
       equot[NI - 1] |= j;
       eshup1 (num);
@@ -5194,11 +5708,10 @@ eiremain (den, num)
   emdnorm (num, 0, 0, ln, 0);
 }
 
-/* This routine may be called to report one of the following
-   error conditions (in the include file mconf.h).
+/* Report an error condition CODE encountered in function NAME.
 
     Mnemonic        Value          Significance
+
      DOMAIN            1       argument domain error
      SING              2       function singularity
      OVERFLOW          3       overflow range error
@@ -5208,63 +5721,61 @@ eiremain (den, num)
      INVALID           7       NaN - producing operation
      EDOM             33       Unix domain error code
      ERANGE           34       Unix range error code
-  The default version of the file prints the function name,
-  passed to it by the pointer fctnam, followed by the
-  error condition.  The display is directed to the standard
-  output device.  The routine then returns to the calling
-  program.  Users may wish to modify the program to abort by
-  calling exit under severe error conditions such as domain
-  errors.
-  Since all error conditions pass control to this function,
-  the display may be easily changed, eliminated, or directed
-  to an error logging device. */
-
-/* Note: the order of appearance of the following messages is bound to the
-   error codes defined above.  */
 
-#define NMSGS 8
-static char *ermsg[NMSGS] =
-{
-  "unknown",                   /* error code 0 */
-  "domain",                    /* error code 1 */
-  "singularity",               /* et seq.      */
-  "overflow",
-  "underflow",
-  "total loss of precision",
-  "partial loss of precision",
-  "invalid operation"
-};
+   The order of appearance of the following messages is bound to the
+   error codes defined above.  */
 
 int merror = 0;
 extern int merror;
 
-static void 
+static void
 mtherr (name, code)
-     char *name;
+     const char *name;
      int code;
 {
-  char errstr[80];
-
-  /* Display string passed by calling program, which is supposed to be the
+  /* The string passed by the calling program is supposed to be the
      name of the function in which the error occurred.
-
-     Display error message defined by the code argument.  */
-
-  if ((code <= 0) || (code >= NMSGS))
-    code = 0;
-  sprintf (errstr, " %s %s error", name, ermsg[code]);
+     The code argument selects which error message string will be printed.  */
+
+  if (strcmp (name, "esub") == 0)
+    name = "subtraction";
+  else if (strcmp (name, "ediv") == 0)
+    name = "division";
+  else if (strcmp (name, "emul") == 0)
+    name = "multiplication";
+  else if (strcmp (name, "enormlz") == 0)
+    name = "normalization";
+  else if (strcmp (name, "etoasc") == 0)
+    name = "conversion to text";
+  else if (strcmp (name, "asctoe") == 0)
+    name = "parsing";
+  else if (strcmp (name, "eremain") == 0)
+    name = "modulus";
+  else if (strcmp (name, "esqrt") == 0)
+    name = "square root";
   if (extra_warnings)
-    warning (errstr);
+    {
+      switch (code)
+       {
+       case DOMAIN:    warning ("%s: argument domain error"    , name); break;
+       case SING:      warning ("%s: function singularity"     , name); break;
+       case OVERFLOW:  warning ("%s: overflow range error"     , name); break;
+       case UNDERFLOW: warning ("%s: underflow range error"    , name); break;
+       case TLOSS:     warning ("%s: total loss of precision"  , name); break;
+       case PLOSS:     warning ("%s: partial loss of precision", name); break;
+       case INVALID:   warning ("%s: NaN - producing operation", name); break;
+       default:        abort ();
+       }
+    }
+
   /* Set global error message word */
   merror = code + 1;
 }
 
 #ifdef DEC
-/* Convert DEC double precision to e type.  */
+/* Convert DEC double precision D to e type E.  */
 
-static void 
+static void
 dectoe (d, e)
      unsigned EMUSHORT *d;
      unsigned EMUSHORT *e;
@@ -5302,16 +5813,9 @@ dectoe (d, e)
   emovo (y, e);
 }
 
+/* Convert e type X to DEC double precision D.  */
 
-
-/*
-;      convert e type to DEC double precision
-;      double d;
-;      EMUSHORT e[NE];
-;      etodec (e, &d);
-*/
-
-static void 
+static void
 etodec (x, d)
      unsigned EMUSHORT *x, *d;
 {
@@ -5320,8 +5824,9 @@ etodec (x, d)
   int rndsav;
 
   emovi (x, xi);
-  exp = (EMULONG) xi[E] - (EXONE - 0201);      /* adjust exponent for offsets */
-/* round off to nearest or even */
+  /* Adjust exponent for offsets.  */
+  exp = (EMULONG) xi[E] - (EXONE - 0201);
+  /* Round off to nearest or even.  */
   rndsav = rndprc;
   rndprc = 56;
   emdnorm (xi, 0, 0, exp, 64);
@@ -5329,7 +5834,10 @@ etodec (x, d)
   todec (xi, d);
 }
 
-static void 
+/* Convert exploded e-type X, that has already been rounded to
+   56-bit precision, to DEC format double Y.  */
+
+static void
 todec (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -5375,7 +5883,7 @@ todec (x, y)
 #ifdef IBM
 /* Convert IBM single/double precision to e type.  */
 
-static void 
+static void
 ibmtoe (d, e, mode)
      unsigned EMUSHORT *d;
      unsigned EMUSHORT *e;
@@ -5383,7 +5891,6 @@ ibmtoe (d, e, mode)
 {
   unsigned EMUSHORT y[NI];
   register unsigned EMUSHORT r, *p;
-  int rndsav;
 
   ecleaz (y);                  /* start with a zero */
   p = y;                       /* point to our number */
@@ -5419,7 +5926,7 @@ ibmtoe (d, e, mode)
 
 /* Convert e type to IBM single/double precision.  */
 
-static void 
+static void
 etoibm (x, d, mode)
      unsigned EMUSHORT *x, *d;
      enum machine_mode mode;
@@ -5438,7 +5945,7 @@ etoibm (x, d, mode)
   toibm (xi, d, mode);
 }
 
-static void 
+static void
 toibm (x, y, mode)
      unsigned EMUSHORT *x, *y;
      enum machine_mode mode;
@@ -5492,11 +5999,257 @@ 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 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 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
@@ -5536,6 +6289,7 @@ unsigned EMUSHORT SFlittlenan[2] = {0, 0xffc0};
 #endif
 
 
+#ifdef NANS
 static void
 make_nan (nan, sign, mode)
      unsigned EMUSHORT *nan;
@@ -5548,56 +6302,63 @@ 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:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
       n = 8;
-      if (FLOAT_WORDS_BIG_ENDIAN)
+      if (REAL_WORDS_BIG_ENDIAN)
        p = TFbignan;
       else
        p = TFlittlenan;
       break;
+#endif
+      /* FALLTHRU */
+
     case XFmode:
       n = 6;
-      if (FLOAT_WORDS_BIG_ENDIAN)
+      if (REAL_WORDS_BIG_ENDIAN)
        p = XFbignan;
       else
        p = XFlittlenan;
       break;
+
     case DFmode:
       n = 4;
-      if (FLOAT_WORDS_BIG_ENDIAN)
+      if (REAL_WORDS_BIG_ENDIAN)
        p = DFbignan;
       else
        p = DFlittlenan;
       break;
-    case HFmode:
+
     case SFmode:
+    case HFmode:
       n = 2;
-      if (FLOAT_WORDS_BIG_ENDIAN)
+      if (REAL_WORDS_BIG_ENDIAN)
        p = SFbignan;
       else
        p = SFlittlenan;
       break;
 #endif
+
     default:
       abort ();
     }
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    *nan++ = (sign << 15) | *p++;
+  if (REAL_WORDS_BIG_ENDIAN)
+    *nan++ = (sign << 15) | (*p++ & 0x7fff);
   while (--n != 0)
     *nan++ = *p++;
-  if (! FLOAT_WORDS_BIG_ENDIAN)
-    *nan = (sign << 15) | *p;
+  if (! REAL_WORDS_BIG_ENDIAN)
+    *nan = (sign << 15) | (*p & 0x7fff);
 }
+#endif /* NANS */
 
-/* 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];
@@ -5605,7 +6366,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 (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
       s[0] = (unsigned EMUSHORT) (f >> 16);
       s[1] = (unsigned EMUSHORT) f;
@@ -5623,9 +6384,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
@@ -5641,19 +6469,21 @@ ereal_from_double (d)
   unsigned EMUSHORT e[NE];
 
   /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces.  */
-  if (FLOAT_WORDS_BIG_ENDIAN)
+  if (REAL_WORDS_BIG_ENDIAN)
     {
+#if HOST_BITS_PER_WIDE_INT == 32
       s[0] = (unsigned EMUSHORT) (d[0] >> 16);
       s[1] = (unsigned EMUSHORT) d[0];
-#if HOST_BITS_PER_WIDE_INT == 32
       s[2] = (unsigned EMUSHORT) (d[1] >> 16);
       s[3] = (unsigned EMUSHORT) d[1];
 #else
       /* In this case the entire target double is contained in the
         first array element.  The second element of the input is
         ignored.  */
-      s[2] = (unsigned EMUSHORT) (d[0] >> 48);
-      s[3] = (unsigned EMUSHORT) (d[0] >> 32);
+      s[0] = (unsigned EMUSHORT) (d[0] >> 48);
+      s[1] = (unsigned EMUSHORT) (d[0] >> 32);
+      s[2] = (unsigned EMUSHORT) (d[0] >> 16);
+      s[3] = (unsigned EMUSHORT) d[0];
 #endif
     }
   else
@@ -5669,21 +6499,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 FLOAT_WORDS_BIG_ENDIAN.  */
+   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];
@@ -5708,11 +6539,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;
@@ -5757,9 +6588,9 @@ ditoe (di, e)
 }
 
 
-/* Convert e-type to unsigned 64-bit int. */
+/* Convert e-type to unsigned 64-bit int.  */
 
-static void 
+static void
 etoudi (x, i)
      unsigned EMUSHORT *x;
      unsigned EMUSHORT *i;
@@ -5840,9 +6671,9 @@ noshift:
 }
 
 
-/* Convert e-type to signed 64-bit int. */
+/* Convert e-type to signed 64-bit int.  */
 
-static void 
+static void
 etodi (x, i)
      unsigned EMUSHORT *x;
      unsigned EMUSHORT *i;
@@ -5938,13 +6769,13 @@ etodi (x, i)
 }
 
 
-/* Longhand square root routine. */
+/* Longhand square root routine.  */
 
 
 static int esqinited = 0;
 static unsigned short sqrndbit[NI];
 
-static void 
+static void
 esqrt (x, y)
      unsigned EMUSHORT *x, *y;
 {
@@ -5980,7 +6811,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)
@@ -6009,7 +6840,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++)
@@ -6035,35 +6866,44 @@ 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
    floating point mode.  The mode can hold an integer value
    that many bits wide, without losing any bits.  */
 
-int
+unsigned int
 significand_size (mode)
      enum machine_mode mode;
 {
 
-switch (mode)
+/* Don't test the modes, but their sizes, lest this
+   code won't work for BITS_PER_UNIT != 8 .  */
+
+switch (GET_MODE_BITSIZE (mode))
   {
-  case SFmode:
+  case 32:
+
+#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
+    return 56;
+#endif
+
     return 24;
 
-  case DFmode:
+  case 64:
 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
     return 53;
 #else
@@ -6073,15 +6913,24 @@ switch (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 XFmode:
+  case 96:
     return 64;
-  case TFmode:
+
+  case 128:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
     return 113;
+#else
+    return 64;
+#endif
 
   default:
     abort ();