#ifndef GCC_REAL_H
#define GCC_REAL_H
+#include "machmode.h"
+
/* Define codes for all the float formats that we know of. */
#define UNKNOWN_FLOAT_FORMAT 0
#define IEEE_FLOAT_FORMAT 1
/* **** Start of software floating point emulator interface macros **** */
/* REAL_VALUE_TYPE is an array of the minimum number of HOST_WIDE_INTs
- required to hold MAX_LONG_DOUBLE_TYPE_SIZE bits. */
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 128
-/* For 128 bit reals, we calculate internally with extra precision. */
-#define N (160 / BITS_PER_UNIT)
+ required to hold either a 96- or 160-bit extended precision floating
+ point type. This is true even if the maximum precision floating
+ point type on the target is smaller. */
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !INTEL_EXTENDED_IEEE_FORMAT
+#define REAL_VALUE_TYPE_SIZE 160
+#else
+#define REAL_VALUE_TYPE_SIZE 96
+#endif
+#define REAL_WIDTH \
+ (REAL_VALUE_TYPE_SIZE/HOST_BITS_PER_WIDE_INT \
+ + (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */
+struct realvaluetype GTY(()) {
+ HOST_WIDE_INT r[REAL_WIDTH];
+};
+/* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it needs
+ to be a macro. realvaluetype cannot be a typedef as this interferes with
+ other headers declaring opaque pointers to it. */
+#define REAL_VALUE_TYPE struct realvaluetype
+
+/* Calculate the format for CONST_DOUBLE. We need as many slots as
+ are necessary to overlay a REAL_VALUE_TYPE on them. This could be
+ as many as five (32-bit HOST_WIDE_INT, 160-bit REAL_VALUE_TYPE).
+
+ A number of places assume that there are always at least two 'w'
+ slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
+
+#if REAL_WIDTH == 1
+# define CONST_DOUBLE_FORMAT "ww"
#else
-#define N (MAX_LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)
+# if REAL_WIDTH == 2
+# define CONST_DOUBLE_FORMAT "ww"
+# else
+# if REAL_WIDTH == 3
+# define CONST_DOUBLE_FORMAT "www"
+# else
+# if REAL_WIDTH == 4
+# define CONST_DOUBLE_FORMAT "wwww"
+# else
+# if REAL_WIDTH == 5
+# define CONST_DOUBLE_FORMAT "wwwww"
+# else
+ #error "REAL_WIDTH > 5 not supported"
+# endif
+# endif
+# endif
+# endif
#endif
-#define S sizeof (HOST_WIDE_INT)
-typedef struct {
- HOST_WIDE_INT r[N/S + (N%S ? 1 : 0)]; /* round up */
-} REAL_VALUE_TYPE;
-#undef N
-#undef S
extern unsigned int significand_size PARAMS ((enum machine_mode));
extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
REAL_VALUE_TYPE));
+/* Expansion of REAL_VALUE_TRUNCATE.
+ The result is in floating point, rounded to nearest or even. */
+extern bool exact_real_truncate PARAMS ((enum machine_mode,
+ REAL_VALUE_TYPE *));
+
/* These return HOST_WIDE_INT: */
/* Convert a floating-point value to integer, rounding toward zero. */
#define REAL_VALUE_FIX(x) (efixi (x))
#define REAL_VALUE_NEGATE ereal_negate
+/* Compute the absolute value of a floating-point value X. */
+#define REAL_VALUE_ABS(x) \
+ (REAL_VALUE_NEGATIVE (x) ? REAL_VALUE_NEGATE (x) : (x))
+
/* Determine whether a floating-point value X is infinite. */
#define REAL_VALUE_ISINF(x) (target_isinf (x))
/* 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));
+#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) \
+ const_double_from_real_value (r, m)
+extern rtx const_double_from_real_value PARAMS ((REAL_VALUE_TYPE,
+ enum machine_mode));
+
+/* Shorthand; can be handy in machine descriptions. */
+#define CONST_DOUBLE_ATOF(s, m) \
+ CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_ATOF (s, m), m)
/* 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 void debug_real PARAMS ((REAL_VALUE_TYPE));
extern REAL_VALUE_TYPE ereal_atof PARAMS ((const char *, enum machine_mode));
+/* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node. */
+extern tree build_real PARAMS ((tree, REAL_VALUE_TYPE));
+
+
#endif /* ! GCC_REAL_H */