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