OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / real.h
index b946619..ccd0541 100644 (file)
@@ -1,5 +1,6 @@
-/* Front-end tree definitions for GNU compiler.
-   Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+/* Definitions of floating-point access for GNU compiler.
+   Copyright (C) 1989, 1991, 1994, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 #ifndef REAL_H_INCLUDED
 #define REAL_H_INCLUDED
@@ -25,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define IEEE_FLOAT_FORMAT 1
 #define VAX_FLOAT_FORMAT 2
 #define IBM_FLOAT_FORMAT 3
+#define C4X_FLOAT_FORMAT 4
 
 /* Default to IEEE float if not specified.  Nearly all machines use it.  */
 
@@ -40,6 +43,24 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define REAL_INFINITY
 #endif
 
+/* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
+   in the header files, then this implies the word-endianness is the same as
+   for integers.  */
+
+/* This is defined 0 or 1, like WORDS_BIG_ENDIAN.  */
+#ifndef FLOAT_WORDS_BIG_ENDIAN
+#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+/* This is defined 0 or 1, unlike HOST_WORDS_BIG_ENDIAN.  */
+#ifndef HOST_FLOAT_WORDS_BIG_ENDIAN
+#ifdef HOST_WORDS_BIG_ENDIAN
+#define HOST_FLOAT_WORDS_BIG_ENDIAN 1
+#else
+#define HOST_FLOAT_WORDS_BIG_ENDIAN 0
+#endif
+#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
@@ -47,12 +68,25 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #ifndef LONG_DOUBLE_TYPE_SIZE
 #define LONG_DOUBLE_TYPE_SIZE 64
 #endif
-#if (LONG_DOUBLE_TYPE_SIZE == 96) || defined (REAL_ARITHMETIC)
+/* MAX_LONG_DOUBLE_TYPE_SIZE is a constant tested by #if.
+   LONG_DOUBLE_TYPE_SIZE can vary at compiler run time.
+   So long as macros like REAL_VALUE_TO_TARGET_LONG_DOUBLE cannot
+   vary too, however, then XFmode and TFmode long double
+   cannot both be supported at the same time.  */
+#ifndef MAX_LONG_DOUBLE_TYPE_SIZE
+#define MAX_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
+#endif
+#if (MAX_LONG_DOUBLE_TYPE_SIZE == 96) || (MAX_LONG_DOUBLE_TYPE_SIZE == 128)
+#ifndef REAL_ARITHMETIC
+#define REAL_ARITHMETIC
+#endif
+#endif
+#ifdef 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)
+#if (MAX_LONG_DOUBLE_TYPE_SIZE == 96)
 #define REAL_IS_NOT_DOUBLE
 #define REAL_ARITHMETIC
 typedef struct {
@@ -62,6 +96,17 @@ typedef struct {
 
 #else /* no XFmode support */
 
+#if (MAX_LONG_DOUBLE_TYPE_SIZE == 128)
+
+#define REAL_IS_NOT_DOUBLE
+#define REAL_ARITHMETIC
+typedef struct {
+  HOST_WIDE_INT r[(19 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
+} realvaluetype;
+#define REAL_VALUE_TYPE realvaluetype
+
+#else /* not TFmode */
+
 #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. */
@@ -75,10 +120,14 @@ typedef struct {
    is actually a host machine double. */
 #define REAL_VALUE_TYPE double
 #endif
+
+#endif /* no TFmode support */
 #endif /* no XFmode support */
 
+extern unsigned int significand_size   PARAMS ((enum machine_mode));
+
 /* If emulation has been enabled by defining REAL_ARITHMETIC or by
-   setting LONG_DOUBLE_TYPE_SIZE to 96, then define macros so that
+   setting LONG_DOUBLE_TYPE_SIZE to 96 or 128, 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.  */
@@ -87,14 +136,37 @@ typedef struct {
 #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 ();
+/* Declare functions in real.c. */
+extern void earith             PARAMS ((REAL_VALUE_TYPE *, int,
+                                      REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
+extern REAL_VALUE_TYPE etrunci PARAMS ((REAL_VALUE_TYPE));
+extern REAL_VALUE_TYPE etruncui        PARAMS ((REAL_VALUE_TYPE));
+extern REAL_VALUE_TYPE ereal_atof PARAMS ((const char *, enum machine_mode));
+extern REAL_VALUE_TYPE ereal_negate PARAMS ((REAL_VALUE_TYPE));
+extern HOST_WIDE_INT efixi     PARAMS ((REAL_VALUE_TYPE));
+extern unsigned HOST_WIDE_INT efixui PARAMS ((REAL_VALUE_TYPE));
+extern void ereal_from_int     PARAMS ((REAL_VALUE_TYPE *,
+                                      HOST_WIDE_INT, HOST_WIDE_INT,
+                                      enum machine_mode));
+extern void ereal_from_uint    PARAMS ((REAL_VALUE_TYPE *,
+                                      unsigned HOST_WIDE_INT,
+                                      unsigned HOST_WIDE_INT,
+                                      enum machine_mode));
+extern void ereal_to_int       PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *,
+                                      REAL_VALUE_TYPE));
+extern REAL_VALUE_TYPE ereal_ldexp PARAMS ((REAL_VALUE_TYPE, int));
+
+extern void etartdouble                PARAMS ((REAL_VALUE_TYPE, long *));
+extern void etarldouble                PARAMS ((REAL_VALUE_TYPE, long *));
+extern void etardouble         PARAMS ((REAL_VALUE_TYPE, long *));
+extern long etarsingle         PARAMS ((REAL_VALUE_TYPE));
+extern void ereal_to_decimal   PARAMS ((REAL_VALUE_TYPE, char *));
+extern int ereal_cmp           PARAMS ((REAL_VALUE_TYPE, REAL_VALUE_TYPE));
+extern int ereal_isneg         PARAMS ((REAL_VALUE_TYPE));
+extern REAL_VALUE_TYPE ereal_unto_float PARAMS ((long));
+extern REAL_VALUE_TYPE ereal_unto_double PARAMS ((long *));
+extern REAL_VALUE_TYPE ereal_from_float PARAMS ((HOST_WIDE_INT));
+extern REAL_VALUE_TYPE ereal_from_double PARAMS ((HOST_WIDE_INT *));
 
 #define REAL_VALUES_EQUAL(x, y) (ereal_cmp ((x), (y)) == 0)
 /* true if x < y : */
@@ -104,37 +176,67 @@ REAL_VALUE_TYPE ereal_negate (), ereal_truncate ();
 /* 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 ();
+extern REAL_VALUE_TYPE real_value_truncate     PARAMS ((enum machine_mode,
+                                                       REAL_VALUE_TYPE));
 #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))
+/* These return HOST_WIDE_INT: */
+/* Convert a floating-point value to integer, rounding toward zero.  */
+#define REAL_VALUE_FIX(x) (efixi (x))
+/* Convert a floating-point value to unsigned integer, rounding
+   toward zero. */
+#define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
+
+/* Convert ASCII string S to floating point in mode M.
+   Decimal input uses ATOF.  Hexadecimal uses HTOF.  */
+#define REAL_VALUE_ATOF(s,m) ereal_atof(s,m)
+#define REAL_VALUE_HTOF(s,m) ereal_atof(s,m)
 
-#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))
+
+/* Here the cast to HOST_WIDE_INT sign-extends arguments such as ~0.  */
+#define REAL_VALUE_FROM_INT(d, lo, hi, mode) \
+  ereal_from_int (&d, (HOST_WIDE_INT) (lo), (HOST_WIDE_INT) (hi), mode)
+
+#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
+  ereal_from_uint (&d, lo, hi, mode)
 
 /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs. */
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 96
 #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) (etarldouble ((IN), (OUT)))
+#else
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) (etartdouble ((IN), (OUT)))
+#endif
 #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)))
 
+/* Inverse of REAL_VALUE_TO_TARGET_DOUBLE. */
+#define REAL_VALUE_UNTO_TARGET_DOUBLE(d)  (ereal_unto_double (d))
+
+/* Inverse of REAL_VALUE_TO_TARGET_SINGLE. */
+#define REAL_VALUE_UNTO_TARGET_SINGLE(f)  (ereal_unto_float (f))
+
+/* d is an array of HOST_WIDE_INT that holds a double precision
+   value in the target computer's floating point format. */
+#define REAL_VALUE_FROM_TARGET_DOUBLE(d)  (ereal_from_double (d))
+
+/* f is a HOST_WIDE_INT containing a single precision target float value. */
+#define REAL_VALUE_FROM_TARGET_SINGLE(f)  (ereal_from_float (f))
+
 /* 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 */
+#else /* No XFmode or TFmode and REAL_ARITHMETIC not defined */
 
 /* old interface */
 #ifdef REAL_ARITHMETIC
@@ -175,29 +277,39 @@ typedef struct {
    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)
+#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT)           \
+do {                                                   \
+  union {                                              \
+    float f;                                           \
+    HOST_WIDE_INT l;                                   \
+  } u;                                                 \
+  if (sizeof(HOST_WIDE_INT) < sizeof(float))           \
+    abort();                                           \
+  u.l = 0;                                             \
+  u.f = (IN);                                          \
+  (OUT) = u.l;                                         \
+} 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.  */\
-     (OUT)[0] = ((long *) &in)[0];                                     \
-     (OUT)[1] = ((long *) &in)[1];                                     \
-   } while (0)
-#else
-#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT)                           \
-do { REAL_VALUE_TYPE in = (IN);  /* Make sure it's not in a register.  */\
-     (OUT)[1] = ((long *) &in)[0];                                     \
-     (OUT)[0] = ((long *) &in)[1];                                     \
-   } while (0)
-#endif
+do {                                                                   \
+  union {                                                              \
+    REAL_VALUE_TYPE f;                                                 \
+    HOST_WIDE_INT l[2];                                                        \
+  } u;                                                                 \
+  if (sizeof(HOST_WIDE_INT) * 2 < sizeof(REAL_VALUE_TYPE))             \
+    abort();                                                           \
+  u.l[0] = u.l[1] = 0;                                                 \
+  u.f = (IN);                                                          \
+  if (HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_WORDS_BIG_ENDIAN)           \
+    (OUT)[0] = u.l[0], (OUT)[1] = u.l[1];                              \
+  else                                                                 \
+    (OUT)[1] = u.l[0], (OUT)[0] = u.l[1];                              \
+} while (0)
 #endif
 #endif /* HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT */
 
@@ -206,6 +318,13 @@ do { REAL_VALUE_TYPE in = (IN);  /* Make sure it's not in a register.  */\
 #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(a, b) REAL_VALUE_TO_TARGET_DOUBLE (a, b)
 #endif
 
+/* Compare two floating-point objects for bitwise identity.
+   This is not the same as comparing for equality on IEEE hosts:
+   -0.0 equals 0.0 but they are not identical, and conversely
+   two NaNs might be identical but they cannot be equal.  */
+#define REAL_VALUES_IDENTICAL(x, y) \
+  (!bcmp ((char *) &(x), (char *) &(y), sizeof (REAL_VALUE_TYPE)))
+
 /* Compare two floating-point values for equality.  */
 #ifndef REAL_VALUES_EQUAL
 #define REAL_VALUES_EQUAL(x, y) ((x) == (y))
@@ -226,13 +345,13 @@ do { REAL_VALUE_TYPE in = (IN);  /* Make sure it's not in a register.  */\
 #define REAL_VALUE_UNSIGNED_RNDZINT(x) ((double) ((unsigned int) (x)))
 #endif
 
-/* Convert a floating-point value to integer, using any rounding mode.  */
+/* Convert a floating-point value to integer, rounding toward zero.  */
 #ifndef REAL_VALUE_FIX
 #define REAL_VALUE_FIX(x) ((int) (x))
 #endif
 
-/* Convert a floating-point value to unsigned integer, using any rounding
-   mode.  */
+/* Convert a floating-point value to unsigned integer, rounding
+   toward zero. */
 #ifndef REAL_VALUE_UNSIGNED_FIX
 #define REAL_VALUE_UNSIGNED_FIX(x) ((unsigned int) (x))
 #endif
@@ -240,15 +359,18 @@ 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)
-extern double ldexp ();
+extern double ldexp PARAMS ((double, int));
 #endif
 
 /* Convert the string X to a floating-point value.  */
 #ifndef REAL_VALUE_ATOF
 #if 1
 /* Use real.c to convert decimal numbers to binary, ... */
-REAL_VALUE_TYPE ereal_atof ();
+extern REAL_VALUE_TYPE ereal_atof PARAMS ((const char *, enum machine_mode));
 #define REAL_VALUE_ATOF(x, s) ereal_atof (x, s)
+/* Could use ereal_atof here for hexadecimal floats too, but real_hex_to_f
+   is OK and it uses faster native fp arithmetic.  */
+/* #define REAL_VALUE_HTOF(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)
@@ -263,6 +385,13 @@ extern double (atof) ();
 #endif
 #endif
 
+/* Hexadecimal floating constant input for use with host computer's
+   fp arithmetic.  */
+#ifndef REAL_VALUE_HTOF
+extern REAL_VALUE_TYPE real_hex_to_f PARAMS ((char *, enum machine_mode));
+#define REAL_VALUE_HTOF(s,m) real_hex_to_f(s,m)
+#endif
+
 /* Negate the floating-point value X.  */
 #ifndef REAL_VALUE_NEGATE
 #define REAL_VALUE_NEGATE(x) (- (x))
@@ -273,7 +402,8 @@ extern double (atof) ();
    size and where `float' is SFmode.  */
 
 /* Don't use REAL_VALUE_TRUNCATE directly--always call real_value_truncate.  */
-extern REAL_VALUE_TYPE real_value_truncate ();
+extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
+                                                 REAL_VALUE_TYPE));
 
 #ifndef REAL_VALUE_TRUNCATE
 #define REAL_VALUE_TRUNCATE(mode, x) \
@@ -296,6 +426,10 @@ extern REAL_VALUE_TYPE real_value_truncate ();
 #define REAL_VALUE_NEGATIVE(x) (target_negative (x))
 #endif
 
+extern int target_isnan                        PARAMS ((REAL_VALUE_TYPE));
+extern int target_isinf                        PARAMS ((REAL_VALUE_TYPE));
+extern int target_negative             PARAMS ((REAL_VALUE_TYPE));
+
 /* Determine whether a floating-point value X is minus 0. */
 #ifndef REAL_VALUE_MINUS_ZERO
 #define REAL_VALUE_MINUS_ZERO(x) ((x) == 0 && REAL_VALUE_NEGATIVE (x))
@@ -328,26 +462,30 @@ union real_extract
 #define CONST_DOUBLE_HIGH(r) XWINT (r, 3)
 
 /* Link for chain of all CONST_DOUBLEs in use in current function.  */
-#define CONST_DOUBLE_CHAIN(r) XEXP (r, 1)
+#define CONST_DOUBLE_CHAIN(r) X0EXP (r, 1)
 /* The MEM which represents this CONST_DOUBLE's value in memory,
    or const0_rtx if no MEM has been made for it yet,
    or cc0_rtx if it is not on the chain.  */
 #define CONST_DOUBLE_MEM(r) XEXP (r, 0)
 
+/* Given a CONST_DOUBLE in FROM, store into TO the value it represents.  */
 /* Function to return a real value (not a tree node)
    from a given integer constant.  */
-REAL_VALUE_TYPE real_value_from_int_cst ();
-
-/* Given a CONST_DOUBLE in FROM, store into TO the value it represents.  */
+union tree_node;
+REAL_VALUE_TYPE real_value_from_int_cst        PARAMS ((union tree_node *,
+                                               union tree_node *));
 
 #define REAL_VALUE_FROM_CONST_DOUBLE(to, from)         \
 do { union real_extract u;                             \
-     bcopy (&CONST_DOUBLE_LOW ((from)), &u, sizeof u); \
+     bcopy ((char *) &CONST_DOUBLE_LOW ((from)), (char *) &u, sizeof u); \
      to = u.d; } while (0)
 
 /* Return a CONST_DOUBLE with value R and mode M.  */
 
 #define CONST_DOUBLE_FROM_REAL_VALUE(r, m) immed_real_const_1 (r,  m)
+extern struct rtx_def *immed_real_const_1      PARAMS ((REAL_VALUE_TYPE,
+                                                      enum machine_mode));
+
 
 /* Convert a floating point value `r', that can be interpreted
    as a host machine float or double, to a decimal ASCII string `s'
@@ -356,4 +494,19 @@ do { union real_extract u;                         \
 #define REAL_VALUE_TO_DECIMAL(r, fmt, s) (sprintf (s, fmt, r))
 #endif
 
+/* Replace R by 1/R in the given machine mode, if the result is exact.  */
+extern int exact_real_inverse  PARAMS ((enum machine_mode, REAL_VALUE_TYPE *));
+extern int target_isnan                PARAMS ((REAL_VALUE_TYPE));
+extern int target_isinf                PARAMS ((REAL_VALUE_TYPE));
+extern int target_negative     PARAMS ((REAL_VALUE_TYPE));
+extern void debug_real         PARAMS ((REAL_VALUE_TYPE));
+
+/* In varasm.c */
+extern void assemble_real              PARAMS ((REAL_VALUE_TYPE,
+                                              enum machine_mode));
+extern void debug_real                 PARAMS ((REAL_VALUE_TYPE));
+
+/* In varasm.c */
+extern void assemble_real              PARAMS ((REAL_VALUE_TYPE,
+                                              enum machine_mode));
 #endif /* Not REAL_H_INCLUDED */