real.h revision 52284
150397Sobrien/* Definitions of floating-point access for GNU compiler.
252284Sobrien   Copyright (C) 1989, 91, 94, 96-98, 1999 Free Software Foundation, Inc.
318334Speter
418334SpeterThis file is part of GNU CC.
518334Speter
618334SpeterGNU CC is free software; you can redistribute it and/or modify
718334Speterit under the terms of the GNU General Public License as published by
818334Speterthe Free Software Foundation; either version 2, or (at your option)
918334Speterany later version.
1018334Speter
1118334SpeterGNU CC is distributed in the hope that it will be useful,
1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1418334SpeterGNU General Public License for more details.
1518334Speter
1618334SpeterYou should have received a copy of the GNU General Public License
1718334Speteralong with GNU CC; see the file COPYING.  If not, write to
1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
1918334SpeterBoston, MA 02111-1307, USA.  */
2018334Speter
2118334Speter#ifndef REAL_H_INCLUDED
2218334Speter#define REAL_H_INCLUDED
2318334Speter
2418334Speter/* Define codes for all the float formats that we know of.  */
2518334Speter#define UNKNOWN_FLOAT_FORMAT 0
2618334Speter#define IEEE_FLOAT_FORMAT 1
2718334Speter#define VAX_FLOAT_FORMAT 2
2818334Speter#define IBM_FLOAT_FORMAT 3
2950397Sobrien#define C4X_FLOAT_FORMAT 4
3018334Speter
3118334Speter/* Default to IEEE float if not specified.  Nearly all machines use it.  */
3218334Speter
3318334Speter#ifndef TARGET_FLOAT_FORMAT
3418334Speter#define	TARGET_FLOAT_FORMAT	IEEE_FLOAT_FORMAT
3518334Speter#endif
3618334Speter
3718334Speter#ifndef HOST_FLOAT_FORMAT
3818334Speter#define	HOST_FLOAT_FORMAT	IEEE_FLOAT_FORMAT
3918334Speter#endif
4018334Speter
4118334Speter#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
4218334Speter#define REAL_INFINITY
4318334Speter#endif
4418334Speter
4518334Speter/* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
4618334Speter   in the header files, then this implies the word-endianness is the same as
4718334Speter   for integers.  */
4818334Speter
4918334Speter/* This is defined 0 or 1, like WORDS_BIG_ENDIAN.  */
5018334Speter#ifndef FLOAT_WORDS_BIG_ENDIAN
5118334Speter#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
5218334Speter#endif
5318334Speter
5418334Speter/* This is defined 0 or 1, unlike HOST_WORDS_BIG_ENDIAN.  */
5518334Speter#ifndef HOST_FLOAT_WORDS_BIG_ENDIAN
5618334Speter#ifdef HOST_WORDS_BIG_ENDIAN
5718334Speter#define HOST_FLOAT_WORDS_BIG_ENDIAN 1
5818334Speter#else
5918334Speter#define HOST_FLOAT_WORDS_BIG_ENDIAN 0
6018334Speter#endif
6118334Speter#endif
6218334Speter
6318334Speter/* Defining REAL_ARITHMETIC invokes a floating point emulator
6418334Speter   that can produce a target machine format differing by more
6518334Speter   than just endian-ness from the host's format.  The emulator
6618334Speter   is also used to support extended real XFmode.  */
6718334Speter#ifndef LONG_DOUBLE_TYPE_SIZE
6818334Speter#define LONG_DOUBLE_TYPE_SIZE 64
6918334Speter#endif
7018334Speter#if (LONG_DOUBLE_TYPE_SIZE == 96) || (LONG_DOUBLE_TYPE_SIZE == 128)
7118334Speter#ifndef REAL_ARITHMETIC
7218334Speter#define REAL_ARITHMETIC
7318334Speter#endif
7418334Speter#endif
7518334Speter#ifdef REAL_ARITHMETIC
7618334Speter/* **** Start of software floating point emulator interface macros **** */
7718334Speter
7818334Speter/* Support 80-bit extended real XFmode if LONG_DOUBLE_TYPE_SIZE
7918334Speter   has been defined to be 96 in the tm.h machine file. */
8018334Speter#if (LONG_DOUBLE_TYPE_SIZE == 96)
8118334Speter#define REAL_IS_NOT_DOUBLE
8218334Speter#define REAL_ARITHMETIC
8318334Spetertypedef struct {
8418334Speter  HOST_WIDE_INT r[(11 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
8518334Speter} realvaluetype;
8618334Speter#define REAL_VALUE_TYPE realvaluetype
8718334Speter
8818334Speter#else /* no XFmode support */
8918334Speter
9018334Speter#if (LONG_DOUBLE_TYPE_SIZE == 128)
9118334Speter
9218334Speter#define REAL_IS_NOT_DOUBLE
9318334Speter#define REAL_ARITHMETIC
9418334Spetertypedef struct {
9518334Speter  HOST_WIDE_INT r[(19 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
9618334Speter} realvaluetype;
9718334Speter#define REAL_VALUE_TYPE realvaluetype
9818334Speter
9918334Speter#else /* not TFmode */
10018334Speter
10118334Speter#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
10218334Speter/* If no XFmode support, then a REAL_VALUE_TYPE is 64 bits wide
10318334Speter   but it is not necessarily a host machine double. */
10418334Speter#define REAL_IS_NOT_DOUBLE
10518334Spetertypedef struct {
10618334Speter  HOST_WIDE_INT r[(7 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
10718334Speter} realvaluetype;
10818334Speter#define REAL_VALUE_TYPE realvaluetype
10918334Speter#else
11018334Speter/* If host and target formats are compatible, then a REAL_VALUE_TYPE
11118334Speter   is actually a host machine double. */
11218334Speter#define REAL_VALUE_TYPE double
11318334Speter#endif
11418334Speter
11518334Speter#endif /* no TFmode support */
11618334Speter#endif /* no XFmode support */
11718334Speter
11818334Speterextern int significand_size	PROTO((enum machine_mode));
11918334Speter
12018334Speter/* If emulation has been enabled by defining REAL_ARITHMETIC or by
12118334Speter   setting LONG_DOUBLE_TYPE_SIZE to 96 or 128, then define macros so that
12218334Speter   they invoke emulator functions. This will succeed only if the machine
12318334Speter   files have been updated to use these macros in place of any
12418334Speter   references to host machine `double' or `float' types.  */
12518334Speter#ifdef REAL_ARITHMETIC
12618334Speter#undef REAL_ARITHMETIC
12718334Speter#define REAL_ARITHMETIC(value, code, d1, d2) \
12818334Speter  earith (&(value), (code), &(d1), &(d2))
12918334Speter
13018334Speter/* Declare functions in real.c. */
13118334Speterextern void earith		PROTO((REAL_VALUE_TYPE *, int,
13218334Speter				       REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
13318334Speterextern REAL_VALUE_TYPE etrunci	PROTO((REAL_VALUE_TYPE));
13418334Speterextern REAL_VALUE_TYPE etruncui	PROTO((REAL_VALUE_TYPE));
13552284Sobrienextern REAL_VALUE_TYPE ereal_atof PROTO((const char *, enum machine_mode));
13618334Speterextern REAL_VALUE_TYPE ereal_negate PROTO((REAL_VALUE_TYPE));
13718334Speterextern HOST_WIDE_INT efixi	PROTO((REAL_VALUE_TYPE));
13818334Speterextern unsigned HOST_WIDE_INT efixui PROTO((REAL_VALUE_TYPE));
13918334Speterextern void ereal_from_int	PROTO((REAL_VALUE_TYPE *,
14050397Sobrien				       HOST_WIDE_INT, HOST_WIDE_INT,
14150397Sobrien				       enum machine_mode));
14218334Speterextern void ereal_from_uint	PROTO((REAL_VALUE_TYPE *,
14318334Speter				       unsigned HOST_WIDE_INT,
14450397Sobrien				       unsigned HOST_WIDE_INT,
14550397Sobrien				       enum machine_mode));
14618334Speterextern void ereal_to_int	PROTO((HOST_WIDE_INT *, HOST_WIDE_INT *,
14718334Speter				       REAL_VALUE_TYPE));
14818334Speterextern REAL_VALUE_TYPE ereal_ldexp PROTO((REAL_VALUE_TYPE, int));
14918334Speter
15018334Speterextern void etartdouble		PROTO((REAL_VALUE_TYPE, long *));
15118334Speterextern void etarldouble		PROTO((REAL_VALUE_TYPE, long *));
15218334Speterextern void etardouble		PROTO((REAL_VALUE_TYPE, long *));
15318334Speterextern long etarsingle		PROTO((REAL_VALUE_TYPE));
15418334Speterextern void ereal_to_decimal	PROTO((REAL_VALUE_TYPE, char *));
15518334Speterextern int ereal_cmp		PROTO((REAL_VALUE_TYPE, REAL_VALUE_TYPE));
15618334Speterextern int ereal_isneg		PROTO((REAL_VALUE_TYPE));
15750397Sobrienextern REAL_VALUE_TYPE ereal_unto_float PROTO((long));
15850397Sobrienextern REAL_VALUE_TYPE ereal_unto_double PROTO((long *));
15918334Speterextern REAL_VALUE_TYPE ereal_from_float PROTO((HOST_WIDE_INT));
16018334Speterextern REAL_VALUE_TYPE ereal_from_double PROTO((HOST_WIDE_INT *));
16118334Speter
16218334Speter#define REAL_VALUES_EQUAL(x, y) (ereal_cmp ((x), (y)) == 0)
16318334Speter/* true if x < y : */
16418334Speter#define REAL_VALUES_LESS(x, y) (ereal_cmp ((x), (y)) == -1)
16518334Speter#define REAL_VALUE_LDEXP(x, n) ereal_ldexp (x, n)
16618334Speter
16718334Speter/* These return REAL_VALUE_TYPE: */
16818334Speter#define REAL_VALUE_RNDZINT(x) (etrunci (x))
16918334Speter#define REAL_VALUE_UNSIGNED_RNDZINT(x) (etruncui (x))
17050397Sobrienextern REAL_VALUE_TYPE real_value_truncate	PROTO ((enum machine_mode,
17150397Sobrien							REAL_VALUE_TYPE));
17218334Speter#define REAL_VALUE_TRUNCATE(mode, x)  real_value_truncate (mode, x)
17318334Speter
17418334Speter/* These return HOST_WIDE_INT: */
17518334Speter/* Convert a floating-point value to integer, rounding toward zero.  */
17618334Speter#define REAL_VALUE_FIX(x) (efixi (x))
17718334Speter/* Convert a floating-point value to unsigned integer, rounding
17818334Speter   toward zero. */
17918334Speter#define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
18018334Speter
18152284Sobrien/* Convert ASCII string S to floating point in mode M.
18252284Sobrien   Decimal input uses ATOF.  Hexadecimal uses HTOF.  */
18318334Speter#define REAL_VALUE_ATOF ereal_atof
18452284Sobrien#define REAL_VALUE_HTOF ereal_atof
18552284Sobrien
18618334Speter#define REAL_VALUE_NEGATE ereal_negate
18718334Speter
18818334Speter#define REAL_VALUE_MINUS_ZERO(x) \
18918334Speter ((ereal_cmp (x, dconst0) == 0) && (ereal_isneg (x) != 0 ))
19018334Speter
19118334Speter#define REAL_VALUE_TO_INT ereal_to_int
19218334Speter
19318334Speter/* Here the cast to HOST_WIDE_INT sign-extends arguments such as ~0.  */
19450397Sobrien#define REAL_VALUE_FROM_INT(d, lo, hi, mode) \
19550397Sobrien  ereal_from_int (&d, (HOST_WIDE_INT) (lo), (HOST_WIDE_INT) (hi), mode)
19618334Speter
19750397Sobrien#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
19850397Sobrien  ereal_from_uint (&d, lo, hi, mode)
19918334Speter
20018334Speter/* IN is a REAL_VALUE_TYPE.  OUT is an array of longs. */
20118334Speter#if LONG_DOUBLE_TYPE_SIZE == 96
20218334Speter#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) (etarldouble ((IN), (OUT)))
20318334Speter#else
20418334Speter#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) (etartdouble ((IN), (OUT)))
20518334Speter#endif
20618334Speter#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) (etardouble ((IN), (OUT)))
20718334Speter
20818334Speter/* IN is a REAL_VALUE_TYPE.  OUT is a long. */
20918334Speter#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) ((OUT) = etarsingle ((IN)))
21018334Speter
21150397Sobrien/* Inverse of REAL_VALUE_TO_TARGET_DOUBLE. */
21250397Sobrien#define REAL_VALUE_UNTO_TARGET_DOUBLE(d)  (ereal_unto_double (d))
21350397Sobrien
21450397Sobrien/* Inverse of REAL_VALUE_TO_TARGET_SINGLE. */
21550397Sobrien#define REAL_VALUE_UNTO_TARGET_SINGLE(f)  (ereal_unto_float (f))
21650397Sobrien
21718334Speter/* d is an array of HOST_WIDE_INT that holds a double precision
21818334Speter   value in the target computer's floating point format. */
21918334Speter#define REAL_VALUE_FROM_TARGET_DOUBLE(d)  (ereal_from_double (d))
22018334Speter
22118334Speter/* f is a HOST_WIDE_INT containing a single precision target float value. */
22218334Speter#define REAL_VALUE_FROM_TARGET_SINGLE(f)  (ereal_from_float (f))
22318334Speter
22418334Speter/* Conversions to decimal ASCII string.  */
22518334Speter#define REAL_VALUE_TO_DECIMAL(r, fmt, s) (ereal_to_decimal (r, s))
22618334Speter
22718334Speter#endif /* REAL_ARITHMETIC defined */
22818334Speter
22918334Speter/* **** End of software floating point emulator interface macros **** */
23018334Speter#else /* No XFmode or TFmode and REAL_ARITHMETIC not defined */
23118334Speter
23218334Speter/* old interface */
23318334Speter#ifdef REAL_ARITHMETIC
23418334Speter/* Defining REAL_IS_NOT_DOUBLE breaks certain initializations
23518334Speter   when REAL_ARITHMETIC etc. are not defined.  */
23618334Speter
23718334Speter/* Now see if the host and target machines use the same format.
23818334Speter   If not, define REAL_IS_NOT_DOUBLE (even if we end up representing
23918334Speter   reals as doubles because we have no better way in this cross compiler.)
24018334Speter   This turns off various optimizations that can happen when we know the
24118334Speter   compiler's float format matches the target's float format.
24218334Speter   */
24318334Speter#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
24418334Speter#define	REAL_IS_NOT_DOUBLE
24518334Speter#ifndef REAL_VALUE_TYPE
24618334Spetertypedef struct {
24718334Speter    HOST_WIDE_INT r[sizeof (double)/sizeof (HOST_WIDE_INT)];
24818334Speter  } realvaluetype;
24918334Speter#define REAL_VALUE_TYPE realvaluetype
25018334Speter#endif /* no REAL_VALUE_TYPE */
25118334Speter#endif /* formats differ */
25218334Speter#endif /* 0 */
25318334Speter
25418334Speter#endif /* emulator not used */
25518334Speter
25618334Speter/* If we are not cross-compiling, use a `double' to represent the
25718334Speter   floating-point value.  Otherwise, use some other type
25818334Speter   (probably a struct containing an array of longs).  */
25918334Speter#ifndef REAL_VALUE_TYPE
26018334Speter#define REAL_VALUE_TYPE double
26118334Speter#else
26218334Speter#define REAL_IS_NOT_DOUBLE
26318334Speter#endif
26418334Speter
26518334Speter#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
26618334Speter
26718334Speter/* Convert a type `double' value in host format first to a type `float'
26818334Speter   value in host format and then to a single type `long' value which
26918334Speter   is the bitwise equivalent of the `float' value.  */
27018334Speter#ifndef REAL_VALUE_TO_TARGET_SINGLE
27150397Sobrien#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT)		\
27250397Sobriendo {							\
27350397Sobrien  union {						\
27450397Sobrien    float f;						\
27550397Sobrien    HOST_WIDE_INT l;					\
27650397Sobrien  } u;							\
27750397Sobrien  if (sizeof(HOST_WIDE_INT) < sizeof(float))		\
27850397Sobrien    abort();						\
27950397Sobrien  u.l = 0;						\
28050397Sobrien  u.f = (IN);						\
28150397Sobrien  (OUT) = u.l;						\
28250397Sobrien} while (0)
28318334Speter#endif
28418334Speter
28518334Speter/* Convert a type `double' value in host format to a pair of type `long'
28618334Speter   values which is its bitwise equivalent, but put the two words into
28718334Speter   proper word order for the target.  */
28818334Speter#ifndef REAL_VALUE_TO_TARGET_DOUBLE
28918334Speter#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT)				\
29050397Sobriendo {									\
29150397Sobrien  union {								\
29250397Sobrien    REAL_VALUE_TYPE f;							\
29350397Sobrien    HOST_WIDE_INT l[2];							\
29450397Sobrien  } u;									\
29550397Sobrien  if (sizeof(HOST_WIDE_INT) * 2 < sizeof(REAL_VALUE_TYPE))		\
29650397Sobrien    abort();								\
29750397Sobrien  u.l[0] = u.l[1] = 0;							\
29850397Sobrien  u.f = (IN);								\
29950397Sobrien  if (HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_WORDS_BIG_ENDIAN)		\
30050397Sobrien    (OUT)[0] = u.l[0], (OUT)[1] = u.l[1];				\
30150397Sobrien  else									\
30250397Sobrien    (OUT)[1] = u.l[0], (OUT)[0] = u.l[1];				\
30350397Sobrien} while (0)
30418334Speter#endif
30518334Speter#endif /* HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT */
30618334Speter
30718334Speter/* In this configuration, double and long double are the same. */
30818334Speter#ifndef REAL_VALUE_TO_TARGET_LONG_DOUBLE
30918334Speter#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(a, b) REAL_VALUE_TO_TARGET_DOUBLE (a, b)
31018334Speter#endif
31118334Speter
31250397Sobrien/* Compare two floating-point objects for bitwise identity.
31350397Sobrien   This is not the same as comparing for equality on IEEE hosts:
31450397Sobrien   -0.0 equals 0.0 but they are not identical, and conversely
31550397Sobrien   two NaNs might be identical but they cannot be equal.  */
31650397Sobrien#define REAL_VALUES_IDENTICAL(x, y) \
31750397Sobrien  (!bcmp ((char *) &(x), (char *) &(y), sizeof (REAL_VALUE_TYPE)))
31850397Sobrien
31918334Speter/* Compare two floating-point values for equality.  */
32018334Speter#ifndef REAL_VALUES_EQUAL
32118334Speter#define REAL_VALUES_EQUAL(x, y) ((x) == (y))
32218334Speter#endif
32318334Speter
32418334Speter/* Compare two floating-point values for less than.  */
32518334Speter#ifndef REAL_VALUES_LESS
32618334Speter#define REAL_VALUES_LESS(x, y) ((x) < (y))
32718334Speter#endif
32818334Speter
32918334Speter/* Truncate toward zero to an integer floating-point value.  */
33018334Speter#ifndef REAL_VALUE_RNDZINT
33118334Speter#define REAL_VALUE_RNDZINT(x) ((double) ((int) (x)))
33218334Speter#endif
33318334Speter
33418334Speter/* Truncate toward zero to an unsigned integer floating-point value.  */
33518334Speter#ifndef REAL_VALUE_UNSIGNED_RNDZINT
33618334Speter#define REAL_VALUE_UNSIGNED_RNDZINT(x) ((double) ((unsigned int) (x)))
33718334Speter#endif
33818334Speter
33918334Speter/* Convert a floating-point value to integer, rounding toward zero.  */
34018334Speter#ifndef REAL_VALUE_FIX
34118334Speter#define REAL_VALUE_FIX(x) ((int) (x))
34218334Speter#endif
34318334Speter
34418334Speter/* Convert a floating-point value to unsigned integer, rounding
34518334Speter   toward zero. */
34618334Speter#ifndef REAL_VALUE_UNSIGNED_FIX
34718334Speter#define REAL_VALUE_UNSIGNED_FIX(x) ((unsigned int) (x))
34818334Speter#endif
34918334Speter
35018334Speter/* Scale X by Y powers of 2.  */
35118334Speter#ifndef REAL_VALUE_LDEXP
35218334Speter#define REAL_VALUE_LDEXP(x, y) ldexp (x, y)
35318334Speterextern double ldexp ();
35418334Speter#endif
35518334Speter
35618334Speter/* Convert the string X to a floating-point value.  */
35718334Speter#ifndef REAL_VALUE_ATOF
35818334Speter#if 1
35918334Speter/* Use real.c to convert decimal numbers to binary, ... */
36018334SpeterREAL_VALUE_TYPE ereal_atof ();
36118334Speter#define REAL_VALUE_ATOF(x, s) ereal_atof (x, s)
36252284Sobrien/* Could use ereal_atof here for hexadecimal floats too, but real_hex_to_f
36352284Sobrien   is OK and it uses faster native fp arithmetic.  */
36452284Sobrien/* #define REAL_VALUE_HTOF(x, s) ereal_atof (x, s) */
36518334Speter#else
36618334Speter/* ... or, if you like the host computer's atof, go ahead and use it: */
36718334Speter#define REAL_VALUE_ATOF(x, s) atof (x)
36818334Speter#if defined (MIPSEL) || defined (MIPSEB)
36918334Speter/* MIPS compiler can't handle parens around the function name.
37018334Speter   This problem *does not* appear to be connected with any
37118334Speter   macro definition for atof.  It does not seem there is one.  */
37218334Speterextern double atof ();
37318334Speter#else
37418334Speterextern double (atof) ();
37518334Speter#endif
37618334Speter#endif
37718334Speter#endif
37818334Speter
37952284Sobrien/* Hexadecimal floating constant input for use with host computer's
38052284Sobrien   fp arithmetic.  */
38152284Sobrien#ifndef REAL_VALUE_HTOF
38252284Sobrienextern REAL_VALUE_TYPE real_hex_to_f PROTO((char *, enum machine_mode));
38352284Sobrien#define REAL_VALUE_HTOF(s,m) real_hex_to_f(s,m)
38452284Sobrien#endif
38552284Sobrien
38618334Speter/* Negate the floating-point value X.  */
38718334Speter#ifndef REAL_VALUE_NEGATE
38818334Speter#define REAL_VALUE_NEGATE(x) (- (x))
38918334Speter#endif
39018334Speter
39118334Speter/* Truncate the floating-point value X to mode MODE.  This is correct only
39218334Speter   for the most common case where the host and target have objects of the same
39318334Speter   size and where `float' is SFmode.  */
39418334Speter
39518334Speter/* Don't use REAL_VALUE_TRUNCATE directly--always call real_value_truncate.  */
39650397Sobrienextern REAL_VALUE_TYPE real_value_truncate PROTO((enum machine_mode, REAL_VALUE_TYPE));
39718334Speter
39818334Speter#ifndef REAL_VALUE_TRUNCATE
39918334Speter#define REAL_VALUE_TRUNCATE(mode, x) \
40018334Speter (GET_MODE_BITSIZE (mode) == sizeof (float) * HOST_BITS_PER_CHAR	\
40118334Speter  ? (float) (x) : (x))
40218334Speter#endif
40318334Speter
40418334Speter/* Determine whether a floating-point value X is infinite. */
40518334Speter#ifndef REAL_VALUE_ISINF
40618334Speter#define REAL_VALUE_ISINF(x) (target_isinf (x))
40718334Speter#endif
40818334Speter
40918334Speter/* Determine whether a floating-point value X is a NaN. */
41018334Speter#ifndef REAL_VALUE_ISNAN
41118334Speter#define REAL_VALUE_ISNAN(x) (target_isnan (x))
41218334Speter#endif
41318334Speter
41418334Speter/* Determine whether a floating-point value X is negative. */
41518334Speter#ifndef REAL_VALUE_NEGATIVE
41618334Speter#define REAL_VALUE_NEGATIVE(x) (target_negative (x))
41718334Speter#endif
41818334Speter
41950397Sobrienextern int target_isnan			PROTO ((REAL_VALUE_TYPE));
42050397Sobrienextern int target_isinf			PROTO ((REAL_VALUE_TYPE));
42150397Sobrienextern int target_negative		PROTO ((REAL_VALUE_TYPE));
42250397Sobrien
42318334Speter/* Determine whether a floating-point value X is minus 0. */
42418334Speter#ifndef REAL_VALUE_MINUS_ZERO
42518334Speter#define REAL_VALUE_MINUS_ZERO(x) ((x) == 0 && REAL_VALUE_NEGATIVE (x))
42618334Speter#endif
42718334Speter
42818334Speter/* Constant real values 0, 1, 2, and -1.  */
42918334Speter
43018334Speterextern REAL_VALUE_TYPE dconst0;
43118334Speterextern REAL_VALUE_TYPE dconst1;
43218334Speterextern REAL_VALUE_TYPE dconst2;
43318334Speterextern REAL_VALUE_TYPE dconstm1;
43418334Speter
43518334Speter/* Union type used for extracting real values from CONST_DOUBLEs
43618334Speter   or putting them in.  */
43718334Speter
43818334Speterunion real_extract
43918334Speter{
44018334Speter  REAL_VALUE_TYPE d;
44118334Speter  HOST_WIDE_INT i[sizeof (REAL_VALUE_TYPE) / sizeof (HOST_WIDE_INT)];
44218334Speter};
44318334Speter
44418334Speter/* For a CONST_DOUBLE:
44518334Speter   The usual two ints that hold the value.
44618334Speter   For a DImode, that is all there are;
44718334Speter    and CONST_DOUBLE_LOW is the low-order word and ..._HIGH the high-order.
44818334Speter   For a float, the number of ints varies,
44918334Speter    and CONST_DOUBLE_LOW is the one that should come first *in memory*.
45018334Speter    So use &CONST_DOUBLE_LOW(r) as the address of an array of ints.  */
45118334Speter#define CONST_DOUBLE_LOW(r) XWINT (r, 2)
45218334Speter#define CONST_DOUBLE_HIGH(r) XWINT (r, 3)
45318334Speter
45418334Speter/* Link for chain of all CONST_DOUBLEs in use in current function.  */
45518334Speter#define CONST_DOUBLE_CHAIN(r) XEXP (r, 1)
45618334Speter/* The MEM which represents this CONST_DOUBLE's value in memory,
45718334Speter   or const0_rtx if no MEM has been made for it yet,
45818334Speter   or cc0_rtx if it is not on the chain.  */
45918334Speter#define CONST_DOUBLE_MEM(r) XEXP (r, 0)
46018334Speter
46150397Sobrien/* Given a CONST_DOUBLE in FROM, store into TO the value it represents.  */
46218334Speter/* Function to return a real value (not a tree node)
46318334Speter   from a given integer constant.  */
46450397Sobrienunion tree_node;
46550397SobrienREAL_VALUE_TYPE real_value_from_int_cst	PROTO ((union tree_node *,
46650397Sobrien						union tree_node *));
46718334Speter
46818334Speter#define REAL_VALUE_FROM_CONST_DOUBLE(to, from)		\
46918334Speterdo { union real_extract u;				\
47018334Speter     bcopy ((char *) &CONST_DOUBLE_LOW ((from)), (char *) &u, sizeof u); \
47118334Speter     to = u.d; } while (0)
47218334Speter
47318334Speter/* Return a CONST_DOUBLE with value R and mode M.  */
47418334Speter
47518334Speter#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) immed_real_const_1 (r,  m)
47618334Speterextern struct rtx_def *immed_real_const_1	PROTO((REAL_VALUE_TYPE,
47718334Speter						       enum machine_mode));
47818334Speter
47918334Speter
48018334Speter/* Convert a floating point value `r', that can be interpreted
48118334Speter   as a host machine float or double, to a decimal ASCII string `s'
48218334Speter   using printf format string `fmt'.  */
48318334Speter#ifndef REAL_VALUE_TO_DECIMAL
48418334Speter#define REAL_VALUE_TO_DECIMAL(r, fmt, s) (sprintf (s, fmt, r))
48518334Speter#endif
48618334Speter
48750397Sobrien/* Replace R by 1/R in the given machine mode, if the result is exact.  */
48850397Sobrienextern int exact_real_inverse PROTO((enum machine_mode, REAL_VALUE_TYPE *));
48950397Sobrien
49050397Sobrienextern void debug_real			PROTO ((REAL_VALUE_TYPE));
49150397Sobrien
49250397Sobrien/* In varasm.c */
49350397Sobrienextern void assemble_real		PROTO ((REAL_VALUE_TYPE,
49450397Sobrien						enum machine_mode));
49518334Speter#endif /* Not REAL_H_INCLUDED */
496