/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
and support for XFmode IEEE extended real floating point arithmetic.
- Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
+#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).
-To support cross compilation between IEEE, VAX and IBM floating
-point formats, define REAL_ARITHMETIC in the tm.h file.
-
-In either case the machine files (tm.h) must not contain any code
+Machine files (tm.h etc) must not contain any code
that tries to use host floating point arithmetic to convert
REAL_VALUE_TYPEs from `double' to `float', pass them to fprintf,
etc. In cross-compile situations a REAL_VALUE_TYPE may not
be intelligible to the host computer's native arithmetic.
-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 a floating point
arithmetic suite that was not written with gcc in mind. Avoid
changing the low-level arithmetic routines unless you have suitable
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. */
+netlib.att.com: netlib/cephes. */
\f
/* Type of computer arithmetic.
- Only one of DEC, IBM, IEEE, or UNK should get defined.
+ Only one of DEC, IBM, IEEE, C4X, or UNK should get defined.
`IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically
to big-endian IEEE floating-point data structure. This definition
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.
+ both mean DFmode.
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 to non-zero
+ 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>,
These optional macros may be defined in tm.h. In real.h, they
default to WORDS_BIG_ENDIAN, etc., so there is no need to define
them for any normal host or target machine on which the floats
- and the integers have the same endian-ness. */
+ and the integers have the same endian-ness. */
/* The following converts gcc macros into the ones used by this file. */
-/* REAL_ARITHMETIC defined means that macros in real.h are
- defined to call emulator functions. */
-#ifdef REAL_ARITHMETIC
-
#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
/* PDP-11, Pro350, VAX: */
#define DEC 1
/* 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 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
- target machine's structure and will get its ends swapped
- accordingly (but not here). Probably only the decimal <-> binary
- functions in this file will actually be used in this case. */
-
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define DEC 1
-#else /* it's not VAX */
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-/* IBM System/370 style */
-#define IBM 1
-#else /* it's also not an IBM */
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define IEEE
-#else /* it's not IEEE either */
-unknown arithmetic type
-#define UNK 1
-#endif /* not IEEE */
-#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
#endif
#endif
+/* If no 16-bit type has been found and the compiler is GCC, try HImode. */
+#if defined(__GNUC__) && EMUSHORT_SIZE != 16
+typedef int HItype __attribute__ ((mode (HI)));
+typedef unsigned int UHItype __attribute__ ((mode (HI)));
+#undef EMUSHORT
+#undef EMUSHORT_SIZE
+#undef EMULONG_SIZE
+#define EMUSHORT HItype
+#define UEMUSHORT UHItype
+#define EMUSHORT_SIZE 16
+#define EMULONG_SIZE 32
+#else
+#define UEMUSHORT unsigned EMUSHORT
+#endif
+
#if HOST_BITS_PER_SHORT >= EMULONG_SIZE
#define EMULONG short
#else
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 || \
+ ((INTEL_EXTENDED_IEEE_FORMAT != 0) && 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 ((e), (r), 2*NE)
+# define PUT_REAL(e,r) \
+ do { \
+ memcpy ((r), (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 ((e), (r), 2*NE)
+# define PUT_REAL(e,r) \
+ do { \
+ memcpy ((r), (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 == REAL_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)); \
- } \
+#define GET_REAL(r,e) \
+do { \
+ if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
+ e53toe ((const UEMUSHORT *) (r), (e)); \
+ else \
+ { \
+ UEMUSHORT w[4]; \
+ memcpy (&w[3], ((const EMUSHORT *) r), sizeof (EMUSHORT)); \
+ memcpy (&w[2], ((const EMUSHORT *) r) + 1, sizeof (EMUSHORT)); \
+ memcpy (&w[1], ((const EMUSHORT *) r) + 2, sizeof (EMUSHORT)); \
+ memcpy (&w[0], ((const EMUSHORT *) r) + 3, sizeof (EMUSHORT)); \
+ e53toe (w, (e)); \
+ } \
} while (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); \
- *((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), (UEMUSHORT *) (r)); \
+ else \
+ { \
+ UEMUSHORT 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 */
-
-/* emulator uses host format */
-#define GET_REAL(r,e) e53toe ((unsigned EMUSHORT *) (r), (e))
-#define PUT_REAL(e,r) etoe53 ((e), (unsigned EMUSHORT *) (r))
-
-#endif /* not REAL_ARITHMETIC */
#endif /* not TFmode */
-#endif /* no XFmode */
+#endif /* not XFmode */
/* Number of 16 bit words in internal format */
/* 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[];
+extern const UEMUSHORT ezero[NE], ehalf[NE], eone[NE], etwo[NE];
+extern const UEMUSHORT elog2[NE], esqrt2[NE];
-static void endian PROTO((unsigned EMUSHORT *, long *,
+static void endian PARAMS ((const UEMUSHORT *, 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 *,
- 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 *,
- unsigned EMUSHORT *));
-static void eadd PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- unsigned EMUSHORT *));
-static void eadd1 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- unsigned EMUSHORT *));
-static void ediv PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- unsigned EMUSHORT *));
-static void emul PROTO((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 *,
- unsigned EMUSHORT *));
-static void euifrac PROTO((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
- unsigned EMUSHORT *));
-static int eshift PROTO((unsigned EMUSHORT *, int));
-static int enormlz PROTO((unsigned EMUSHORT *));
-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 eclear PARAMS ((UEMUSHORT *));
+static void emov PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#if 0
+static void eabs PARAMS ((UEMUSHORT *));
+#endif
+static void eneg PARAMS ((UEMUSHORT *));
+static int eisneg PARAMS ((const UEMUSHORT *));
+static int eisinf PARAMS ((const UEMUSHORT *));
+static int eisnan PARAMS ((const UEMUSHORT *));
+static void einfin PARAMS ((UEMUSHORT *));
+#ifdef NANS
+static void enan PARAMS ((UEMUSHORT *, int));
+static void einan PARAMS ((UEMUSHORT *));
+static int eiisnan PARAMS ((const UEMUSHORT *));
+static void make_nan PARAMS ((UEMUSHORT *, int, enum machine_mode));
+#endif
+static int eiisneg PARAMS ((const UEMUSHORT *));
+static void saturate PARAMS ((UEMUSHORT *, int, int, int));
+static void emovi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void emovo PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void ecleaz PARAMS ((UEMUSHORT *));
+static void ecleazs PARAMS ((UEMUSHORT *));
+static void emovz PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#if 0
+static void eiinfin PARAMS ((UEMUSHORT *));
+#endif
+#ifdef INFINITY
+static int eiisinf PARAMS ((const UEMUSHORT *));
+#endif
+static int ecmpm PARAMS ((const UEMUSHORT *, const UEMUSHORT *));
+static void eshdn1 PARAMS ((UEMUSHORT *));
+static void eshup1 PARAMS ((UEMUSHORT *));
+static void eshdn8 PARAMS ((UEMUSHORT *));
+static void eshup8 PARAMS ((UEMUSHORT *));
+static void eshup6 PARAMS ((UEMUSHORT *));
+static void eshdn6 PARAMS ((UEMUSHORT *));
+static void eaddm PARAMS ((const UEMUSHORT *, UEMUSHORT *));\f
+static void esubm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void m16m PARAMS ((unsigned int, const UEMUSHORT *, UEMUSHORT *));
+static int edivm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static int emulm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void emdnorm PARAMS ((UEMUSHORT *, int, int, EMULONG, int));
+static void esub PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
+ UEMUSHORT *));
+static void eadd PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
+ UEMUSHORT *));
+static void eadd1 PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
+ UEMUSHORT *));
+static void ediv PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
+ UEMUSHORT *));
+static void emul PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
+ UEMUSHORT *));
+static void e53toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void e64toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
+static void e113toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#endif
+static void e24toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
+static void etoe113 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void toe113 PARAMS ((UEMUSHORT *, UEMUSHORT *));
+#endif
+static void etoe64 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void toe64 PARAMS ((UEMUSHORT *, UEMUSHORT *));
+static void etoe53 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void toe53 PARAMS ((UEMUSHORT *, UEMUSHORT *));
+static void etoe24 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void toe24 PARAMS ((UEMUSHORT *, UEMUSHORT *));
+static int ecmp PARAMS ((const UEMUSHORT *, const UEMUSHORT *));
+#if 0
+static void eround PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#endif
+static void ltoe PARAMS ((const HOST_WIDE_INT *, UEMUSHORT *));
+static void ultoe PARAMS ((const unsigned HOST_WIDE_INT *, UEMUSHORT *));
+static void eifrac PARAMS ((const UEMUSHORT *, HOST_WIDE_INT *,
+ UEMUSHORT *));
+static void euifrac PARAMS ((const UEMUSHORT *, unsigned HOST_WIDE_INT *,
+ UEMUSHORT *));
+static int eshift PARAMS ((UEMUSHORT *, int));
+static int enormlz PARAMS ((UEMUSHORT *));
#if 0
-static void efrexp PROTO((unsigned EMUSHORT *, int *,
- unsigned EMUSHORT *));
+static void e24toasc PARAMS ((const UEMUSHORT *, char *, int));
+static void e53toasc PARAMS ((const UEMUSHORT *, char *, int));
+static void e64toasc PARAMS ((const UEMUSHORT *, char *, int));
+static void e113toasc PARAMS ((const UEMUSHORT *, char *, int));
+#endif /* 0 */
+static void etoasc PARAMS ((const UEMUSHORT *, char *, int));
+static void asctoe24 PARAMS ((const char *, UEMUSHORT *));
+static void asctoe53 PARAMS ((const char *, UEMUSHORT *));
+static void asctoe64 PARAMS ((const char *, UEMUSHORT *));
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
+static void asctoe113 PARAMS ((const char *, UEMUSHORT *));
+#endif
+static void asctoe PARAMS ((const char *, UEMUSHORT *));
+static void asctoeg PARAMS ((const char *, UEMUSHORT *, int));
+static void efloor PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+#if 0
+static void efrexp PARAMS ((const UEMUSHORT *, int *,
+ UEMUSHORT *));
#endif
-static void eldexp PROTO((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
+static void eldexp PARAMS ((const UEMUSHORT *, int, UEMUSHORT *));
#if 0
-static void eremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- unsigned EMUSHORT *));
+static void eremain PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
+ UEMUSHORT *));
#endif
-static void eiremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void mtherr PROTO((char *, int));
+static void eiremain PARAMS ((UEMUSHORT *, UEMUSHORT *));
+static void mtherr PARAMS ((const char *, int));
#ifdef DEC
-static void dectoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etodec PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void todec PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void dectoe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void etodec PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void todec PARAMS ((UEMUSHORT *, UEMUSHORT *));
#endif
#ifdef IBM
-static void ibmtoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- enum machine_mode));
-static void etoibm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- enum machine_mode));
-static void toibm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
- enum machine_mode));
+static void ibmtoe PARAMS ((const UEMUSHORT *, UEMUSHORT *,
+ enum machine_mode));
+static void etoibm PARAMS ((const UEMUSHORT *, UEMUSHORT *,
+ enum machine_mode));
+static void toibm PARAMS ((UEMUSHORT *, UEMUSHORT *,
+ enum machine_mode));
+#endif
+#ifdef C4X
+static void c4xtoe PARAMS ((const UEMUSHORT *, UEMUSHORT *,
+ enum machine_mode));
+static void etoc4x PARAMS ((const UEMUSHORT *, UEMUSHORT *,
+ enum machine_mode));
+static void toc4x PARAMS ((UEMUSHORT *, UEMUSHORT *,
+ enum machine_mode));
#endif
-static void make_nan PROTO((unsigned EMUSHORT *, int, enum machine_mode));
#if 0
-static void uditoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void ditoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoudi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etodi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void esqrt PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void uditoe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void ditoe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void etoudi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void etodi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
+static void esqrt PARAMS ((const UEMUSHORT *, UEMUSHORT *));
#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. */
+ result is normally passed to fprintf by the ASM_OUTPUT_ macros. */
-static void
+static void
endian (e, x, mode)
- unsigned EMUSHORT e[];
+ const UEMUSHORT e[];
long x[];
enum machine_mode mode;
{
{
switch (mode)
{
-
case TFmode:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* 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;
+#else
+ x[3] = 0;
+#endif
+ /* FALLTHRU */
case XFmode:
-
/* Swap halfwords in the third long. */
th = (unsigned long) e[4] & 0xffff;
t = (unsigned long) e[5] & 0xffff;
t |= th << 16;
x[2] = (long) t;
- /* fall into the double case */
+ /* FALLTHRU */
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 */
+ /* FALLTHRU */
- 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;
switch (mode)
{
-
case TFmode:
-
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Pack the fourth long. */
th = (unsigned long) e[7] & 0xffff;
t = (unsigned long) e[6] & 0xffff;
t |= th << 16;
x[3] = (long) t;
+#else
+ x[3] = 0;
+#endif
+ /* FALLTHRU */
case XFmode:
-
/* Pack the third long.
Each element of the input REAL_VALUE_TYPE array has 16 useful bits
in it. */
t = (unsigned long) e[4] & 0xffff;
t |= th << 16;
x[2] = (long) t;
- /* fall into the double case */
+ /* FALLTHRU */
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 */
+ /* FALLTHRU */
- 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;
/* This is the implementation of the REAL_ARITHMETIC macro. */
-void
+void
earith (value, icode, r1, r2)
REAL_VALUE_TYPE *value;
int icode;
REAL_VALUE_TYPE *r1;
REAL_VALUE_TYPE *r2;
{
- unsigned EMUSHORT d1[NE], d2[NE], v[NE];
+ UEMUSHORT d1[NE], d2[NE], v[NE];
enum tree_code code;
GET_REAL (r1, d1);
break;
case RDIV_EXPR:
-#ifndef REAL_INFINITY
+#ifndef INFINITY
if (ecmp (d2, ezero) == 0)
- {
-#ifdef NANS
- enan (v, eisneg (d1) ^ eisneg (d2));
- break;
-#else
abort ();
#endif
- }
-#endif
ediv (d2, d1, v); /* d1/d2 */
break;
/* 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;
{
- unsigned EMUSHORT f[NE], g[NE];
+ UEMUSHORT f[NE], g[NE];
REAL_VALUE_TYPE r;
HOST_WIDE_INT l;
/* 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;
{
- unsigned EMUSHORT f[NE], g[NE];
+ UEMUSHORT f[NE], g[NE];
REAL_VALUE_TYPE r;
unsigned HOST_WIDE_INT l;
}
-/* 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];
+ UEMUSHORT tem[NE], e[NE];
REAL_VALUE_TYPE r;
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:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
asctoe113 (s, tem);
e113toe (tem, e);
break;
+#endif
+ /* FALLTHRU */
+
+ case XFmode:
+ asctoe64 (s, tem);
+ e64toe (tem, e);
+ break;
+
default:
asctoe (s, e);
}
/* Expansion of REAL_NEGATE. */
-REAL_VALUE_TYPE
+REAL_VALUE_TYPE
ereal_negate (x)
REAL_VALUE_TYPE x;
{
- unsigned EMUSHORT e[NE];
+ UEMUSHORT e[NE];
REAL_VALUE_TYPE r;
GET_REAL (&x, e);
efixi (x)
REAL_VALUE_TYPE x;
{
- unsigned EMUSHORT f[NE], g[NE];
+ UEMUSHORT f[NE], g[NE];
HOST_WIDE_INT l;
GET_REAL (&x, f);
efixui (x)
REAL_VALUE_TYPE x;
{
- unsigned EMUSHORT f[NE], g[NE];
+ UEMUSHORT f[NE], g[NE];
unsigned HOST_WIDE_INT l;
GET_REAL (&x, f);
/* REAL_VALUE_FROM_INT macro. */
-void
+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];
+ UEMUSHORT df[NE], dg[NE];
HOST_WIDE_INT low, high;
int sign;
break;
case 128:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
etoe113 (dg, df);
e113toe (df, dg);
+#else
+ etoe64 (dg, df);
+ e64toe (df, dg);
+#endif
break;
default:
}
-/* REAL_VALUE_FROM_UNSIGNED_INT macro. */
+/* REAL_VALUE_FROM_UNSIGNED_INT macro. */
-void
+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];
+ UEMUSHORT df[NE], dg[NE];
unsigned HOST_WIDE_INT low, high;
if (GET_MODE_CLASS (mode) != MODE_FLOAT)
break;
case 128:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
etoe113 (dg, df);
e113toe (df, dg);
+#else
+ etoe64 (dg, df);
+ e64toe (df, dg);
+#endif
break;
default:
/* REAL_VALUE_TO_INT macro. */
-void
+void
ereal_to_int (low, high, rr)
HOST_WIDE_INT *low, *high;
REAL_VALUE_TYPE rr;
{
- unsigned EMUSHORT d[NE], df[NE], dg[NE], dh[NE];
+ UEMUSHORT d[NE], df[NE], dg[NE], dh[NE];
int s;
GET_REAL (&rr, d);
ediv (df, d, dg); /* dg = d / 2^32 is the high word */
euifrac (dg, (unsigned HOST_WIDE_INT *) high, dh);
emul (df, dh, dg); /* fractional part is the low word */
- euifrac (dg, (unsigned HOST_WIDE_INT *)low, dh);
+ euifrac (dg, (unsigned HOST_WIDE_INT *) low, dh);
if (s)
{
/* complement and add 1 */
REAL_VALUE_TYPE x;
int n;
{
- unsigned EMUSHORT e[NE], y[NE];
+ UEMUSHORT e[NE], y[NE];
REAL_VALUE_TYPE r;
GET_REAL (&x, e);
return (r);
}
-/* These routines are conditionally compiled because functions
- of the same names may be defined in fold-const.c. */
-
-#ifdef REAL_ARITHMETIC
-
/* Check for infinity in a REAL_VALUE_TYPE. */
int
target_isinf (x)
- REAL_VALUE_TYPE x;
+ REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
{
- unsigned EMUSHORT e[NE];
-
#ifdef INFINITY
+ UEMUSHORT e[NE];
+
GET_REAL (&x, e);
return (eisinf (e));
#else
int
target_isnan (x)
- REAL_VALUE_TYPE x;
+ REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
{
- unsigned EMUSHORT e[NE];
-
#ifdef NANS
+ UEMUSHORT e[NE];
+
GET_REAL (&x, e);
return (eisnan (e));
#else
enum machine_mode mode;
REAL_VALUE_TYPE arg;
{
- unsigned EMUSHORT e[NE], t[NE];
+ UEMUSHORT e[NE], t[NE];
REAL_VALUE_TYPE r;
GET_REAL (&arg, e);
switch (mode)
{
case TFmode:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
etoe113 (e, t);
e113toe (t, t);
break;
+#endif
+ /* FALLTHRU */
case XFmode:
etoe64 (e, t);
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);
enum machine_mode mode;
REAL_VALUE_TYPE *r;
{
- unsigned EMUSHORT e[NE], einv[NE];
+ UEMUSHORT e[NE], einv[NE];
REAL_VALUE_TYPE rinv;
int i;
PUT_REAL (einv, r);
return 1;
}
-#endif /* REAL_ARITHMETIC defined */
/* Used for debugging--print the value of R in human-readable format
on stderr. */
REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
fprintf (stderr, "%s", dstr);
-}
+}
\f
/* 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'.
+ 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. */
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[];
{
- unsigned EMUSHORT e[NE];
+ UEMUSHORT e[NE];
GET_REAL (&r, e);
+#if INTEL_EXTENDED_IEEE_FORMAT == 0
etoe113 (e, e);
+#else
+ etoe64 (e, e);
+#endif
endian (e, l, TFmode);
}
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[];
{
- unsigned EMUSHORT e[NE];
+ UEMUSHORT e[NE];
GET_REAL (&r, e);
etoe64 (e, e);
/* 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
+void
etardouble (r, l)
REAL_VALUE_TYPE r;
long l[];
{
- unsigned EMUSHORT e[NE];
+ UEMUSHORT e[NE];
GET_REAL (&r, e);
etoe53 (e, e);
etarsingle (r)
REAL_VALUE_TYPE r;
{
- unsigned EMUSHORT e[NE];
+ UEMUSHORT e[NE];
long l;
GET_REAL (&r, e);
REAL_VALUE_TYPE x;
char *s;
{
- unsigned EMUSHORT e[NE];
+ UEMUSHORT e[NE];
GET_REAL (&x, e);
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. */
+ or -2 if either is a NaN. */
int
ereal_cmp (x, y)
REAL_VALUE_TYPE x, y;
{
- unsigned EMUSHORT ex[NE], ey[NE];
+ UEMUSHORT ex[NE], ey[NE];
GET_REAL (&x, ex);
GET_REAL (&y, ey);
ereal_isneg (x)
REAL_VALUE_TYPE x;
{
- unsigned EMUSHORT ex[NE];
+ UEMUSHORT ex[NE];
GET_REAL (&x, ex);
return (eisneg (ex));
}
-/* End of REAL_ARITHMETIC interface */
\f
/*
Extended precision IEEE binary floating point arithmetic routines
most significant word first,
most significant bit is set)
ei[NI-1] low guard word (0x8000 bit is rounding place)
-
-
-
+
+
+
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
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,
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
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 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
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.
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). */
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 IEEE should be defined.
are provided as arrays of hexadecimal 16 bit integers.
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. */
/* e type constants used by high precision check routines */
-#if LONG_DOUBLE_TYPE_SIZE == 128
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* 0.0 */
-unsigned EMUSHORT ezero[NE] =
+const UEMUSHORT ezero[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
-extern unsigned EMUSHORT ezero[];
/* 5.0E-1 */
-unsigned EMUSHORT ehalf[NE] =
+const UEMUSHORT ehalf[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,};
-extern unsigned EMUSHORT ehalf[];
/* 1.0E0 */
-unsigned EMUSHORT eone[NE] =
+const UEMUSHORT eone[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
-extern unsigned EMUSHORT eone[];
/* 2.0E0 */
-unsigned EMUSHORT etwo[NE] =
+const UEMUSHORT etwo[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,};
-extern unsigned EMUSHORT etwo[];
/* 3.2E1 */
-unsigned EMUSHORT e32[NE] =
+const UEMUSHORT e32[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,};
-extern unsigned EMUSHORT e32[];
/* 6.93147180559945309417232121458176568075500134360255E-1 */
-unsigned EMUSHORT elog2[NE] =
+const UEMUSHORT elog2[NE] =
{0x40f3, 0xf6af, 0x03f2, 0xb398,
0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
-extern unsigned EMUSHORT elog2[];
/* 1.41421356237309504880168872420969807856967187537695E0 */
-unsigned EMUSHORT esqrt2[NE] =
+const UEMUSHORT esqrt2[NE] =
{0x1d6f, 0xbe9f, 0x754a, 0x89b3,
0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
-extern unsigned EMUSHORT esqrt2[];
/* 3.14159265358979323846264338327950288419716939937511E0 */
-unsigned EMUSHORT epi[NE] =
+const UEMUSHORT epi[NE] =
{0x2902, 0x1cd1, 0x80dc, 0x628b,
0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
-extern unsigned EMUSHORT epi[];
#else
/* LONG_DOUBLE_TYPE_SIZE is other than 128 */
-unsigned EMUSHORT ezero[NE] =
+const UEMUSHORT ezero[NE] =
{0, 0000000, 0000000, 0000000, 0000000, 0000000,};
-unsigned EMUSHORT ehalf[NE] =
+const UEMUSHORT ehalf[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0x3ffe,};
-unsigned EMUSHORT eone[NE] =
+const UEMUSHORT eone[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0x3fff,};
-unsigned EMUSHORT etwo[NE] =
+const UEMUSHORT etwo[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0040000,};
-unsigned EMUSHORT e32[NE] =
+const UEMUSHORT e32[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0040004,};
-unsigned EMUSHORT elog2[NE] =
+const UEMUSHORT elog2[NE] =
{0xc9e4, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
-unsigned EMUSHORT esqrt2[NE] =
+const UEMUSHORT esqrt2[NE] =
{0x597e, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
-unsigned EMUSHORT epi[NE] =
+const UEMUSHORT epi[NE] =
{0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
#endif
/* Clear out entire e-type number X. */
-static void
+static void
eclear (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
- register int i;
+ int i;
for (i = 0; i < NE; i++)
*x++ = 0;
/* Move e-type number from A to B. */
-static void
+static void
emov (a, b)
- register unsigned EMUSHORT *a, *b;
+ const UEMUSHORT *a;
+ UEMUSHORT *b;
{
- register int i;
+ int i;
for (i = 0; i < NE; i++)
*b++ = *a++;
}
+#if 0
/* Absolute value of e-type X. */
-static void
+static void
eabs (x)
- unsigned EMUSHORT x[];
+ UEMUSHORT x[];
{
/* sign is top bit of last word of external format */
- x[NE - 1] &= 0x7fff;
+ x[NE - 1] &= 0x7fff;
}
+#endif /* 0 */
/* Negate the e-type number X. */
-static void
+static void
eneg (x)
- unsigned EMUSHORT x[];
+ UEMUSHORT x[];
{
x[NE - 1] ^= 0x8000; /* Toggle the sign bit */
/* Return 1 if sign bit of e-type number X is nonzero, else zero. */
-static int
+static int
eisneg (x)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
{
if (x[NE - 1] & 0x8000)
/* Return 1 if e-type number X is infinity, else return zero. */
-static int
+static int
eisinf (x)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
{
#ifdef NANS
/* 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[];
+ const UEMUSHORT x[] ATTRIBUTE_UNUSED;
{
#ifdef NANS
int i;
/* 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;
+ UEMUSHORT *x;
{
- register int i;
+ int i;
#ifdef INFINITY
for (i = 0; i < NE - 1; i++)
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;
+ UEMUSHORT *x;
int sign;
{
- register int i;
+ int i;
for (i = 0; i < NE - 2; i++)
*x++ = 0;
*x++ = 0xc000;
*x = (sign << 15) | 0x7fff;
}
+#endif /* NANS */
/* Move in an e-type number A, converting it to exploded e-type B. */
-static void
+static void
emovi (a, b)
- unsigned EMUSHORT *a, *b;
+ const UEMUSHORT *a;
+ UEMUSHORT *b;
{
- register unsigned EMUSHORT *p, *q;
+ const UEMUSHORT *p;
+ UEMUSHORT *q;
int i;
q = b;
/* Move out exploded e-type number A, converting it to e type B. */
-static void
+static void
emovo (a, b)
- unsigned EMUSHORT *a, *b;
+ const UEMUSHORT *a;
+ UEMUSHORT *b;
{
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT i;
+ const UEMUSHORT *p;
+ UEMUSHORT *q;
+ UEMUSHORT i;
int j;
p = a;
/* Clear out exploded e-type number XI. */
-static void
+static void
ecleaz (xi)
- register unsigned EMUSHORT *xi;
+ UEMUSHORT *xi;
{
- register int i;
+ int i;
for (i = 0; i < NI; i++)
*xi++ = 0;
/* Clear out exploded e-type XI, but don't touch the sign. */
-static void
+static void
ecleazs (xi)
- register unsigned EMUSHORT *xi;
+ UEMUSHORT *xi;
{
- register int i;
+ int i;
++xi;
for (i = 0; i < NI - 1; i++)
/* Move exploded e-type number from A to B. */
-static void
+static void
emovz (a, b)
- register unsigned EMUSHORT *a, *b;
+ const UEMUSHORT *a;
+ UEMUSHORT *b;
{
- register int i;
+ int i;
for (i = 0; i < NI - 1; i++)
*b++ = *a++;
The explicit pattern for this is maximum exponent and
top two significant bits set. */
+#ifdef NANS
static void
einan (x)
- unsigned EMUSHORT x[];
+ UEMUSHORT x[];
{
ecleaz (x);
x[E] = 0x7fff;
x[M + 1] = 0xc000;
}
+#endif /* NANS */
/* Return nonzero if exploded e-type X is a NaN. */
-static int
+#ifdef NANS
+static int
eiisnan (x)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
{
int i;
}
return (0);
}
+#endif /* NANS */
/* Return nonzero if sign of exploded e-type X is nonzero. */
-static int
+static int
eiisneg (x)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
{
return x[0] != 0;
}
+#if 0
/* Fill exploded e-type X with infinity pattern.
This has maximum exponent and significand all zeros. */
static void
eiinfin (x)
- unsigned EMUSHORT x[];
+ UEMUSHORT x[];
{
ecleaz (x);
x[E] = 0x7fff;
}
+#endif /* 0 */
/* Return nonzero if exploded e-type X is infinite. */
-static int
+#ifdef INFINITY
+static int
eiisinf (x)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
{
#ifdef NANS
return (1);
return (0);
}
-
+#endif /* INFINITY */
/* Compare significands of numbers in internal exploded e-type format.
Guard words are included in the comparison.
static int
ecmpm (a, b)
- register unsigned EMUSHORT *a, *b;
+ const UEMUSHORT *a, *b;
{
int i;
/* Shift significand of exploded e-type X down by 1 bit. */
-static void
+static void
eshdn1 (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
- register unsigned EMUSHORT bits;
+ UEMUSHORT bits;
int i;
x += M; /* point to significand area */
/* Shift significand of exploded e-type X up by 1 bit. */
-static void
+static void
eshup1 (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
- register unsigned EMUSHORT bits;
+ UEMUSHORT bits;
int i;
x += NI - 1;
/* Shift significand of exploded e-type X down by 8 bits. */
-static void
+static void
eshdn8 (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
- register unsigned EMUSHORT newbyt, oldbyt;
+ UEMUSHORT newbyt, oldbyt;
int i;
x += M;
/* Shift significand of exploded e-type X up by 8 bits. */
-static void
+static void
eshup8 (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
int i;
- register unsigned EMUSHORT newbyt, oldbyt;
+ UEMUSHORT newbyt, oldbyt;
x += NI - 1;
oldbyt = 0;
/* Shift significand of exploded e-type X up by 16 bits. */
-static void
+static void
eshup6 (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
int i;
- register unsigned EMUSHORT *p;
+ UEMUSHORT *p;
p = x + M;
x += M + 1;
/* Shift significand of exploded e-type X down by 16 bits. */
-static void
+static void
eshdn6 (x)
- register unsigned EMUSHORT *x;
+ UEMUSHORT *x;
{
int i;
- register unsigned EMUSHORT *p;
+ UEMUSHORT *p;
x += NI - 1;
p = x + 1;
/* Add significands of exploded e-type X and Y. X + Y replaces Y. */
-static void
+static void
eaddm (x, y)
- unsigned EMUSHORT *x, *y;
+ const UEMUSHORT *x;
+ UEMUSHORT *y;
{
- register unsigned EMULONG a;
+ unsigned EMULONG a;
int i;
unsigned int carry;
carry = 1;
else
carry = 0;
- *y = (unsigned EMUSHORT) a;
+ *y = (UEMUSHORT) a;
--x;
--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;
+ const UEMUSHORT *x;
+ UEMUSHORT *y;
{
unsigned EMULONG a;
int i;
carry = 1;
else
carry = 0;
- *y = (unsigned EMUSHORT) a;
+ *y = (UEMUSHORT) a;
--x;
--y;
}
}
-static unsigned EMUSHORT equot[NI];
+static UEMUSHORT equot[NI];
#if 0
/* Divide significands */
-int
+int
edivm (den, num)
- unsigned EMUSHORT den[], num[];
+ UEMUSHORT den[], num[];
{
int i;
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT j;
+ UEMUSHORT *p, *q;
+ UEMUSHORT j;
p = &equot[0];
*p++ = num[0];
/* Multiply significands */
-int
+int
emulm (a, b)
- unsigned EMUSHORT a[], b[];
+ UEMUSHORT a[], b[];
{
- unsigned EMUSHORT *p, *q;
+ UEMUSHORT *p, *q;
int i, j, k;
equot[0] = b[0];
static void
m16m (a, b, c)
unsigned int a;
- unsigned EMUSHORT b[], c[];
+ const UEMUSHORT b[];
+ UEMUSHORT c[];
{
- register unsigned EMUSHORT *pp;
- register unsigned EMULONG carry;
- unsigned EMUSHORT *ps;
- unsigned EMUSHORT p[NI];
+ UEMUSHORT *pp;
+ unsigned EMULONG carry;
+ const UEMUSHORT *ps;
+ UEMUSHORT p[NI];
unsigned EMULONG aa, m;
int i;
{
m = (unsigned EMULONG) aa * *ps--;
carry = (m & 0xffff) + *pp;
- *pp-- = (unsigned EMUSHORT)carry;
+ *pp-- = (UEMUSHORT) carry;
carry = (carry >> 16) + (m >> 16) + *pp;
- *pp = (unsigned EMUSHORT)carry;
+ *pp = (UEMUSHORT) carry;
*(pp-1) = carry >> 16;
}
}
static int
edivm (den, num)
- unsigned EMUSHORT den[], num[];
+ const UEMUSHORT den[];
+ UEMUSHORT num[];
{
int i;
- register unsigned EMUSHORT *p;
+ UEMUSHORT *p;
unsigned EMULONG tnum;
- unsigned EMUSHORT j, tdenm, tquot;
- unsigned EMUSHORT tprod[NI+1];
+ UEMUSHORT j, tdenm, tquot;
+ UEMUSHORT tprod[NI+1];
p = &equot[0];
*p++ = num[0];
tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
/* Do not execute the divide instruction if it will overflow. */
- if ((tdenm * 0xffffL) < tnum)
+ if ((tdenm * (unsigned long) 0xffff) < tnum)
tquot = 0xffff;
else
tquot = tnum / tdenm;
/* Multiply denominator by trial quotient digit. */
- m16m ((unsigned int)tquot, den, tprod);
+ m16m ((unsigned int) tquot, den, tprod);
/* The quotient digit may have been overestimated. */
if (ecmpm (tprod, num) > 0)
{
}
esubm (tprod, num);
equot[i] = tquot;
- eshup6(num);
+ eshup6 (num);
}
/* test for nonzero remainder after roundoff bit */
p = &num[M];
for (i=0; i<NI; i++)
num[i] = equot[i];
- return ((int)j);
+ return ((int) j);
}
/* Multiply significands of exploded e-type A and B, result in B. */
static int
emulm (a, b)
- unsigned EMUSHORT a[], b[];
+ const UEMUSHORT a[];
+ UEMUSHORT b[];
{
- unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT pprod[NI];
- unsigned EMUSHORT j;
+ const UEMUSHORT *p;
+ UEMUSHORT *q;
+ UEMUSHORT pprod[NI];
+ UEMUSHORT j;
int i;
equot[0] = b[0];
else
{
m16m ((unsigned int) *p--, b, pprod);
- eaddm(pprod, equot);
+ eaddm (pprod, equot);
}
j |= *q;
- eshdn6(equot);
+ eshdn6 (equot);
}
for (i=0; i<NI; i++)
b[i] = equot[i];
/* return flag for lost nonzero bits */
- return ((int)j);
+ return ((int) j);
}
#endif
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. If it is nonzero, the
returned value will be rounded to RNDPRC bits.
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
- result is denormal. */
+ result is denormal. */
static int rlast = -1;
static int rw = 0;
-static unsigned EMUSHORT rmsk = 0;
-static unsigned EMUSHORT rmbit = 0;
-static unsigned EMUSHORT rebit = 0;
+static UEMUSHORT rmsk = 0;
+static UEMUSHORT rmbit = 0;
+static UEMUSHORT rebit = 0;
static int re = 0;
-static unsigned EMUSHORT rbit[NI];
+static UEMUSHORT rbit[NI];
-static void
+static void
emdnorm (s, lost, subflg, exp, rcntrl)
- unsigned EMUSHORT s[];
+ UEMUSHORT s[];
int lost;
int subflg;
EMULONG exp;
int rcntrl;
{
int i, j;
- unsigned EMUSHORT r;
+ UEMUSHORT r;
/* Normalize */
j = enormlz (s);
re = rw - 1;
rebit = 1;
break;
+
case 113:
rw = 10;
rmsk = 0x7fff;
rebit = 0x8000;
re = rw;
break;
+
case 64:
rw = 7;
rmsk = 0xffff;
re = rw - 1;
rebit = 1;
break;
+
/* For DEC or IBM arithmetic */
case 56:
rw = 6;
rebit = 0x100;
re = rw;
break;
+
case 53:
rw = 6;
rmsk = 0x7ff;
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;
s[rw] &= ~rmsk;
if ((r & rmbit) != 0)
{
+#ifndef C4X
if (r == rmbit)
{
if (lost == 0)
goto mddone;
}
}
+#endif
eaddm (rbit, s);
}
mddone:
if (exp < 0)
s[1] = 0;
else
- s[1] = (unsigned EMUSHORT) exp;
+ s[1] = (UEMUSHORT) exp;
}
/* 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;
+ const UEMUSHORT *a, *b;
+ UEMUSHORT *c;
{
#ifdef NANS
/* Add. C = A + B, all e type. */
-static void
+static void
eadd (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
+ const UEMUSHORT *a, *b;
+ UEMUSHORT *c;
{
#ifdef NANS
/* Arithmetic common to both addition and subtraction. */
-static void
+static void
eadd1 (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
+ const UEMUSHORT *a, *b;
+ UEMUSHORT *c;
{
- unsigned EMUSHORT ai[NI], bi[NI], ci[NI];
+ UEMUSHORT ai[NI], bi[NI], ci[NI];
int i, lost, j, k;
EMULONG lt, lta, ltb;
break;
}
}
- bi[E] = (unsigned EMUSHORT) ltb;
+ bi[E] = (UEMUSHORT) ltb;
goto done;
}
if (i > 0)
esubm (ai, bi);
subflg = 1;
}
- emdnorm (bi, lost, subflg, ltb, 64);
+ emdnorm (bi, lost, subflg, ltb, !ROUND_TOWARDS_ZERO);
done:
emovo (bi, c);
/* Divide: C = B/A, all e type. */
-static void
+static void
ediv (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
+ const UEMUSHORT *a, *b;
+ UEMUSHORT *c;
{
- unsigned EMUSHORT ai[NI], bi[NI];
+ UEMUSHORT ai[NI], bi[NI];
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);
+ sign = eisneg (a) ^ eisneg (b);
#ifdef NANS
/* Return any NaN input. */
i = edivm (ai, bi);
/* calculate exponent */
lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
+ emdnorm (bi, i, 0, lt, !ROUND_TOWARDS_ZERO);
emovo (bi, c);
divsign:
*(c+(NE-1)) &= ~0x8000;
}
-/* Multiply e-types A and B, return e-type product C. */
+/* Multiply e-types A and B, return e-type product C. */
-static void
+static void
emul (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
+ const UEMUSHORT *a, *b;
+ UEMUSHORT *c;
{
- unsigned EMUSHORT ai[NI], bi[NI];
+ UEMUSHORT ai[NI], bi[NI];
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);
+ sign = eisneg (a) ^ eisneg (b);
#ifdef NANS
/* NaN times anything is the same NaN. */
j = emulm (ai, bi);
/* calculate exponent */
lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
+ emdnorm (bi, j, 0, lt, !ROUND_TOWARDS_ZERO);
emovo (bi, c);
mulsign:
static void
e53toe (pe, y)
- unsigned EMUSHORT *pe, *y;
+ const UEMUSHORT *pe;
+ UEMUSHORT *y;
{
#ifdef DEC
ibmtoe (pe, y, DFmode);
#else
- register unsigned EMUSHORT r;
- register unsigned EMUSHORT *e, *p;
- unsigned EMUSHORT yy[NI];
+#ifdef C4X
+
+ c4xtoe (pe, y, HFmode);
+
+#else
+ UEMUSHORT r;
+ const UEMUSHORT *e;
+ UEMUSHORT *p;
+ UEMUSHORT yy[NI];
int denorm, k;
e = pe;
#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);
+ yy[E] -= (UEMUSHORT) (k - 1);
}
emovo (yy, y);
+#endif /* not C4X */
#endif /* not IBM */
#endif /* not DEC */
}
/* Convert double extended precision float PE to e type Y. */
-static void
+static void
e64toe (pe, y)
- unsigned EMUSHORT *pe, *y;
+ const UEMUSHORT *pe;
+ UEMUSHORT *y;
{
- unsigned EMUSHORT yy[NI];
- unsigned EMUSHORT *e, *p, *q;
+ UEMUSHORT yy[NI];
+ const UEMUSHORT *e;
+ UEMUSHORT *p, *q;
int i;
e = pe;
/* 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)
+ if ((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
{
- unsigned EMUSHORT temp[NI];
+ UEMUSHORT temp[NI];
- emovi(yy, temp);
- eshup1(temp);
- emovo(temp,y);
+ emovi (yy, temp);
+ eshup1 (temp);
+ emovo (temp,y);
return;
}
}
*q++ = *p++;
}
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Convert 128-bit long double precision float PE to e type Y. */
-static void
+static void
e113toe (pe, y)
- unsigned EMUSHORT *pe, *y;
+ const UEMUSHORT *pe;
+ UEMUSHORT *y;
{
- register unsigned EMUSHORT r;
- unsigned EMUSHORT *e, *p;
- unsigned EMUSHORT yy[NI];
+ UEMUSHORT r;
+ const UEMUSHORT *e;
+ UEMUSHORT *p;
+ UEMUSHORT yy[NI];
int denorm, i;
e = pe;
}
emovo (yy, y);
}
+#endif
/* Convert single precision float PE to e type Y. */
-static void
+static void
e24toe (pe, y)
- unsigned EMUSHORT *pe, *y;
+ const UEMUSHORT *pe;
+ UEMUSHORT *y;
{
#ifdef IBM
ibmtoe (pe, y, SFmode);
#else
- register unsigned EMUSHORT r;
- register unsigned EMUSHORT *e, *p;
- unsigned EMUSHORT yy[NI];
+
+#ifdef C4X
+
+ c4xtoe (pe, y, QFmode);
+
+#else
+
+ UEMUSHORT r;
+ const UEMUSHORT *e;
+ UEMUSHORT *p;
+ UEMUSHORT yy[NI];
int denorm, k;
e = pe;
yy[M] = (r & 0x7f) | 0200;
r &= ~0x807f; /* strip sign and 7 significand bits */
#ifdef INFINITY
- if (r == 0x7f80)
+ if (!LARGEST_EXPONENT_IS_NORMAL (32) && r == 0x7f80)
{
#ifdef NANS
if (REAL_WORDS_BIG_ENDIAN)
if ((k = enormlz (yy)) > NBITS)
ecleazs (yy);
else
- yy[E] -= (unsigned EMUSHORT) (k - 1);
+ yy[E] -= (UEMUSHORT) (k - 1);
}
emovo (yy, y);
+#endif /* not C4X */
#endif /* not IBM */
}
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Convert e-type X to IEEE 128-bit long double format E. */
-static void
+static void
etoe113 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
EMULONG exp;
int rndsav;
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 113;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
+#ifdef INFINITY
nonorm:
+#endif
toe113 (xi, e);
}
/* 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;
+ UEMUSHORT *a, *b;
{
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT i;
+ UEMUSHORT *p, *q;
+ UEMUSHORT i;
#ifdef NANS
if (eiisnan (a))
*q-- = *p++;
}
}
+#endif
/* Convert e-type X to IEEE double extended format E. */
-static void
+static void
etoe64 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
EMULONG exp;
int rndsav;
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 64;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
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. */
-static void
+static void
toe64 (a, b)
- unsigned EMUSHORT *a, *b;
+ UEMUSHORT *a, *b;
{
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT i;
+ UEMUSHORT *p, *q;
+ UEMUSHORT i;
#ifdef NANS
if (eiisnan (a))
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
#ifdef DEC
/* Convert e-type X to DEC-format double E. */
-static void
+static void
etoe53 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
etodec (x, e); /* see etodec.c */
}
/* Convert exploded e-type X, that has already been rounded to
56-bit double precision, to DEC double Y. */
-static void
+static void
toe53 (x, y)
- unsigned EMUSHORT *x, *y;
+ UEMUSHORT *x, *y;
{
todec (x, y);
}
#ifdef IBM
/* Convert e-type X to IBM 370-format double E. */
-static void
+static void
etoe53 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
etoibm (x, e, DFmode);
}
/* 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;
+ UEMUSHORT *x, *y;
{
toibm (x, y, DFmode);
}
-#else /* it's neither DEC nor IBM */
-
-/* Convert e-type X to IEEE double E. */
+#else /* it's neither DEC nor IBM */
+#ifdef C4X
+/* Convert e-type X to C4X-format long double E. */
-static void
+static void
etoe53 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
- unsigned EMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
+ etoc4x (x, e, HFmode);
+}
+
+/* Convert exploded e-type X, that has already been rounded to
+ 56-bit precision, to IBM 370 double Y. */
+
+static void
+toe53 (x, y)
+ UEMUSHORT *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)
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
+{
+ UEMUSHORT xi[NI];
+ EMULONG exp;
+ int rndsav;
#ifdef NANS
if (eisnan (x))
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 53;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
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;
+ UEMUSHORT *x, *y;
{
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
+ UEMUSHORT i;
+ UEMUSHORT *p;
#ifdef NANS
if (eiisnan (x))
return;
}
#endif
+ if (LARGEST_EXPONENT_IS_NORMAL (64) && x[1] > 2047)
+ {
+ saturate (y, eiisneg (x), 64, 1);
+ return;
+ }
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
*y++ = 0;
}
#else
- *y |= (unsigned EMUSHORT) 0x7fef;
+ *y |= (UEMUSHORT) 0x7fef;
if (! REAL_WORDS_BIG_ENDIAN)
{
*(--y) = 0xffff;
i <<= 4;
eshift (x, 5);
}
- i |= *p++ & (unsigned EMUSHORT) 0x0f; /* *p = xi[M] */
- *y |= (unsigned EMUSHORT) i; /* high order output already has sign bit set */
+ i |= *p++ & (UEMUSHORT) 0x0f; /* *p = xi[M] */
+ *y |= (UEMUSHORT) i; /* high order output already has sign bit set */
if (! REAL_WORDS_BIG_ENDIAN)
{
*(--y) = *p++;
}
}
+#endif /* not C4X */
#endif /* not IBM */
#endif /* not DEC */
#ifdef IBM
/* Convert e-type X to IBM 370 float E. */
-static void
+static void
etoe24 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
etoibm (x, e, SFmode);
}
/* Convert exploded e-type X, that has already been rounded to
float precision, to IBM 370 float Y. */
-static void
+static void
toe24 (x, y)
- unsigned EMUSHORT *x, *y;
+ UEMUSHORT *x, *y;
{
toibm (x, y, SFmode);
}
#else
+
+#ifdef C4X
+/* Convert e-type X to C4X float E. */
+
+static void
+etoe24 (x, e)
+ const UEMUSHORT *x;
+ UEMUSHORT *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)
+ UEMUSHORT *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
+static void
etoe24 (x, e)
- unsigned EMUSHORT *x, *e;
+ const UEMUSHORT *x;
+ UEMUSHORT *e;
{
EMULONG exp;
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
int rndsav;
#ifdef NANS
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 24;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
+#ifdef INFINITY
nonorm:
+#endif
toe24 (xi, e);
}
/* Convert exploded e-type X, that has already been rounded to
float precision, to IEEE float Y. */
-static void
+static void
toe24 (x, y)
- unsigned EMUSHORT *x, *y;
+ UEMUSHORT *x, *y;
{
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
+ UEMUSHORT i;
+ UEMUSHORT *p;
#ifdef NANS
if (eiisnan (x))
return;
}
#endif
+ if (LARGEST_EXPONENT_IS_NORMAL (32) && x[1] > 255)
+ {
+ saturate (y, eiisneg (x), 32, 1);
+ return;
+ }
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
i = *p++;
/* Handle overflow cases. */
- if (i >= 255)
+ if (!LARGEST_EXPONENT_IS_NORMAL (32) && i >= 255)
{
#ifdef INFINITY
- *y |= (unsigned EMUSHORT) 0x7f80;
+ *y |= (UEMUSHORT) 0x7f80;
#ifdef DEC
*(--y) = 0;
#endif
}
#endif
#else /* no INFINITY */
- *y |= (unsigned EMUSHORT) 0x7f7f;
+ *y |= (UEMUSHORT) 0x7f7f;
#ifdef DEC
*(--y) = 0xffff;
#endif
i <<= 7;
eshift (x, 8);
}
- i |= *p++ & (unsigned EMUSHORT) 0x7f; /* *p = xi[M] */
+ i |= *p++ & (UEMUSHORT) 0x7f; /* *p = xi[M] */
/* High order output already has sign bit set. */
*y |= i;
#ifdef DEC
}
#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;
+ const UEMUSHORT *a, *b;
{
- unsigned EMUSHORT ai[NI], bi[NI];
- register unsigned EMUSHORT *p, *q;
- register int i;
+ UEMUSHORT ai[NI], bi[NI];
+ UEMUSHORT *p, *q;
+ int i;
int msign;
#ifdef NANS
return (-msign); /* p is littler */
}
+#if 0
/* Find e-type nearest integer to X, as floor (X + 0.5). */
-static void
+static void
eround (x, y)
- unsigned EMUSHORT *x, *y;
+ const UEMUSHORT *x;
+ UEMUSHORT *y;
{
eadd (ehalf, x, y);
efloor (y, y);
}
+#endif /* 0 */
/* Convert HOST_WIDE_INT LP to e type Y. */
-static void
+static void
ltoe (lp, y)
- HOST_WIDE_INT *lp;
- unsigned EMUSHORT *y;
+ const HOST_WIDE_INT *lp;
+ UEMUSHORT *y;
{
- unsigned EMUSHORT yi[NI];
+ UEMUSHORT yi[NI];
unsigned HOST_WIDE_INT ll;
int k;
}
/* move the long integer to yi significand area */
#if HOST_BITS_PER_WIDE_INT == 64
- yi[M] = (unsigned EMUSHORT) (ll >> 48);
- yi[M + 1] = (unsigned EMUSHORT) (ll >> 32);
- yi[M + 2] = (unsigned EMUSHORT) (ll >> 16);
- yi[M + 3] = (unsigned EMUSHORT) ll;
+ yi[M] = (UEMUSHORT) (ll >> 48);
+ yi[M + 1] = (UEMUSHORT) (ll >> 32);
+ yi[M + 2] = (UEMUSHORT) (ll >> 16);
+ yi[M + 3] = (UEMUSHORT) ll;
yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
#else
- yi[M] = (unsigned EMUSHORT) (ll >> 16);
- yi[M + 1] = (unsigned EMUSHORT) ll;
+ yi[M] = (UEMUSHORT) (ll >> 16);
+ yi[M + 1] = (UEMUSHORT) ll;
yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
#endif
if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
ecleaz (yi); /* it was zero */
else
- yi[E] -= (unsigned EMUSHORT) k;/* subtract shift count from exponent */
+ yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
emovo (yi, y); /* output the answer */
}
/* 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;
+ const unsigned HOST_WIDE_INT *lp;
+ UEMUSHORT *y;
{
- unsigned EMUSHORT yi[NI];
+ UEMUSHORT yi[NI];
unsigned HOST_WIDE_INT ll;
int k;
/* move the long integer to ayi significand area */
#if HOST_BITS_PER_WIDE_INT == 64
- yi[M] = (unsigned EMUSHORT) (ll >> 48);
- yi[M + 1] = (unsigned EMUSHORT) (ll >> 32);
- yi[M + 2] = (unsigned EMUSHORT) (ll >> 16);
- yi[M + 3] = (unsigned EMUSHORT) ll;
+ yi[M] = (UEMUSHORT) (ll >> 48);
+ yi[M + 1] = (UEMUSHORT) (ll >> 32);
+ yi[M + 2] = (UEMUSHORT) (ll >> 16);
+ yi[M + 3] = (UEMUSHORT) ll;
yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
#else
- yi[M] = (unsigned EMUSHORT) (ll >> 16);
- yi[M + 1] = (unsigned EMUSHORT) ll;
+ yi[M] = (UEMUSHORT) (ll >> 16);
+ yi[M + 1] = (UEMUSHORT) ll;
yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
#endif
if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
ecleaz (yi); /* it was zero */
else
- yi[E] -= (unsigned EMUSHORT) k; /* subtract shift count from exponent */
+ yi[E] -= (UEMUSHORT) k; /* subtract shift count from exponent */
emovo (yi, y); /* output the answer */
}
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;
+ const UEMUSHORT *x;
HOST_WIDE_INT *i;
- unsigned EMUSHORT *frac;
+ UEMUSHORT *frac;
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
int j, k;
unsigned HOST_WIDE_INT ll;
if ((k = enormlz (xi)) > NBITS)
ecleaz (xi);
else
- xi[E] -= (unsigned EMUSHORT) k;
+ xi[E] -= (UEMUSHORT) k;
emovo (xi, frac);
}
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;
+ const UEMUSHORT *x;
unsigned HOST_WIDE_INT *i;
- unsigned EMUSHORT *frac;
+ UEMUSHORT *frac;
{
unsigned HOST_WIDE_INT ll;
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
int j, k;
emovi (x, xi);
{
/* Long integer overflow: output large integer
and correct fraction.
- Note, the BSD microvax compiler says that ~(0UL)
+ Note, the BSD MicroVAX compiler says that ~(0UL)
is a syntax error. */
*i = ~(0L);
eshift (xi, k);
if ((k = enormlz (xi)) > NBITS)
ecleaz (xi);
else
- xi[E] -= (unsigned EMUSHORT) k;
+ xi[E] -= (UEMUSHORT) k;
emovo (xi, frac);
}
/* Shift the significand of exploded e-type X up or down by SC bits. */
-static int
+static int
eshift (x, sc)
- unsigned EMUSHORT *x;
+ UEMUSHORT *x;
int sc;
{
- unsigned EMUSHORT lost;
- unsigned EMUSHORT *p;
+ UEMUSHORT lost;
+ UEMUSHORT *p;
if (sc == 0)
return (0);
/* Shift normalize the significand area of exploded e-type X.
Return the shift count (up = positive). */
-static int
+static int
enormlz (x)
- unsigned EMUSHORT x[];
+ UEMUSHORT x[];
{
- register unsigned EMUSHORT *p;
+ UEMUSHORT *p;
int sc;
sc = 0;
#define NTEN 12
#define MAXP 4096
-#if LONG_DOUBLE_TYPE_SIZE == 128
-static unsigned EMUSHORT etens[NTEN + 1][NE] =
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0)
+static const UEMUSHORT etens[NTEN + 1][NE] =
{
{0x6576, 0x4a92, 0x804a, 0x153f,
0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
};
-static unsigned EMUSHORT emtens[NTEN + 1][NE] =
+static const UEMUSHORT emtens[NTEN + 1][NE] =
{
{0x2030, 0xcffc, 0xa1c3, 0x8123,
0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
};
#else
/* LONG_DOUBLE_TYPE_SIZE is other than 128 */
-static unsigned EMUSHORT etens[NTEN + 1][NE] =
+static const UEMUSHORT etens[NTEN + 1][NE] =
{
{0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
{0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */
{0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
};
-static unsigned EMUSHORT emtens[NTEN + 1][NE] =
+static const UEMUSHORT emtens[NTEN + 1][NE] =
{
{0x2de4, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
{0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */
};
#endif
+#if 0
/* Convert float value X to ASCII string STRING with NDIG digits after
the decimal point. */
-static void
+static void
e24toasc (x, string, ndigs)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
char *string;
int ndigs;
{
- unsigned EMUSHORT w[NI];
+ UEMUSHORT w[NI];
e24toe (x, w);
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[];
+ const UEMUSHORT x[];
char *string;
int ndigs;
{
- unsigned EMUSHORT w[NI];
+ UEMUSHORT w[NI];
e53toe (x, w);
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[];
+ const UEMUSHORT x[];
char *string;
int ndigs;
{
- unsigned EMUSHORT w[NI];
+ UEMUSHORT w[NI];
e64toe (x, w);
etoasc (w, string, ndigs);
/* Convert 128-bit long double value X to ASCII string STRING with NDIG digits
after the decimal point. */
-static void
+static void
e113toasc (x, string, ndigs)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
char *string;
int ndigs;
{
- unsigned EMUSHORT w[NI];
+ UEMUSHORT w[NI];
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[];
+ const UEMUSHORT x[];
char *string;
int ndigs;
{
EMUSHORT digit;
- unsigned EMUSHORT y[NI], t[NI], u[NI], w[NI];
- unsigned EMUSHORT *p, *r, *ten;
- unsigned EMUSHORT sign;
+ UEMUSHORT y[NI], t[NI], u[NI], w[NI];
+ const UEMUSHORT *p, *r, *ten;
+ UEMUSHORT sign;
int i, j, k, expon, rndsav;
char *s, *ss;
- unsigned EMUSHORT m;
+ UEMUSHORT m;
rndsav = rndprc;
}
else
{
- *s++ = (char)digit + '0';
+ *s++ = (char) digit + '0';
*s++ = '.';
}
/* Generate digits after the decimal point. */
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 == '.')
{
/* Convert ASCII string S to single precision float value Y. */
-static void
+static void
asctoe24 (s, y)
- char *s;
- unsigned EMUSHORT *y;
+ const char *s;
+ UEMUSHORT *y;
{
asctoeg (s, y, 24);
}
/* Convert ASCII string S to double precision value Y. */
-static void
+static void
asctoe53 (s, y)
- char *s;
- unsigned EMUSHORT *y;
+ const char *s;
+ UEMUSHORT *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
}
/* Convert ASCII string S to double extended value Y. */
-static void
+static void
asctoe64 (s, y)
- char *s;
- unsigned EMUSHORT *y;
+ const char *s;
+ UEMUSHORT *y;
{
asctoeg (s, y, 64);
}
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Convert ASCII string S to 128-bit long double Y. */
-static void
+static void
asctoe113 (s, y)
- char *s;
- unsigned EMUSHORT *y;
+ const char *s;
+ UEMUSHORT *y;
{
asctoeg (s, y, 113);
}
+#endif
/* Convert ASCII string S to e type Y. */
-static void
+static void
asctoe (s, y)
- char *s;
- unsigned EMUSHORT *y;
+ const char *s;
+ UEMUSHORT *y;
{
asctoeg (s, y, NBITS);
}
/* Convert ASCII string SS to e type Y, with a specified rounding precision
- of OPREC bits. */
+ of OPREC bits. BASE is 16 for C99 hexadecimal floating constants. */
-static void
+static void
asctoeg (ss, y, oprec)
- char *ss;
- unsigned EMUSHORT *y;
+ const char *ss;
+ UEMUSHORT *y;
int oprec;
{
- unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
+ UEMUSHORT 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;
+ UEMUSHORT nsign;
char *sp, *s, *lstr;
+ int base = 10;
/* 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;
trail = 0;
nxtcom:
- k = *s - '0';
- if ((k >= 0) && (k <= 9))
+ k = hex_value (*s);
+ if ((k >= 0) && (k < base))
{
/* Ignore leading zeros */
if ((prec == 0) && (decflg == 0) && (k == 0))
if ((trail == 0) && (decflg != 0))
{
sp = s;
- while ((*sp >= '0') && (*sp <= '9'))
+ while (ISDIGIT (*sp) || (base == 16 && ISXDIGIT (*sp)))
++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';
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;
+ xt[NI - 2] = (UEMUSHORT) k;
eaddm (xt, yy);
}
else
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;
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 ',':
case 'I':
goto infinite;
default:
- error:
+ unexpected_char_error:
#ifdef NANS
einan (yy);
#else
/* Exponent interpretation */
expnt:
- /* 0.0eXXX is zero, regardless of XXX. Check for the 0.0. */
+ /* 0.0eXXX is zero, regardless of XXX. Check for the 0.0. */
for (k = 0; k < NI; k++)
{
if (yy[k] != 0)
}
if (*s == '+')
++s;
- while ((*s >= '0') && (*s <= '9'))
+ while (ISDIGIT (*s))
{
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);
}
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. */
while ((nexp > 0) && (yy[2] == 0))
}
lexp = (EXONE - 1 + NBITS) - k;
emdnorm (yy, lost, 0, lexp, 64);
+ lost = 0;
/* Convert to external format:
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);
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:
toibm (yy, y, DFmode);
break;
#endif
+#ifdef C4X
+ case 32:
+ toc4x (yy, y, HFmode);
+ break;
+#endif
+
case 53:
toe53 (yy, y);
break;
case 64:
toe64 (yy, y);
break;
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
case 113:
toe113 (yy, y);
break;
+#endif
case NBITS:
emovo (yy, y);
break;
/* Return Y = largest integer not greater than X (truncated toward minus
infinity). */
-static unsigned EMUSHORT bmask[] =
+static const UEMUSHORT bmask[] =
{
0xffff,
0xfffe,
0x0000,
};
-static void
+static void
efloor (x, y)
- unsigned EMUSHORT x[], y[];
+ const UEMUSHORT x[];
+ UEMUSHORT y[];
{
- register unsigned EMUSHORT *p;
+ UEMUSHORT *p;
int e, expon, i;
- unsigned EMUSHORT f[NE];
+ UEMUSHORT f[NE];
emov (x, f); /* leave in external format */
expon = (int) f[NE - 1];
/* truncate negatives toward minus infinity */
isitneg:
- if ((unsigned EMUSHORT) expon & (unsigned EMUSHORT) 0x8000)
+ if ((UEMUSHORT) expon & (UEMUSHORT) 0x8000)
{
for (i = 0; i < NE - 1; i++)
{
/* 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[];
+ const UEMUSHORT x[];
int *exp;
- unsigned EMUSHORT s[];
+ UEMUSHORT s[];
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
EMULONG li;
emovi (x, xi);
/* Return e type Y = X * 2^PWR2. */
-static void
+static void
eldexp (x, pwr2, y)
- unsigned EMUSHORT x[];
+ const UEMUSHORT x[];
int pwr2;
- unsigned EMUSHORT y[];
+ UEMUSHORT y[];
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
EMULONG li;
int i;
li = xi[1];
li += pwr2;
i = 0;
- emdnorm (xi, i, i, li, 64);
+ emdnorm (xi, i, i, li, !ROUND_TOWARDS_ZERO);
emovo (xi, y);
}
/* 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[];
+ const UEMUSHORT a[], b[];
+ UEMUSHORT c[];
{
- unsigned EMUSHORT den[NI], num[NI];
+ UEMUSHORT den[NI], num[NI];
#ifdef NANS
if (eisinf (b)
/* Return quotient of exploded e-types NUM / DEN in EQUOT,
remainder in NUM. */
-static void
+static void
eiremain (den, num)
- unsigned EMUSHORT den[], num[];
+ UEMUSHORT den[], num[];
{
EMULONG ld, ln;
- unsigned EMUSHORT j;
+ UEMUSHORT j;
ld = den[E];
ld -= enormlz (den);
}
/* Report an error condition CODE encountered in function NAME.
- CODE is one of the following:
Mnemonic Value Significance
-
+
DOMAIN 1 argument domain error
SING 2 function singularity
OVERFLOW 3 overflow range error
INVALID 7 NaN - producing operation
EDOM 33 Unix domain error code
ERANGE 34 Unix range error code
-
+
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"
-};
-
int merror = 0;
extern int merror;
-static void
+static void
mtherr (name, code)
- char *name;
+ const char *name;
int code;
{
- char errstr[80];
-
/* The string passed by the calling program is supposed to be the
name of the function in which the error occurred.
The code argument selects which error message string will be printed. */
- if ((code <= 0) || (code >= NMSGS))
- code = 0;
- sprintf (errstr, " %s %s error", name, ermsg[code]);
+ 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 D to e type E. */
-static void
+static void
dectoe (d, e)
- unsigned EMUSHORT *d;
- unsigned EMUSHORT *e;
+ const UEMUSHORT *d;
+ UEMUSHORT *e;
{
- unsigned EMUSHORT y[NI];
- register unsigned EMUSHORT r, *p;
+ UEMUSHORT y[NI];
+ UEMUSHORT r, *p;
ecleaz (y); /* start with a zero */
p = y; /* point to our number */
/* Convert e type X to DEC double precision D. */
-static void
+static void
etodec (x, d)
- unsigned EMUSHORT *x, *d;
+ const UEMUSHORT *x;
+ UEMUSHORT *d;
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
EMULONG exp;
int rndsav;
/* Round off to nearest or even. */
rndsav = rndprc;
rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
todec (xi, d);
}
/* Convert exploded e-type X, that has already been rounded to
56-bit precision, to DEC format double Y. */
-static void
+static void
todec (x, y)
- unsigned EMUSHORT *x, *y;
+ UEMUSHORT *x, *y;
{
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
+ UEMUSHORT i;
+ UEMUSHORT *p;
p = x;
*y = 0;
#ifdef IBM
/* Convert IBM single/double precision to e type. */
-static void
+static void
ibmtoe (d, e, mode)
- unsigned EMUSHORT *d;
- unsigned EMUSHORT *e;
+ const UEMUSHORT *d;
+ UEMUSHORT *e;
enum machine_mode mode;
{
- unsigned EMUSHORT y[NI];
- register unsigned EMUSHORT r, *p;
- int rndsav;
+ UEMUSHORT y[NI];
+ UEMUSHORT r, *p;
ecleaz (y); /* start with a zero */
p = y; /* point to our number */
/* Convert e type to IBM single/double precision. */
-static void
+static void
etoibm (x, d, mode)
- unsigned EMUSHORT *x, *d;
+ const UEMUSHORT *x;
+ UEMUSHORT *d;
enum machine_mode mode;
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
EMULONG exp;
int rndsav;
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
toibm (xi, d, mode);
}
-static void
+static void
toibm (x, y, mode)
- unsigned EMUSHORT *x, *y;
+ UEMUSHORT *x, *y;
enum machine_mode mode;
{
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
+ UEMUSHORT i;
+ UEMUSHORT *p;
int r;
p = x;
}
#endif /* IBM */
+
+#ifdef C4X
+/* Convert C4X single/double precision to e type. */
+
+static void
+c4xtoe (d, e, mode)
+ const UEMUSHORT *d;
+ UEMUSHORT *e;
+ enum machine_mode mode;
+{
+ UEMUSHORT y[NI];
+ UEMUSHORT dn[4];
+ int r;
+ int isnegative;
+ int size;
+ int i;
+ int carry;
+
+ dn[0] = d[0];
+ dn[1] = d[1];
+ if (mode != QFmode)
+ {
+ dn[2] = d[3] << 8;
+ dn[3] = 0;
+ }
+
+ /* Short-circuit the zero case. */
+ if ((dn[0] == 0x8000)
+ && (dn[1] == 0x0000)
+ && ((mode == QFmode) || ((dn[2] == 0x0000) && (dn[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 = dn[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] = dn[0] & 0x7f;
+
+ y[M+1] = dn[1];
+ if (mode != QFmode) /* There are only 2 words in QFmode. */
+ {
+ y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */
+ y[M+3] = dn[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] = (dn[0] & 0x7f) | 0x80;
+
+ y[M+1] = dn[1];
+ if (mode != QFmode) /* There are only 2 words in QFmode. */
+ {
+ y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */
+ y[M+3] = dn[3];
+ }
+ eshift (y, -8);
+ }
+
+ emovo (y, e);
+}
+
+
+/* Convert e type to C4X single/double precision. */
+
+static void
+etoc4x (x, d, mode)
+ const UEMUSHORT *x;
+ UEMUSHORT *d;
+ enum machine_mode mode;
+{
+ UEMUSHORT 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, !ROUND_TOWARDS_ZERO);
+ rndprc = rndsav;
+ toc4x (xi, d, mode);
+}
+
+static void
+toc4x (x, y, mode)
+ UEMUSHORT *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;
+ y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
+ y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
+ }
+#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];
+ y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
+ y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
+ }
+}
+#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
TFMODE_NAN;
#else
#ifdef IEEE
-unsigned EMUSHORT TFbignan[8] =
+static const UEMUSHORT TFbignan[8] =
{0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
-unsigned EMUSHORT TFlittlenan[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff};
+static const UEMUSHORT TFlittlenan[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff};
#endif
#endif
XFMODE_NAN;
#else
#ifdef IEEE
-unsigned EMUSHORT XFbignan[6] =
+static const UEMUSHORT XFbignan[6] =
{0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
-unsigned EMUSHORT XFlittlenan[6] = {0, 0, 0, 0xc000, 0xffff, 0};
+static const UEMUSHORT XFlittlenan[6] = {0, 0, 0, 0xc000, 0xffff, 0};
#endif
#endif
DFMODE_NAN;
#else
#ifdef IEEE
-unsigned EMUSHORT DFbignan[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
-unsigned EMUSHORT DFlittlenan[4] = {0, 0, 0, 0xfff8};
+static const UEMUSHORT DFbignan[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
+static const UEMUSHORT DFlittlenan[4] = {0, 0, 0, 0xfff8};
#endif
#endif
SFMODE_NAN;
#else
#ifdef IEEE
-unsigned EMUSHORT SFbignan[2] = {0x7fff, 0xffff};
-unsigned EMUSHORT SFlittlenan[2] = {0, 0xffc0};
+static const UEMUSHORT SFbignan[2] = {0x7fff, 0xffff};
+static const UEMUSHORT SFlittlenan[2] = {0, 0xffc0};
#endif
#endif
+#ifdef NANS
static void
make_nan (nan, sign, mode)
- unsigned EMUSHORT *nan;
+ UEMUSHORT *nan;
int sign;
enum machine_mode mode;
{
int n;
- unsigned EMUSHORT *p;
+ const UEMUSHORT *p;
+ int size;
+ size = GET_MODE_BITSIZE (mode);
+ if (LARGEST_EXPONENT_IS_NORMAL (size))
+ {
+ warning ("%d-bit floats cannot hold NaNs", size);
+ saturate (nan, sign, size, 0);
+ return;
+ }
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)
+#if !defined(DEC) && !defined(IBM) && !defined(C4X)
case TFmode:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
n = 8;
if (REAL_WORDS_BIG_ENDIAN)
p = TFbignan;
else
p = TFlittlenan;
break;
+#endif
+ /* FALLTHRU */
+
case XFmode:
n = 6;
if (REAL_WORDS_BIG_ENDIAN)
else
p = XFlittlenan;
break;
+
case DFmode:
n = 4;
if (REAL_WORDS_BIG_ENDIAN)
else
p = DFlittlenan;
break;
- case HFmode:
+
case SFmode:
+ case HFmode:
n = 2;
if (REAL_WORDS_BIG_ENDIAN)
p = SFbignan;
p = SFlittlenan;
break;
#endif
+
default:
abort ();
}
if (REAL_WORDS_BIG_ENDIAN)
- *nan++ = (sign << 15) | *p++;
+ *nan++ = (sign << 15) | (*p++ & 0x7fff);
while (--n != 0)
*nan++ = *p++;
if (! REAL_WORDS_BIG_ENDIAN)
- *nan = (sign << 15) | *p;
+ *nan = (sign << 15) | (*p & 0x7fff);
}
+#endif /* NANS */
+
+
+/* Create a saturation value for a SIZE-bit float, assuming that
+ LARGEST_EXPONENT_IS_NORMAL (SIZE).
+
+ If SIGN is true, fill X with the most negative value, otherwise fill
+ it with the most positive value. WARN is true if the function should
+ warn about overflow. */
+
+static void
+saturate (x, sign, size, warn)
+ UEMUSHORT *x;
+ int sign, size, warn;
+{
+ int i;
+
+ if (warn && extra_warnings)
+ warning ("value exceeds the range of a %d-bit float", size);
+
+ /* Create the most negative value. */
+ for (i = 0; i < size / EMUSHORT_SIZE; i++)
+ x[i] = 0xffff;
+
+ /* Make it positive, if necessary. */
+ if (!sign)
+ x[REAL_WORDS_BIG_ENDIAN? 0 : i - 1] = 0x7fff;
+}
+
/* This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
long f;
{
REAL_VALUE_TYPE r;
- unsigned EMUSHORT s[2];
- unsigned EMUSHORT e[NE];
+ UEMUSHORT s[2];
+ UEMUSHORT 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;
+ s[0] = (UEMUSHORT) (f >> 16);
+ s[1] = (UEMUSHORT) f;
}
else
{
- s[0] = (unsigned EMUSHORT) f;
- s[1] = (unsigned EMUSHORT) (f >> 16);
+ s[0] = (UEMUSHORT) f;
+ s[1] = (UEMUSHORT) (f >> 16);
}
- /* Convert and promote the target float to E-type. */
+ /* Convert and promote the target float to E-type. */
e24toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
+ /* Output E-type to REAL_VALUE_TYPE. */
PUT_REAL (e, &r);
return r;
}
long d[];
{
REAL_VALUE_TYPE r;
- unsigned EMUSHORT s[4];
- unsigned EMUSHORT e[NE];
+ UEMUSHORT s[4];
+ UEMUSHORT 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];
+ s[0] = (UEMUSHORT) (d[0] >> 16);
+ s[1] = (UEMUSHORT) d[0];
+ s[2] = (UEMUSHORT) (d[1] >> 16);
+ s[3] = (UEMUSHORT) 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);
+ s[0] = (UEMUSHORT) d[0];
+ s[1] = (UEMUSHORT) (d[0] >> 16);
+ s[2] = (UEMUSHORT) d[1];
+ s[3] = (UEMUSHORT) (d[1] >> 16);
}
- /* 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;
}
HOST_WIDE_INT f;
{
REAL_VALUE_TYPE r;
- unsigned EMUSHORT s[2];
- unsigned EMUSHORT e[NE];
+ UEMUSHORT s[2];
+ UEMUSHORT 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;
+ s[0] = (UEMUSHORT) (f >> 16);
+ s[1] = (UEMUSHORT) f;
}
else
{
- s[0] = (unsigned EMUSHORT) f;
- s[1] = (unsigned EMUSHORT) (f >> 16);
+ s[0] = (UEMUSHORT) f;
+ s[1] = (UEMUSHORT) (f >> 16);
}
/* Convert and promote the target float to E-type. */
e24toe (s, e);
HOST_WIDE_INT d[];
{
REAL_VALUE_TYPE r;
- unsigned EMUSHORT s[4];
- unsigned EMUSHORT e[NE];
+ UEMUSHORT s[4];
+ UEMUSHORT 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];
#if HOST_BITS_PER_WIDE_INT == 32
- s[2] = (unsigned EMUSHORT) (d[1] >> 16);
- s[3] = (unsigned EMUSHORT) d[1];
+ s[0] = (UEMUSHORT) (d[0] >> 16);
+ s[1] = (UEMUSHORT) d[0];
+ s[2] = (UEMUSHORT) (d[1] >> 16);
+ s[3] = (UEMUSHORT) 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] = (UEMUSHORT) (d[0] >> 48);
+ s[1] = (UEMUSHORT) (d[0] >> 32);
+ s[2] = (UEMUSHORT) (d[0] >> 16);
+ s[3] = (UEMUSHORT) d[0];
#endif
}
else
{
/* Target float words are little-endian. */
- s[0] = (unsigned EMUSHORT) d[0];
- s[1] = (unsigned EMUSHORT) (d[0] >> 16);
+ s[0] = (UEMUSHORT) d[0];
+ s[1] = (UEMUSHORT) (d[0] >> 16);
#if HOST_BITS_PER_WIDE_INT == 32
- s[2] = (unsigned EMUSHORT) d[1];
- s[3] = (unsigned EMUSHORT) (d[1] >> 16);
+ s[2] = (UEMUSHORT) d[1];
+ s[3] = (UEMUSHORT) (d[1] >> 16);
#else
- s[2] = (unsigned EMUSHORT) (d[0] >> 32);
- s[3] = (unsigned EMUSHORT) (d[0] >> 48);
+ s[2] = (UEMUSHORT) (d[0] >> 32);
+ s[3] = (UEMUSHORT) (d[0] >> 48);
#endif
}
/* Convert target double to E-type. */
static void
uditoe (di, e)
- unsigned EMUSHORT *di; /* Address of the 64-bit int. */
- unsigned EMUSHORT *e;
+ const UEMUSHORT *di; /* Address of the 64-bit int. */
+ UEMUSHORT *e;
{
- unsigned EMUSHORT yi[NI];
+ UEMUSHORT yi[NI];
int k;
ecleaz (yi);
if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
ecleaz (yi); /* it was zero */
else
- yi[E] -= (unsigned EMUSHORT) k;/* subtract shift count from exponent */
+ yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
emovo (yi, e);
}
static void
ditoe (di, e)
- unsigned EMUSHORT *di; /* Address of the 64-bit int. */
- unsigned EMUSHORT *e;
+ const UEMUSHORT *di; /* Address of the 64-bit int. */
+ UEMUSHORT *e;
{
unsigned EMULONG acc;
- unsigned EMUSHORT yi[NI];
- unsigned EMUSHORT carry;
+ UEMUSHORT yi[NI];
+ UEMUSHORT carry;
int k, sign;
ecleaz (yi);
if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
ecleaz (yi); /* it was zero */
else
- yi[E] -= (unsigned EMUSHORT) k;/* subtract shift count from exponent */
+ yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
emovo (yi, e);
if (sign)
eneg (e);
/* Convert e-type to unsigned 64-bit int. */
-static void
+static void
etoudi (x, i)
- unsigned EMUSHORT *x;
- unsigned EMUSHORT *i;
+ const UEMUSHORT *x;
+ UEMUSHORT *i;
{
- unsigned EMUSHORT xi[NI];
+ UEMUSHORT xi[NI];
int j, k;
emovi (x, xi);
/* Convert e-type to signed 64-bit int. */
-static void
+static void
etodi (x, i)
- unsigned EMUSHORT *x;
- unsigned EMUSHORT *i;
+ const UEMUSHORT *x;
+ UEMUSHORT *i;
{
unsigned EMULONG acc;
- unsigned EMUSHORT xi[NI];
- unsigned EMUSHORT carry;
- unsigned EMUSHORT *isave;
+ UEMUSHORT xi[NI];
+ UEMUSHORT carry;
+ UEMUSHORT *isave;
int j, k;
emovi (x, xi);
static int esqinited = 0;
static unsigned short sqrndbit[NI];
-static void
+static void
esqrt (x, y)
- unsigned EMUSHORT *x, *y;
+ const UEMUSHORT *x;
+ UEMUSHORT *y;
{
- unsigned EMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
+ UEMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
EMULONG m, exp;
int i, j, k, n, nlups;
k |= (int) num[i];
/* Renormalize and round off. */
- emdnorm (sq, k, 0, exp, 64);
+ emdnorm (sq, k, 0, exp, !ROUND_TOWARDS_ZERO);
emovo (sq, y);
}
#endif
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 (GET_MODE_BITSIZE (mode))
{
case 32:
+
+#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
+ return 56;
+#endif
+
return 24;
case 64:
#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
return 56;
#else
+#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
+ return 56;
+#else
abort ();
#endif
#endif
#endif
+#endif
case 96:
return 64;
+
case 128:
+#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
return 113;
+#else
+ return 64;
+#endif
default:
abort ();