#include "config.h"
#include "system.h"
+#include "real.h"
#include "tree.h"
#include "toplev.h"
#include "tm_p.h"
#define EMUSHORT_SIZE HOST_BITS_PER_LONG
#define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
#else
-/* You will have to modify this program to have a smaller unit size. */
-#define EMU_NON_COMPILE
+ #error "You will have to modify this program to have a smaller unit size."
#endif
#endif
#endif
#if HOST_BITS_PER_LONGLONG >= EMULONG_SIZE
#define EMULONG long long int
#else
-/* You will have to modify this program to have a smaller unit size. */
-#define EMU_NON_COMPILE
+ #error "You will have to modify this program to have a smaller unit size."
#endif
#endif
#endif
#endif
-
-/* The host interface doesn't work if no 16-bit size exists. */
#if EMUSHORT_SIZE != 16
-#define EMU_NON_COMPILE
+ #error "The host interface doesn't work if no 16-bit size exists."
#endif
-/* OK to continue compilation. */
-#ifndef EMU_NON_COMPILE
-
-/* Construct macros to translate between REAL_VALUE_TYPE and e type.
- In GET_REAL and PUT_REAL, r and e are pointers.
- A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
- in memory, with no holes. */
+/* Calculate the size of the generic "e" type. This always has
+ identical in-memory size to REAL_VALUE_TYPE. The sizes are supposed
+ to be the same as well, but when REAL_VALUE_TYPE_SIZE is not evenly
+ divisible by HOST_BITS_PER_WIDE_INT we have some padding in
+ REAL_VALUE_TYPE.
+ There are only two supported sizes: ten and six 16-bit words (160
+ or 96 bits). */
-#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 */
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !INTEL_EXTENDED_IEEE_FORMAT
+/* TFmode */
+# define NE 10
+# define MAXDECEXP 4932
+# define MINDECEXP -4977
+#else
# 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
-/* 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 ((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), (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)
-
-#endif /* not TFmode */
-#endif /* not XFmode */
+#endif
+/* Fail compilation if 2*NE is not the appropriate size.
+ If HOST_BITS_PER_WIDE_INT is 64, we're going to have padding
+ at the end of the array, because neither 96 nor 160 is
+ evenly divisible by 64. */
+struct compile_test_dummy {
+ char twice_NE_must_equal_sizeof_REAL_VALUE_TYPE
+ [(sizeof (REAL_VALUE_TYPE) >= 2*NE) ? 1 : -1];
+};
+
+/* Construct macros to translate between REAL_VALUE_TYPE and e type.
+ In GET_REAL and PUT_REAL, r and e are pointers.
+ A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
+ in memory, with no holes. */
+#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)
/* Number of 16 bit words in internal format */
#define NI (NE+3)
static void enan PARAMS ((UEMUSHORT *, int));
static void einan PARAMS ((UEMUSHORT *));
static int eiisnan PARAMS ((const UEMUSHORT *));
-static int eiisneg 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 *));
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;
return (r);
}
+/* Return true if ARG can be represented exactly in MODE. */
+
+bool
+exact_real_truncate (mode, arg)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE *arg;
+{
+ REAL_VALUE_TYPE trunc;
+
+ if (target_isnan (*arg))
+ return false;
+
+ trunc = real_value_truncate (mode, *arg);
+ return ereal_cmp (*arg, trunc) == 0;
+}
+
/* Try to change R into its exact multiplicative inverse in machine mode
MODE. Return nonzero function value if successful. */
for (i = 0; i < NE - 1; i++)
{
if (*x++ != 0)
- return (1);
+ return (1);
}
#endif
/* Return nonzero if sign of exploded e-type X is nonzero. */
-#ifdef NANS
static int
eiisneg (x)
const UEMUSHORT x[];
return x[0] != 0;
}
-#endif /* NANS */
#if 0
/* Fill exploded e-type X with infinity pattern.
esubm (ai, bi);
subflg = 1;
}
- emdnorm (bi, lost, subflg, ltb, 64);
+ emdnorm (bi, lost, subflg, ltb, !ROUND_TOWARDS_ZERO);
done:
emovo (bi, c);
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:
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:
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)
/* 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:
/* 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:
/* 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:
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)
/* 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:
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 |= (UEMUSHORT) 0x7f80;
*i = -(*i);
}
else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
- *i = (HOST_WIDE_INT) xi[M] & 0xffff;
- if (xi[0])
- *i = -(*i);
- }
+ {
+ /* shift not more than 16 bits */
+ eshift (xi, k);
+ *i = (HOST_WIDE_INT) xi[M] & 0xffff;
+ if (xi[0])
+ *i = -(*i);
+ }
xi[0] = 0;
xi[E] = EXONE - 1;
xi[M] = 0;
}
}
doexp:
- /*
- if (expon >= 0)
- sprintf (ss, "e+%d", expon);
- else
- sprintf (ss, "e%d", expon);
- */
+ /* Strip trailing zeros, but leave at least one. */
+ while (ss[-1] == '0' && ss[-2] != '.')
+ --ss;
sprintf (ss, "e%d", expon);
bxit:
rndprc = rndsav;
li = xi[1];
li += pwr2;
i = 0;
- emdnorm (xi, i, i, li, 64);
+ emdnorm (xi, i, i, li, !ROUND_TOWARDS_ZERO);
emovo (xi, y);
}
/* 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);
}
/* 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);
}
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);
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;
y[i] = ((~y[i]) + carry) & 0xffff;
carry = 0;
}
- }
+ }
if (carry)
- {
+ {
eshift (y, -1);
y[M+1] |= 0x8000;
r++;
- }
+ }
y[1] = r + EXONE;
}
else
/* Round off to nearest or even. */
rndsav = rndprc;
rndprc = mode == QFmode ? 24 : 32;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
toc4x (xi, d, mode);
}
*y++ = 0x8000;
*y++ = 0x0000;
if (mode != QFmode)
- {
- *y++ = 0x0000;
- *y++ = 0x0000;
- }
+ {
+ *y++ = 0x0000;
+ *y++ = 0x0000;
+ }
return;
}
{
int n;
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
}
#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. */
}
else
{
- /* shift not more than 16 bits */
+ /* shift not more than 16 bits */
eshift (xi, k);
noshift:
}
else
{
- /* shift not more than 16 bits */
+ /* shift not more than 16 bits */
eshift (xi, k);
if (WORDS_BIG_ENDIAN)
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
-#endif /* EMU_NON_COMPILE not defined */
\f
/* Return the binary precision of the significand for a given
floating point mode. The mode can hold an integer value