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
This commit is contained in:
Richard Stallman 1993-03-31 05:39:37 +00:00
parent 985b6196e6
commit fd76a739e5
1 changed files with 139 additions and 14 deletions

View File

@ -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 */