summaryrefslogtreecommitdiff
path: root/gcc/real.h
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1993-03-31 05:39:37 +0000
committerRichard Stallman <rms@gnu.org>1993-03-31 05:39:37 +0000
commitfd76a739e5edc6e1b8d2fb2e094f70a8283fe3b8 (patch)
treefce52e724f0f1543abd5bd430a11822c3977e803 /gcc/real.h
parent985b6196e635b59aff9af3e4d9603678febba797 (diff)
downloadgcc-fd76a739e5edc6e1b8d2fb2e094f70a8283fe3b8.tar.gz
If REAL_ARITHMETIC is defined or if LONG_DOUBLE_TYPE_SIZE is 96...
If REAL_ARITHMETIC is defined or if LONG_DOUBLE_TYPE_SIZE is 96, then define REAL_VALUE_ macros to invoke functions in real.c. (REAL_VALUE_RNDZINT, REAL_VALUE_UNSIGNED_RNDZINT): New macros truncate toward zero to integer value but return REAL_VALUE_TYPE. (REAL_VALUE_TO_DECIMAL): New macro defaults to fprintf if no REAL_ARITHMETIC, otherwise uses real.c for binary to decimal conversion. Used in ASM_OUTPUT_ macros. From-SVN: r3934
Diffstat (limited to 'gcc/real.h')
-rw-r--r--gcc/real.h153
1 files changed, 139 insertions, 14 deletions
diff --git a/gcc/real.h b/gcc/real.h
index 7e6579fff6e..527c205e077 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -24,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define UNKNOWN_FLOAT_FORMAT 0
#define IEEE_FLOAT_FORMAT 1
#define VAX_FLOAT_FORMAT 2
+#define IBM_FLOAT_FORMAT 3
/* Default to IEEE float if not specified. Nearly all machines use it. */
@@ -39,6 +40,103 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define REAL_INFINITY
#endif
+/* Defining REAL_ARITHMETIC invokes a floating point emulator
+ that can produce a target machine format differing by more
+ than just endian-ness from the host's format. The emulator
+ is also used to support extended real XFmode. */
+#ifndef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+#endif
+#if (LONG_DOUBLE_TYPE_SIZE == 96) || defined (REAL_ARITHMETIC)
+/* **** Start of software floating point emulator interface macros **** */
+
+/* Support 80-bit extended real XFmode if LONG_DOUBLE_TYPE_SIZE
+ has been defined to be 96 in the tm.h machine file. */
+#if (LONG_DOUBLE_TYPE_SIZE == 96)
+#define REAL_IS_NOT_DOUBLE
+#define REAL_ARITHMETIC
+typedef struct {
+ HOST_WIDE_INT r[(11 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
+} realvaluetype;
+#define REAL_VALUE_TYPE realvaluetype
+
+#else /* no XFmode support */
+
+#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+/* If no XFmode support, then a REAL_VALUE_TYPE is 64 bits wide
+ but it is not necessarily a host machine double. */
+#define REAL_IS_NOT_DOUBLE
+typedef struct {
+ HOST_WIDE_INT r[(7 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
+} realvaluetype;
+#define REAL_VALUE_TYPE realvaluetype
+#else
+/* If host and target formats are compatible, then a REAL_VALUE_TYPE
+ is actually a host machine double. */
+#define REAL_VALUE_TYPE double
+#endif
+#endif /* no XFmode support */
+
+/* If emulation has been enabled by defining REAL_ARITHMETIC or by
+ setting LONG_DOUBLE_TYPE_SIZE to 96, then define macros so that
+ they invoke emulator functions. This will succeed only if the machine
+ files have been updated to use these macros in place of any
+ references to host machine `double' or `float' types. */
+#ifdef REAL_ARITHMETIC
+#undef REAL_ARITHMETIC
+#define REAL_ARITHMETIC(value, code, d1, d2) \
+ earith (&(value), (code), &(d1), &(d2))
+
+/* Declare functions in real.c that are referenced here. */
+void earith (), ereal_from_uint (), ereal_from_int (), ereal_to_int ();
+void etarldouble (), etardouble ();
+long etarsingle ();
+int ereal_cmp (), eroundi (), ereal_isneg ();
+unsigned int eroundui ();
+REAL_VALUE_TYPE etrunci (), etruncui (), ereal_ldexp (), ereal_atof ();
+REAL_VALUE_TYPE ereal_negate (), ereal_truncate ();
+
+#define REAL_VALUES_EQUAL(x, y) (ereal_cmp ((x), (y)) == 0)
+/* true if x < y : */
+#define REAL_VALUES_LESS(x, y) (ereal_cmp ((x), (y)) < 0)
+#define REAL_VALUE_LDEXP(x, n) ereal_ldexp (x, n)
+
+/* These return REAL_VALUE_TYPE: */
+#define REAL_VALUE_RNDZINT(x) (etrunci (x))
+#define REAL_VALUE_UNSIGNED_RNDZINT(x) (etruncui (x))
+extern REAL_VALUE_TYPE real_value_truncate ();
+#define REAL_VALUE_TRUNCATE(mode, x) real_value_truncate (mode, x)
+
+/* These return int: */
+#define REAL_VALUE_FIX(x) (eroundi (x))
+#define REAL_VALUE_UNSIGNED_FIX(x) ((unsigned int) eroundui (x))
+
+#define REAL_VALUE_ATOF ereal_atof
+#define REAL_VALUE_NEGATE ereal_negate
+
+#define REAL_VALUE_MINUS_ZERO(x) \
+ ((ereal_cmp (x, dconst0) == 0) && (ereal_isneg (x) != 0 ))
+
+#define REAL_VALUE_TO_INT ereal_to_int
+#define REAL_VALUE_FROM_INT(d, i, j) (ereal_from_int (&d, i, j))
+#define REAL_VALUE_FROM_UNSIGNED_INT(d, i, j) (ereal_from_uint (&d, i, j))
+
+/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) (etarldouble ((IN), (OUT)))
+#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) (etardouble ((IN), (OUT)))
+
+/* IN is a REAL_VALUE_TYPE. OUT is a long. */
+#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) ((OUT) = etarsingle ((IN)))
+
+/* Conversions to decimal ASCII string. */
+#define REAL_VALUE_TO_DECIMAL(r, fmt, s) (ereal_to_decimal (r, s))
+
+#endif /* REAL_ARITHMETIC defined */
+
+/* **** End of software floating point emulator interface macros **** */
+#else /* LONG_DOUBLE_TYPE_SIZE != 96 and REAL_ARITHMETIC not defined */
+
+/* old interface */
#ifdef REAL_ARITHMETIC
/* Defining REAL_IS_NOT_DOUBLE breaks certain initializations
when REAL_ARITHMETIC etc. are not defined. */
@@ -52,12 +150,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
#define REAL_IS_NOT_DOUBLE
#ifndef REAL_VALUE_TYPE
-#define REAL_VALUE_TYPE \
- struct real_value{ HOST_WIDE_INT i[sizeof (double)/sizeof (HOST_WIDE_INT)]; }
+typedef struct {
+ HOST_WIDE_INT r[sizeof (double)/sizeof (HOST_WIDE_INT)];
+ } realvaluetype;
+#define REAL_VALUE_TYPE realvaluetype
#endif /* no REAL_VALUE_TYPE */
#endif /* formats differ */
#endif /* 0 */
+#endif /* emulator not used */
+
/* If we are not cross-compiling, use a `double' to represent the
floating-point value. Otherwise, use some other type
(probably a struct containing an array of longs). */
@@ -72,14 +174,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Convert a type `double' value in host format first to a type `float'
value in host format and then to a single type `long' value which
is the bitwise equivalent of the `float' value. */
+#ifndef REAL_VALUE_TO_TARGET_SINGLE
#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
do { float f = (float) (IN); \
(OUT) = *(long *) &f; \
- } while (0)
+ } while (0)
+#endif
/* Convert a type `double' value in host format to a pair of type `long'
values which is its bitwise equivalent, but put the two words into
proper word order for the target. */
+#ifndef REAL_VALUE_TO_TARGET_DOUBLE
#if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN
#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
do { REAL_VALUE_TYPE in = (IN); /* Make sure it's not in a register. */\
@@ -93,26 +198,32 @@ do { REAL_VALUE_TYPE in = (IN); /* Make sure it's not in a register. */\
(OUT)[0] = ((long *) &in)[1]; \
} while (0)
#endif
+#endif
#endif /* HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT */
+/* In this configuration, double and long double are the same. */
+#ifndef REAL_VALUE_TO_TARGET_LONG_DOUBLE
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(a, b) REAL_VALUE_TO_TARGET_DOUBLE (a, b)
+#endif
+
/* Compare two floating-point values for equality. */
#ifndef REAL_VALUES_EQUAL
-#define REAL_VALUES_EQUAL(x,y) ((x) == (y))
+#define REAL_VALUES_EQUAL(x, y) ((x) == (y))
#endif
/* Compare two floating-point values for less than. */
#ifndef REAL_VALUES_LESS
-#define REAL_VALUES_LESS(x,y) ((x) < (y))
+#define REAL_VALUES_LESS(x, y) ((x) < (y))
#endif
-/* Convert a floating-point value to integer by truncating. */
-#ifndef REAL_VALUE_FIX_TRUNCATE
-#define REAL_VALUE_FIX_TRUNCATE(x) ((int) (x))
+/* Truncate toward zero to an integer floating-point value. */
+#ifndef REAL_VALUE_RNDZINT
+#define REAL_VALUE_RNDZINT(x) ((double) ((int) (x)))
#endif
-/* Convert a floating-point value to unsigned integer by truncating. */
-#ifndef REAL_VALUE_UNSIGNED_FIX_TRUNCATE
-#define REAL_VALUE_UNSIGNED_FIX_TRUNCATE(x) ((unsigned int) (x))
+/* Truncate toward zero to an unsigned integer floating-point value. */
+#ifndef REAL_VALUE_UNSIGNED_RNDZINT
+#define REAL_VALUE_UNSIGNED_RNDZINT(x) ((double) ((unsigned int) (x)))
#endif
/* Convert a floating-point value to integer, using any rounding mode. */
@@ -128,13 +239,19 @@ do { REAL_VALUE_TYPE in = (IN); /* Make sure it's not in a register. */\
/* Scale X by Y powers of 2. */
#ifndef REAL_VALUE_LDEXP
-#define REAL_VALUE_LDEXP(x,y) ldexp (x, y)
+#define REAL_VALUE_LDEXP(x, y) ldexp (x, y)
extern double ldexp ();
#endif
/* Convert the string X to a floating-point value. */
#ifndef REAL_VALUE_ATOF
-#define REAL_VALUE_ATOF(x) atof (x)
+#if 1
+/* Use real.c to convert decimal numbers to binary, ... */
+REAL_VALUE_TYPE ereal_atof ();
+#define REAL_VALUE_ATOF(x, s) ereal_atof (x, s)
+#else
+/* ... or, if you like the host computer's atof, go ahead and use it: */
+#define REAL_VALUE_ATOF(x, s) atof (x)
#if defined (MIPSEL) || defined (MIPSEB)
/* MIPS compiler can't handle parens around the function name.
This problem *does not* appear to be connected with any
@@ -144,6 +261,7 @@ extern double atof ();
extern double (atof) ();
#endif
#endif
+#endif
/* Negate the floating-point value X. */
#ifndef REAL_VALUE_NEGATE
@@ -229,6 +347,13 @@ do { union real_extract u; \
/* Return a CONST_DOUBLE with value R and mode M. */
-#define CONST_DOUBLE_FROM_REAL_VALUE(r,m) immed_real_const_1 (r, m)
+#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) immed_real_const_1 (r, m)
+
+/* Convert a floating point value `r', that can be interpreted
+ as a host machine float or double, to a decimal ASCII string `s'
+ using printf format string `fmt'. */
+#ifndef REAL_VALUE_TO_DECIMAL
+#define REAL_VALUE_TO_DECIMAL(r, fmt, s) (sprintf (s, fmt, r))
+#endif
#endif /* Not REAL_H_INCLUDED */