/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
and support for XFmode IEEE extended real floating point arithmetic.
- Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
This file is part of GNU CC.
#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).
both mean DFmode. In this case, the software floating-point
support available here is activated by writing
#define REAL_ARITHMETIC
- in tm.h.
+ in tm.h.
The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
and may deactivate XFmode since `long double' is used to refer
- to both modes.
+ to both modes. Defining INTEL_EXTENDED_IEEE_FORMAT at the same
+ time enables 80387-style 80-bit floats in a 128-bit padded
+ image, as seen on IA-64.
The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,
contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,
A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
in memory, with no holes. */
-#if LONG_DOUBLE_TYPE_SIZE == 96
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 96 || \
+ (defined(INTEL_EXTENDED_IEEE_FORMAT) && MAX_LONG_DOUBLE_TYPE_SIZE == 128)
/* Number of 16 bit words in external e type format */
-#define NE 6
-#define MAXDECEXP 4932
-#define MINDECEXP -4956
-#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
-#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
-#else /* no XFmode */
-#if LONG_DOUBLE_TYPE_SIZE == 128
-#define NE 10
-#define MAXDECEXP 4932
-#define MINDECEXP -4977
-#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
-#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
+# define NE 6
+# define MAXDECEXP 4932
+# define MINDECEXP -4956
+# define GET_REAL(r,e) memcpy ((char *)(e), (char *)(r), 2*NE)
+# define PUT_REAL(e,r) \
+ do { \
+ memcpy ((char *)(r), (char *)(e), 2*NE); \
+ if (2*NE < sizeof(*r)) \
+ memset ((char *)(r) + 2*NE, 0, sizeof(*r) - 2*NE); \
+ } while (0)
+# else /* no XFmode */
+# if MAX_LONG_DOUBLE_TYPE_SIZE == 128
+# define NE 10
+# define MAXDECEXP 4932
+# define MINDECEXP -4977
+# define GET_REAL(r,e) memcpy ((char *)(e), (char *)(r), 2*NE)
+# define PUT_REAL(e,r) \
+ do { \
+ memcpy ((char *)(r), (char *)(e), 2*NE); \
+ if (2*NE < sizeof(*r)) \
+ memset ((char *)(r) + 2*NE, 0, sizeof(*r) - 2*NE); \
+ } while (0)
#else
#define NE 6
#define MAXDECEXP 4932
/* 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 ((unsigned EMUSHORT *) (r), (e)); \
+ else \
+ { \
+ unsigned EMUSHORT w[4]; \
+ memcpy (&w[3], ((EMUSHORT *) r), sizeof (EMUSHORT)); \
+ memcpy (&w[2], ((EMUSHORT *) r) + 1, sizeof (EMUSHORT)); \
+ memcpy (&w[1], ((EMUSHORT *) r) + 2, sizeof (EMUSHORT)); \
+ memcpy (&w[0], ((EMUSHORT *) r) + 3, sizeof (EMUSHORT)); \
+ e53toe (w, (e)); \
+ } \
} while (0)
-#define PUT_REAL(e,r) \
-do { \
- if (HOST_FLOAT_WORDS_BIG_ENDIAN == 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), (unsigned EMUSHORT *) (r)); \
+ else \
+ { \
+ unsigned EMUSHORT w[4]; \
+ etoe53 ((e), w); \
+ memcpy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT)); \
+ memcpy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT)); \
+ memcpy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT)); \
+ memcpy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT)); \
+ } \
} while (0)
#else /* not REAL_ARITHMETIC */
/* The exponent of 1.0 */
#define EXONE (0x3fff)
+#if defined(HOST_EBCDIC)
+/* bit 8 is significant in EBCDIC */
+#define CHARMASK 0xff
+#else
+#define CHARMASK 0x7f
+#endif
+
extern int extra_warnings;
extern unsigned EMUSHORT ezero[], ehalf[], eone[], etwo[];
extern unsigned EMUSHORT elog2[], esqrt2[];
-static void endian PROTO((unsigned EMUSHORT *, long *,
+static void endian PARAMS ((unsigned EMUSHORT *, long *,
enum machine_mode));
-static void eclear PROTO((unsigned EMUSHORT *));
-static void emov PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void eclear PARAMS ((unsigned EMUSHORT *));
+static void emov PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
-static void eabs PROTO((unsigned EMUSHORT *));
-#endif
-static void eneg PROTO((unsigned EMUSHORT *));
-static int eisneg PROTO((unsigned EMUSHORT *));
-static int eisinf PROTO((unsigned EMUSHORT *));
-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 eabs PARAMS ((unsigned EMUSHORT *));
+#endif
+static void eneg PARAMS ((unsigned EMUSHORT *));
+static int eisneg PARAMS ((unsigned EMUSHORT *));
+static int eisinf PARAMS ((unsigned EMUSHORT *));
+static int eisnan PARAMS ((unsigned EMUSHORT *));
+static void einfin PARAMS ((unsigned EMUSHORT *));
+#ifdef NANS
+static void enan PARAMS ((unsigned EMUSHORT *, int));
+static void einan PARAMS ((unsigned EMUSHORT *));
+static int eiisnan PARAMS ((unsigned EMUSHORT *));
+static int eiisneg PARAMS ((unsigned EMUSHORT *));
+static void make_nan PARAMS ((unsigned EMUSHORT *, int, enum machine_mode));
+#endif
+static void emovi PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void emovo PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void ecleaz PARAMS ((unsigned EMUSHORT *));
+static void ecleazs PARAMS ((unsigned EMUSHORT *));
+static void emovz PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
-static void eiinfin PROTO((unsigned EMUSHORT *));
-#endif
-static int eiisinf PROTO((unsigned EMUSHORT *));
-static int ecmpm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void eshdn1 PROTO((unsigned EMUSHORT *));
-static void eshup1 PROTO((unsigned EMUSHORT *));
-static void eshdn8 PROTO((unsigned EMUSHORT *));
-static void eshup8 PROTO((unsigned EMUSHORT *));
-static void eshup6 PROTO((unsigned EMUSHORT *));
-static void eshdn6 PROTO((unsigned EMUSHORT *));
-static void eaddm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));\f
-static void esubm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void m16m PROTO((unsigned int, unsigned short *,
+static void eiinfin PARAMS ((unsigned EMUSHORT *));
+#endif
+#ifdef INFINITY
+static int eiisinf PARAMS ((unsigned EMUSHORT *));
+#endif
+static int ecmpm PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void eshdn1 PARAMS ((unsigned EMUSHORT *));
+static void eshup1 PARAMS ((unsigned EMUSHORT *));
+static void eshdn8 PARAMS ((unsigned EMUSHORT *));
+static void eshup8 PARAMS ((unsigned EMUSHORT *));
+static void eshup6 PARAMS ((unsigned EMUSHORT *));
+static void eshdn6 PARAMS ((unsigned EMUSHORT *));
+static void eaddm PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));\f
+static void esubm PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void m16m PARAMS ((unsigned int, unsigned short *,
unsigned short *));
-static int edivm PROTO((unsigned short *, unsigned short *));
-static int emulm PROTO((unsigned short *, unsigned short *));
-static void emdnorm PROTO((unsigned EMUSHORT *, int, int, EMULONG, int));
-static void esub PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static int edivm PARAMS ((unsigned short *, unsigned short *));
+static int emulm PARAMS ((unsigned short *, unsigned short *));
+static void emdnorm PARAMS ((unsigned EMUSHORT *, int, int, EMULONG, int));
+static void esub PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
-static void eadd PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void eadd PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
-static void eadd1 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void eadd1 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
-static void ediv PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void ediv PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
-static void emul PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void emul PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
-static void e53toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void e64toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void e113toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void e24toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe113 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void toe113 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe64 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void toe64 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe53 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void toe53 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoe24 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void toe24 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static int ecmp PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void e53toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void e64toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+static void e113toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+#endif
+static void e24toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe113 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe113 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe64 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe64 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe53 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe53 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoe24 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void toe24 PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static int ecmp PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
-static void eround PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void eround PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
-static void ltoe PROTO((HOST_WIDE_INT *, unsigned EMUSHORT *));
-static void ultoe PROTO((unsigned HOST_WIDE_INT *, unsigned EMUSHORT *));
-static void eifrac PROTO((unsigned EMUSHORT *, HOST_WIDE_INT *,
+static void ltoe PARAMS ((HOST_WIDE_INT *, unsigned EMUSHORT *));
+static void ultoe PARAMS ((unsigned HOST_WIDE_INT *, unsigned EMUSHORT *));
+static void eifrac PARAMS ((unsigned EMUSHORT *, HOST_WIDE_INT *,
unsigned EMUSHORT *));
-static void euifrac PROTO((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
+static void euifrac PARAMS ((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
unsigned EMUSHORT *));
-static int eshift PROTO((unsigned EMUSHORT *, int));
-static int enormlz PROTO((unsigned EMUSHORT *));
+static int eshift PARAMS ((unsigned EMUSHORT *, int));
+static int enormlz PARAMS ((unsigned EMUSHORT *));
#if 0
-static void e24toasc PROTO((unsigned EMUSHORT *, char *, int));
-static void e53toasc PROTO((unsigned EMUSHORT *, char *, int));
-static void e64toasc PROTO((unsigned EMUSHORT *, char *, int));
-static void e113toasc PROTO((unsigned EMUSHORT *, char *, int));
+static void e24toasc PARAMS ((unsigned EMUSHORT *, char *, int));
+static void e53toasc PARAMS ((unsigned EMUSHORT *, char *, int));
+static void e64toasc PARAMS ((unsigned EMUSHORT *, char *, int));
+static void e113toasc PARAMS ((unsigned EMUSHORT *, char *, int));
#endif /* 0 */
-static void etoasc 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 etoasc PARAMS ((unsigned EMUSHORT *, char *, int));
+static void asctoe24 PARAMS ((const char *, unsigned EMUSHORT *));
+static void asctoe53 PARAMS ((const char *, unsigned EMUSHORT *));
+static void asctoe64 PARAMS ((const char *, unsigned EMUSHORT *));
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+static void asctoe113 PARAMS ((const char *, unsigned EMUSHORT *));
+#endif
+static void asctoe PARAMS ((const char *, unsigned EMUSHORT *));
+static void asctoeg PARAMS ((const char *, unsigned EMUSHORT *, int));
+static void efloor PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
-static void efrexp PROTO((unsigned EMUSHORT *, int *,
+static void efrexp PARAMS ((unsigned EMUSHORT *, int *,
unsigned EMUSHORT *));
#endif
-static void eldexp PROTO((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
+static void eldexp PARAMS ((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
#if 0
-static void eremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void eremain PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
#endif
-static void eiremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void mtherr PROTO((char *, int));
+static void eiremain PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+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 ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etodec PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void todec PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
#ifdef IBM
-static void ibmtoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void ibmtoe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
-static void etoibm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void etoibm PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
-static void toibm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void toibm PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
#endif
#ifdef C4X
-static void c4xtoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void c4xtoe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
-static void etoc4x PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void etoc4x PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
-static void toc4x PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
+static void toc4x PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
#endif
-static void make_nan PROTO((unsigned EMUSHORT *, int, enum machine_mode));
#if 0
-static void uditoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void ditoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etoudi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void etodi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void esqrt PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void uditoe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void ditoe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etoudi PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void etodi PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
+static void esqrt PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
\f
/* Copy 32-bit numbers obtained from array containing 16-bit numbers,
swapping ends if required, into output array of longs. The
result is normally passed to fprintf by the ASM_OUTPUT_ macros. */
-static void
+static void
endian (e, x, mode)
unsigned EMUSHORT e[];
long x[];
switch (mode)
{
case TFmode:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
/* Swap halfwords in the fourth long. */
th = (unsigned long) e[6] & 0xffff;
t = (unsigned long) e[7] & 0xffff;
t |= th << 16;
x[3] = (long) t;
+#endif
case XFmode:
/* Swap halfwords in the third long. */
switch (mode)
{
case TFmode:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
/* Pack the fourth long. */
th = (unsigned long) e[7] & 0xffff;
t = (unsigned long) e[6] & 0xffff;
t |= th << 16;
x[3] = (long) t;
+#endif
case XFmode:
/* Pack the third long.
/* This is the implementation of the REAL_ARITHMETIC macro. */
-void
+void
earith (value, icode, r1, r2)
REAL_VALUE_TYPE *value;
int icode;
/* 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;
{
/* 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;
{
}
-/* 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];
e53toe (tem, e);
break;
- case XFmode:
- asctoe64 (s, tem);
- e64toe (tem, e);
- break;
-
case TFmode:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
asctoe113 (s, tem);
e113toe (tem, e);
break;
+#endif
+ /* FALLTHRU */
+
+ case XFmode:
+ asctoe64 (s, tem);
+ e64toe (tem, e);
+ break;
default:
asctoe (s, e);
/* Expansion of REAL_NEGATE. */
-REAL_VALUE_TYPE
+REAL_VALUE_TYPE
ereal_negate (x)
REAL_VALUE_TYPE x;
{
/* REAL_VALUE_FROM_INT macro. */
-void
+void
ereal_from_int (d, i, j, mode)
REAL_VALUE_TYPE *d;
HOST_WIDE_INT i, j;
break;
case 128:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
etoe113 (dg, df);
e113toe (df, dg);
+#else
+ etoe64 (dg, df);
+ e64toe (df, dg);
+#endif
break;
default:
/* 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;
break;
case 128:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
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;
int
target_isinf (x)
- REAL_VALUE_TYPE x;
+ REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
{
+#ifdef INFINITY
unsigned EMUSHORT e[NE];
-#ifdef INFINITY
GET_REAL (&x, e);
return (eisinf (e));
#else
int
target_isnan (x)
- REAL_VALUE_TYPE x;
+ REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
{
+#ifdef NANS
unsigned EMUSHORT e[NE];
-#ifdef NANS
GET_REAL (&x, e);
return (eisnan (e));
#else
switch (mode)
{
case TFmode:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
etoe113 (e, t);
e113toe (t, t);
break;
+#endif
+ /* FALLTHRU */
case XFmode:
etoe64 (e, t);
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[];
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[];
/* 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[];
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
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
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 && !defined(INTEL_EXTENDED_IEEE_FORMAT)
/* 0.0 */
unsigned EMUSHORT ezero[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
/* Clear out entire e-type number X. */
-static void
+static void
eclear (x)
register unsigned EMUSHORT *x;
{
/* Move e-type number from A to B. */
-static void
+static void
emov (a, b)
register unsigned EMUSHORT *a, *b;
{
#if 0
/* Absolute value of e-type X. */
-static void
+static void
eabs (x)
unsigned EMUSHORT x[];
{
/* sign is top bit of last word of external format */
- x[NE - 1] &= 0x7fff;
+ x[NE - 1] &= 0x7fff;
}
#endif /* 0 */
/* Negate the e-type number X. */
-static void
+static void
eneg (x)
unsigned EMUSHORT x[];
{
/* Return 1 if sign bit of e-type number X is nonzero, else zero. */
-static int
+static int
eisneg (x)
unsigned EMUSHORT x[];
{
/* Return 1 if e-type number X is infinity, else return zero. */
-static int
+static int
eisinf (x)
unsigned EMUSHORT x[];
{
/* Check if e-type number is not a number. The bit pattern is one that we
defined, so we know for sure how to detect it. */
-static int
+static int
eisnan (x)
- unsigned EMUSHORT x[];
+ unsigned EMUSHORT x[] ATTRIBUTE_UNUSED;
{
#ifdef NANS
int i;
/* 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;
{
This generates Intel's quiet NaN pattern for extended real.
The exponent is 7fff, the leading mantissa word is c000. */
-static void
+#ifdef NANS
+static void
enan (x, sign)
register unsigned EMUSHORT *x;
int sign;
*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;
{
/* Move out exploded e-type number A, converting it to e type B. */
-static void
+static void
emovo (a, b)
unsigned EMUSHORT *a, *b;
{
/* Clear out exploded e-type number XI. */
-static void
+static void
ecleaz (xi)
register unsigned EMUSHORT *xi;
{
/* Clear out exploded e-type XI, but don't touch the sign. */
-static void
+static void
ecleazs (xi)
register unsigned EMUSHORT *xi;
{
/* Move exploded e-type number from A to B. */
-static void
+static void
emovz (a, b)
register unsigned EMUSHORT *a, *b;
{
The explicit pattern for this is maximum exponent and
top two significant bits set. */
+#ifdef NANS
static void
einan (x)
unsigned EMUSHORT 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[];
{
}
return (0);
}
+#endif /* NANS */
/* Return nonzero if sign of exploded e-type X is nonzero. */
-static int
+#ifdef NANS
+static int
eiisneg (x)
unsigned EMUSHORT x[];
{
return x[0] != 0;
}
+#endif /* NANS */
#if 0
/* Fill exploded e-type X with infinity pattern.
/* Return nonzero if exploded e-type X is infinite. */
-static int
+#ifdef INFINITY
+static int
eiisinf (x)
unsigned EMUSHORT x[];
{
return (1);
return (0);
}
-
+#endif /* INFINITY */
/* Compare significands of numbers in internal exploded e-type format.
Guard words are included in the comparison.
/* Shift significand of exploded e-type X down by 1 bit. */
-static void
+static void
eshdn1 (x)
register unsigned EMUSHORT *x;
{
/* Shift significand of exploded e-type X up by 1 bit. */
-static void
+static void
eshup1 (x)
register unsigned EMUSHORT *x;
{
/* Shift significand of exploded e-type X down by 8 bits. */
-static void
+static void
eshdn8 (x)
register unsigned EMUSHORT *x;
{
/* Shift significand of exploded e-type X up by 8 bits. */
-static void
+static void
eshup8 (x)
register unsigned EMUSHORT *x;
{
/* Shift significand of exploded e-type X up by 16 bits. */
-static void
+static void
eshup6 (x)
register unsigned EMUSHORT *x;
{
/* Shift significand of exploded e-type X down by 16 bits. */
-static void
+static void
eshdn6 (x)
register unsigned EMUSHORT *x;
{
/* Add significands of exploded e-type X and Y. X + Y replaces Y. */
-static void
+static void
eaddm (x, y)
unsigned EMUSHORT *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;
{
/* Divide significands */
-int
+int
edivm (den, num)
unsigned EMUSHORT den[], num[];
{
/* Multiply significands */
-int
+int
emulm (a, b)
unsigned EMUSHORT a[], b[];
{
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
static int re = 0;
static unsigned EMUSHORT rbit[NI];
-static void
+static void
emdnorm (s, lost, subflg, exp, rcntrl)
unsigned EMUSHORT s[];
int lost;
static int subflg = 0;
-static void
+static void
esub (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
/* Add. C = A + B, all e type. */
-static void
+static void
eadd (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
/* Arithmetic common to both addition and subtraction. */
-static void
+static void
eadd1 (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
/* Divide: C = B/A, all e type. */
-static void
+static void
ediv (a, b, c)
unsigned EMUSHORT *a, *b, *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;
{
#endif
eshift (yy, -5);
if (denorm)
- {
+ {
/* If zero exponent, then normalize the significand. */
if ((k = enormlz (yy)) > NBITS)
ecleazs (yy);
/* Convert double extended precision float PE to e type Y. */
-static void
+static void
e64toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
*q++ = *p++;
}
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
/* Convert 128-bit long double precision float PE to e type Y. */
-static void
+static void
e113toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
}
emovo (yy, y);
}
+#endif
/* Convert single precision float PE to e type Y. */
-static void
+static void
e24toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
/* Convert e-type X to IEEE 128-bit long double format E. */
-static void
+static void
etoe113 (x, e)
unsigned EMUSHORT *x, *e;
{
rndprc = 113;
emdnorm (xi, 0, 0, exp, 64);
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;
{
/* Convert e-type X to IEEE double extended format E. */
-static void
+static void
etoe64 (x, e)
unsigned EMUSHORT *x, *e;
{
rndprc = 64;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
+#ifdef INFINITY
nonorm:
+#endif
toe64 (xi, e);
}
/* Convert exploded e-type X, that has already been rounded to
64-bit precision, to IEEE double extended format Y. */
-static void
+static void
toe64 (a, b)
unsigned EMUSHORT *a, *b;
{
else
{
q = b + 4; /* point to output exponent */
-#if LONG_DOUBLE_TYPE_SIZE == 96
- /* Clear the last two bytes of 12-byte Intel format */
+ /* Clear the last two bytes of 12-byte Intel format. q is pointing
+ into an array of size 6 (e.g. x[NE]), so the last two bytes are
+ always there, and there are never more bytes, even when we are using
+ INTEL_EXTENDED_IEEE_FORMAT. */
*(q+1) = 0;
-#endif
}
#endif
#ifdef DEC
/* Convert e-type X to DEC-format double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
/* 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;
{
#ifdef IBM
/* Convert e-type X to IBM 370-format double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
/* 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;
{
#ifdef C4X
/* Convert e-type X to C4X-format long double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
/* 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;
{
/* Convert e-type X to IEEE double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
rndprc = 53;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
+#ifdef INFINITY
nonorm:
+#endif
toe53 (xi, e);
}
/* Convert exploded e-type X, that has already been rounded to
53-bit precision, to IEEE double Y. */
-static void
+static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
#ifdef IBM
/* Convert e-type X to IBM 370 float E. */
-static void
+static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
/* 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;
{
#ifdef C4X
/* Convert e-type X to C4X float E. */
-static void
+static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
/* 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;
{
/* 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;
{
rndprc = 24;
emdnorm (xi, 0, 0, exp, 64);
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;
{
#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;
{
#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;
{
/* Convert HOST_WIDE_INT LP to e type Y. */
-static void
+static void
ltoe (lp, y)
HOST_WIDE_INT *lp;
unsigned EMUSHORT *y;
/* 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;
The output e-type fraction FRAC is the positive fractional
part of abs (X). */
-static void
+static void
eifrac (x, i, frac)
unsigned EMUSHORT *x;
HOST_WIDE_INT *i;
FRAC of e-type X. A negative input yields integer output = 0 but
correct fraction. */
-static void
+static void
euifrac (x, i, frac)
unsigned EMUSHORT *x;
unsigned HOST_WIDE_INT *i;
/* Shift the significand of exploded e-type X up or down by SC bits. */
-static int
+static int
eshift (x, sc)
unsigned EMUSHORT *x;
int sc;
/* 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[];
{
#define NTEN 12
#define MAXP 4096
-#if LONG_DOUBLE_TYPE_SIZE == 128
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !defined(INTEL_EXTENDED_IEEE_FORMAT)
static unsigned EMUSHORT etens[NTEN + 1][NE] =
{
{0x6576, 0x4a92, 0x804a, 0x153f,
/* 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[];
char *string;
/* Convert double value X to ASCII string STRING with NDIG digits after
the decimal point. */
-static void
+static void
e53toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
/* Convert double extended value X to ASCII string STRING with NDIG digits
after the decimal point. */
-static void
+static void
e64toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
/* 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[];
char *string;
static char wstring[80]; /* working storage for ASCII output */
-static void
+static void
etoasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
/* 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;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 24);
/* Convert ASCII string S to double precision value Y. */
-static void
+static void
asctoe53 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
#if defined(DEC) || defined(IBM)
/* Convert ASCII string S to double extended value Y. */
-static void
+static void
asctoe64 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 64);
}
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
/* Convert ASCII string S to 128-bit long double Y. */
-static void
+static void
asctoe113 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 113);
}
+#endif
/* Convert ASCII string S to e type Y. */
-static void
+static void
asctoe (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, NBITS);
}
/* Convert ASCII string SS to e type Y, with a specified rounding precision
- of OPREC bits. */
+ of OPREC bits. BASE is 16 for C99 hexadecimal floating constants. */
-static void
+static void
asctoeg (ss, y, oprec)
- char *ss;
+ const char *ss;
unsigned EMUSHORT *y;
int oprec;
{
unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
int esign, decflg, sgnflg, nexp, exp, prec, lost;
- int k, trail, c, rndsav;
+ int i, k, trail, c, rndsav;
EMULONG lexp;
- unsigned EMUSHORT nsign, *p;
+ unsigned EMUSHORT nsign;
char *sp, *s, *lstr;
+ int base = 10;
/* Copy the input string. */
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))
+ if (*s >= '0' && *s <= '9')
+ k = *s - '0';
+ else if (*s >= 'a' && *s <= 'f')
+ k = 10 + *s - 'a';
+ else
+ k = 10 + *s - 'A';
+ if ((k >= 0) && (k < base))
{
/* Ignore leading zeros */
if ((prec == 0) && (decflg == 0) && (k == 0))
if ((trail == 0) && (decflg != 0))
{
sp = s;
- while ((*sp >= '0') && (*sp <= '9'))
+ while ((*sp >= '0' && *sp <= '9')
+ || (base == 16 && ((*sp >= 'a' && *sp <= 'f')
+ || (*sp >= 'A' && *sp <= 'F'))))
++sp;
/* Check for syntax error */
- c = *sp & 0x7f;
- if ((c != 'e') && (c != 'E') && (c != '\0')
+ c = *sp & CHARMASK;
+ if ((base != 10 || ((c != 'e') && (c != 'E')))
+ && (base != 16 || ((c != 'p') && (c != 'P')))
+ && (c != '\0')
&& (c != '\n') && (c != '\r') && (c != ' ')
&& (c != ','))
- goto error;
+ goto unexpected_char_error;
--sp;
while (*sp == '0')
*sp-- = 'z';
if (yy[2] == 0)
{
- if (decflg)
- nexp += 1; /* count digits after decimal point */
- eshup1 (yy); /* multiply current number by 10 */
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (xt, yy);
+ if (base == 16)
+ {
+ if (decflg)
+ nexp += 4; /* count digits after decimal point */
+
+ eshup1 (yy); /* multiply current number by 16 */
+ eshup1 (yy);
+ eshup1 (yy);
+ eshup1 (yy);
+ }
+ else
+ {
+ if (decflg)
+ nexp += 1; /* count digits after decimal point */
+
+ eshup1 (yy); /* multiply current number by 10 */
+ emovz (yy, xt);
+ eshup1 (xt);
+ eshup1 (xt);
+ eaddm (xt, yy);
+ }
+ /* Insert the current digit. */
ecleaz (xt);
xt[NI - 2] = (unsigned EMUSHORT) k;
eaddm (xt, yy);
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
{
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:
lexp -= EXONE - 0201;
#endif
rndprc = oprec;
- emdnorm (yy, k, 0, lexp, 64);
+ emdnorm (yy, lost, 0, lexp, 64);
aexit:
0x0000,
};
-static void
+static void
efloor (x, y)
unsigned EMUSHORT x[], y[];
{
/* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1.
For example, 1.1 = 0.55 * 2^1. */
-static void
+static void
efrexp (x, exp, s)
unsigned EMUSHORT x[];
int *exp;
/* Return e type Y = X * 2^PWR2. */
-static void
+static void
eldexp (x, pwr2, y)
unsigned EMUSHORT x[];
int pwr2;
/* 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[];
{
/* Return quotient of exploded e-types NUM / DEN in EQUOT,
remainder in NUM. */
-static void
+static void
eiremain (den, num)
unsigned EMUSHORT den[], num[];
{
}
/* 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;
/* Convert e type X to DEC double precision D. */
-static void
+static void
etodec (x, d)
unsigned EMUSHORT *x, *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;
{
#ifdef IBM
/* Convert IBM single/double precision to e type. */
-static void
+static void
ibmtoe (d, e, mode)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
{
unsigned EMUSHORT y[NI];
register unsigned EMUSHORT r, *p;
- int rndsav;
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;
enum machine_mode mode;
toibm (xi, d, mode);
}
-static void
+static void
toibm (x, y, mode)
unsigned EMUSHORT *x, *y;
enum machine_mode mode;
#ifdef C4X
/* Convert C4X single/double precision to e type. */
-static void
+static void
c4xtoe (d, e, mode)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
{
isnegative = FALSE;
}
-
+
r >>= 8; /* Shift exponent word down 8 bits. */
if (r & 0x80) /* Make the exponent negative if it is. */
{
/* Now do the high order mantissa. We don't "or" on the high bit
because it is 2 (not 1) and is handled a little differently
below. */
- y[M] = d[0] & 0x7f;
+ y[M] = d[0] & 0x7f;
y[M+1] = d[1];
if (mode != QFmode) /* There are only 2 words in QFmode. */
{
/* Add our e type exponent offset to form our exponent. */
r += EXONE;
- y[1] = r;
+ y[1] = r;
/* Now do the high order mantissa strip off the exponent and sign
bits and add the high 1 bit. */
- y[M] = (d[0] & 0x7f) | 0x80;
+ y[M] = (d[0] & 0x7f) | 0x80;
y[M+1] = d[1];
if (mode != QFmode) /* There are only 2 words in QFmode. */
/* Convert e type to C4X single/double precision. */
-static void
+static void
etoc4x (x, d, mode)
unsigned EMUSHORT *x, *d;
enum machine_mode mode;
toc4x (xi, d, mode);
}
-static void
+static void
toc4x (x, y, mode)
unsigned EMUSHORT *x, *y;
enum machine_mode mode;
int i;
int v;
int carry;
-
+
/* Short-circuit the zero case */
if ((x[0] == 0) /* Zero exponent and sign */
&& (x[1] == 0)
}
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;
}
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
#endif
return;
}
-
+
y[0] |= ((i & 0xff) << 8);
-
+
eshift (x, 8);
-
+
y[0] |= x[M] & 0x7f;
y[1] = x[M + 1];
if (mode != QFmode)
#endif
+#ifdef NANS
static void
make_nan (nan, sign, mode)
unsigned EMUSHORT *nan;
used like NaN's, but probably not in the same way as IEEE. */
#if !defined(DEC) && !defined(IBM) && !defined(C4X)
case TFmode:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
n = 8;
if (REAL_WORDS_BIG_ENDIAN)
p = TFbignan;
else
p = TFlittlenan;
break;
+#endif
+ /* FALLTHRU */
case XFmode:
n = 6;
if (! REAL_WORDS_BIG_ENDIAN)
*nan = (sign << 15) | (*p & 0x7fff);
}
+#endif /* NANS */
/* This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
/* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
if (REAL_WORDS_BIG_ENDIAN)
{
+#if HOST_BITS_PER_WIDE_INT == 32
s[0] = (unsigned EMUSHORT) (d[0] >> 16);
s[1] = (unsigned EMUSHORT) d[0];
-#if HOST_BITS_PER_WIDE_INT == 32
s[2] = (unsigned EMUSHORT) (d[1] >> 16);
s[3] = (unsigned EMUSHORT) d[1];
#else
/* In this case the entire target double is contained in the
first array element. The second element of the input is
ignored. */
- s[2] = (unsigned EMUSHORT) (d[0] >> 48);
- s[3] = (unsigned EMUSHORT) (d[0] >> 32);
+ s[0] = (unsigned EMUSHORT) (d[0] >> 48);
+ s[1] = (unsigned EMUSHORT) (d[0] >> 32);
+ s[2] = (unsigned EMUSHORT) (d[0] >> 16);
+ s[3] = (unsigned EMUSHORT) d[0];
#endif
}
else
/* Convert e-type to unsigned 64-bit int. */
-static void
+static void
etoudi (x, i)
unsigned EMUSHORT *x;
unsigned EMUSHORT *i;
/* Convert e-type to signed 64-bit int. */
-static void
+static void
etodi (x, i)
unsigned EMUSHORT *x;
unsigned EMUSHORT *i;
static int esqinited = 0;
static unsigned short sqrndbit[NI];
-static void
+static void
esqrt (x, y)
unsigned EMUSHORT *x, *y;
{
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
case 96:
return 64;
+
case 128:
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
return 113;
+#else
+ return 64;
+#endif
default:
abort ();