X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Freal.h;h=31fa56140a9de10c53f0d863290ad3c97b71c1fc;hb=aa870c1bd9a934cad1315b215c0bbcaf7858b6f5;hp=3e691ff436ac825ff27bd40fdd46e7c63bb40d29;hpb=b088f6825dae039ade6c891b0a3f275a082dfdac;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/real.h b/gcc/real.h index 3e691ff436a..31fa56140a9 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -1,29 +1,162 @@ -/* 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, 2002 Free Software Foundation, Inc. -This file is part of GNU CC. + This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ -#ifndef REAL_H_INCLUDED -#define REAL_H_INCLUDED +#ifndef GCC_REAL_H +#define GCC_REAL_H + +#include "machmode.h" + +/* REAL_VALUE_TYPE is an array of the minimum number of HOST_WIDE_INTs + required to hold a 128-bit floating point type. This is true even + if the maximum precision floating point type on the target is smaller. + + The extra 32 bits are for storing the mode of the float. Ideally + we'd keep this elsewhere, but that's too drastic a change all at once. */ + +#define REAL_VALUE_TYPE_SIZE (128 + 32) +#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 four (32-bit HOST_WIDE_INT, 128-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 +# 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 + +/* Declare functions in real.c. */ + +/* Initialize the emulator. */ +extern void init_real_once PARAMS ((void)); + +/* Binary or unary arithmetic on tree_code. */ +extern void real_arithmetic PARAMS ((REAL_VALUE_TYPE *, int, + const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *)); + +/* Compare reals by tree_code. */ +extern bool real_compare PARAMS ((int, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *)); + +/* Determine whether a floating-point value X is infinite. */ +extern bool real_isinf PARAMS ((const REAL_VALUE_TYPE *)); + +/* Determine whether a floating-point value X is a NaN. */ +extern bool real_isnan PARAMS ((const REAL_VALUE_TYPE *)); + +/* Determine whether a floating-point value X is negative. */ +extern bool real_isneg PARAMS ((const REAL_VALUE_TYPE *)); + +/* Determine whether a floating-point value X is minus zero. */ +extern bool real_isnegzero PARAMS ((const REAL_VALUE_TYPE *)); + +/* Compare two floating-point objects for bitwise identity. */ +extern bool real_identical PARAMS ((const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *)); + +/* Extend or truncate to a new mode. */ +extern void real_convert PARAMS ((REAL_VALUE_TYPE *, + enum machine_mode, + const REAL_VALUE_TYPE *)); + +/* Return true if truncating to NEW is exact. */ +extern bool exact_real_truncate PARAMS ((enum machine_mode, + const REAL_VALUE_TYPE *)); + +/* Render R as a decimal floating point constant. */ +extern void real_to_decimal PARAMS ((char *, const REAL_VALUE_TYPE *, + int)); + +/* Render R as a hexadecimal floating point constant. */ +extern void real_to_hexadecimal PARAMS ((char *, const REAL_VALUE_TYPE *, + int)); + +/* Render R as an integer. */ +extern HOST_WIDE_INT real_to_integer PARAMS ((const REAL_VALUE_TYPE *)); +extern void real_to_integer2 PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *, + const REAL_VALUE_TYPE *)); + +/* Initialize R from a decimal or hexadecimal string. */ +extern void real_from_string PARAMS ((REAL_VALUE_TYPE *, const char *)); + +/* Initialize R from an integer pair HIGH/LOW. */ +extern void real_from_integer PARAMS ((REAL_VALUE_TYPE *, + enum machine_mode, + unsigned HOST_WIDE_INT, + HOST_WIDE_INT, int)); + +extern long real_to_target PARAMS ((long *, const REAL_VALUE_TYPE *, + enum machine_mode)); + +extern void real_from_target PARAMS ((REAL_VALUE_TYPE *, const long *, + enum machine_mode)); + +extern void real_inf PARAMS ((REAL_VALUE_TYPE *)); + +extern void real_nan PARAMS ((REAL_VALUE_TYPE *, const char *, + int, enum machine_mode)); + +extern void real_2expN PARAMS ((REAL_VALUE_TYPE *, int)); + +/* ====================================================================== */ +/* Crap. */ /* Define codes for all the float formats that we know of. */ #define UNKNOWN_FLOAT_FORMAT 0 #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. */ @@ -31,116 +164,89 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT #endif -#ifndef HOST_FLOAT_FORMAT -#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT -#endif +#define REAL_ARITHMETIC(value, code, d1, d2) \ + real_arithmetic (&(value), code, &(d1), &(d2)) -#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT -#define REAL_INFINITY -#endif +#define REAL_VALUES_IDENTICAL(x, y) real_identical (&(x), &(y)) +#define REAL_VALUES_EQUAL(x, y) real_compare (EQ_EXPR, &(x), &(y)) +#define REAL_VALUES_LESS(x, y) real_compare (LT_EXPR, &(x), &(y)) -#ifdef REAL_ARITHMETIC -/* Defining REAL_IS_NOT_DOUBLE breaks certain initializations - when REAL_ARITHMETIC etc. are not defined. */ - -/* Now see if the host and target machines use the same format. - If not, define REAL_IS_NOT_DOUBLE (even if we end up representing - reals as doubles because we have no better way in this cross compiler.) - This turns off various optimizations that can happen when we know the - compiler's float format matches the target's float format. - */ -#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT -#define REAL_IS_NOT_DOUBLE -#ifndef REAL_VALUE_TYPE -#define REAL_VALUE_TYPE \ - struct real_value { long i[sizeof (double) / sizeof (long)]; } -#endif /* no REAL_VALUE_TYPE */ -#endif /* formats differ */ -#endif /* 0 */ - -/* 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). */ -#ifndef REAL_VALUE_TYPE -#define REAL_VALUE_TYPE double -#else -#define REAL_IS_NOT_DOUBLE -#endif +/* Determine whether a floating-point value X is infinite. */ +#define REAL_VALUE_ISINF(x) real_isinf (&(x)) -/* Compare two floating-point values for equality. */ -#ifndef REAL_VALUES_EQUAL -#define REAL_VALUES_EQUAL(x,y) ((x) == (y)) -#endif +/* Determine whether a floating-point value X is a NaN. */ +#define REAL_VALUE_ISNAN(x) real_isnan (&(x)) -/* Compare two floating-point values for less than. */ -#ifndef REAL_VALUES_LESS -#define REAL_VALUES_LESS(x,y) ((x) < (y)) -#endif +/* Determine whether a floating-point value X is negative. */ +#define REAL_VALUE_NEGATIVE(x) real_isneg (&(x)) -/* Convert a floating-point value to integer by truncating. */ -#ifndef REAL_VALUE_FIX_TRUNCATE -#define REAL_VALUE_FIX_TRUNCATE(x) ((int) (x)) -#endif +/* Determine whether a floating-point value X is minus zero. */ +#define REAL_VALUE_MINUS_ZERO(x) real_isnegzero (&(x)) -/* 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)) -#endif +/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */ +#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \ + real_to_target (OUT, &(IN), \ + mode_for_size (LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT, 0)) -/* Convert a floating-point value to integer, using any rounding mode. */ -#ifndef REAL_VALUE_FIX -#define REAL_VALUE_FIX(x) ((int) (x)) -#endif +#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \ + real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0)) -/* Convert a floating-point value to unsigned integer, using any rounding - mode. */ -#ifndef REAL_VALUE_UNSIGNED_FIX -#define REAL_VALUE_UNSIGNED_FIX(x) ((unsigned int) (x)) -#endif +/* IN is a REAL_VALUE_TYPE. OUT is a long. */ +#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \ + ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0))) -/* Scale X by Y powers of 2. */ -#ifndef REAL_VALUE_LDEXP -#define REAL_VALUE_LDEXP(x,y) ldexp (x, y) -extern double ldexp (); -#endif +#define REAL_VALUE_TO_DECIMAL(r, s, dig) \ + real_to_decimal (s, &(r), dig) -/* Convert the string X to a floating-point value. */ -#ifndef REAL_VALUE_ATOF -#define REAL_VALUE_ATOF(x) 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 - macro definition for atof. It does not seem there is one. */ -extern double atof (); -#else -extern double (atof) (); -#endif -#endif +#define REAL_VALUE_FROM_INT(r, lo, hi, mode) \ + real_from_integer (&(r), mode, lo, hi, 0) -/* Negate the floating-point value X. */ -#ifndef REAL_VALUE_NEGATE -#define REAL_VALUE_NEGATE(x) (- (x)) -#endif +#define REAL_VALUE_FROM_UNSIGNED_INT(r, lo, hi, mode) \ + real_from_integer (&(r), mode, lo, hi, 1) -/* Truncate the floating-point value X to mode MODE. This is correct only - for the most common case where the host and target have objects of the same - size and where `float' is SFmode. */ +extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode, + REAL_VALUE_TYPE)); -#ifndef REAL_VALUE_TRUNCATE -#define REAL_VALUE_TRUNCATE(mode, x) \ - (GET_MODE_BITSIZE (mode) == sizeof (float) * HOST_BITS_PER_CHAR \ - ? (float) (x) : (x)) -#endif +#define REAL_VALUE_TO_INT(plow, phigh, r) \ + real_to_integer2 (plow, phigh, &(r)) -/* Determine whether a floating-point value X is infinite. */ -#ifndef REAL_VALUE_ISINF -#define REAL_VALUE_ISINF(x) (target_isinf (x)) -#endif +extern REAL_VALUE_TYPE real_arithmetic2 PARAMS ((int, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *)); -/* Determine whether a floating-point value X is minus 0. */ -#ifndef REAL_VALUE_MINUS_ZERO -#define REAL_VALUE_MINUS_ZERO(x) (target_minus_zero (x)) -#endif +#define REAL_VALUE_NEGATE(X) \ + real_arithmetic2 (NEGATE_EXPR, &(X), NULL) + +#define REAL_VALUE_ABS(X) \ + real_arithmetic2 (ABS_EXPR, &(X), NULL) + +extern int significand_size PARAMS ((enum machine_mode)); + +extern REAL_VALUE_TYPE real_from_string2 PARAMS ((const char *, + enum machine_mode)); + +#define REAL_VALUE_ATOF(s, m) \ + real_from_string2 (s, m) + +#define CONST_DOUBLE_ATOF(s, m) \ + CONST_DOUBLE_FROM_REAL_VALUE (real_from_string2 (s, m), m) + +#define REAL_VALUE_FIX(r) \ + real_to_integer (&(r)) + +/* ??? Not quite right. */ +#define REAL_VALUE_UNSIGNED_FIX(r) \ + real_to_integer (&(r)) + +/* ??? These were added for Paranoia support. */ + +/* Return floor log2(R). */ +extern int real_exponent PARAMS ((const REAL_VALUE_TYPE *)); + +/* R = A * 2**EXP. */ +extern void real_ldexp PARAMS ((REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *, int)); + +/* **** End of software floating point emulator interface macros **** */ /* Constant real values 0, 1, 2, and -1. */ @@ -149,45 +255,26 @@ extern REAL_VALUE_TYPE dconst1; extern REAL_VALUE_TYPE dconst2; extern REAL_VALUE_TYPE dconstm1; -/* Union type used for extracting real values from CONST_DOUBLEs - or putting them in. */ - -union real_extract -{ - REAL_VALUE_TYPE d; - int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)]; -}; - -/* For a CONST_DOUBLE: - The usual two ints that hold the value. - For a DImode, that is all there are; - and CONST_DOUBLE_LOW is the low-order word and ..._HIGH the high-order. - For a float, the number of ints varies, - and CONST_DOUBLE_LOW is the one that should come first *in memory*. - So use &CONST_DOUBLE_LOW(r) as the address of an array of ints. */ -#define CONST_DOUBLE_LOW(r) XINT (r, 2) -#define CONST_DOUBLE_HIGH(r) XINT (r, 3) - -/* Link for chain of all CONST_DOUBLEs in use in current function. */ -#define CONST_DOUBLE_CHAIN(r) XEXP (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) - /* Function to return a real value (not a tree node) from a given integer constant. */ -REAL_VALUE_TYPE real_value_from_int_cst (); +REAL_VALUE_TYPE real_value_from_int_cst PARAMS ((union tree_node *, + union tree_node *)); /* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */ - -#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \ -do { union real_extract u; \ - bcopy (&CONST_DOUBLE_LOW ((from)), &u, sizeof u); \ - to = u.d; } while (0) +#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \ + memcpy (&(to), &CONST_DOUBLE_LOW ((from)), sizeof (REAL_VALUE_TYPE)) /* Return a CONST_DOUBLE with value R and mode M. */ +#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)); + +/* Replace R by 1/R in the given machine mode, if the result is exact. */ +extern bool exact_real_inverse PARAMS ((enum machine_mode, REAL_VALUE_TYPE *)); + +/* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node. */ +extern tree build_real PARAMS ((tree, REAL_VALUE_TYPE)); -#define CONST_DOUBLE_FROM_REAL_VALUE(r,m) immed_real_const_1 (r, m) -#endif /* Not REAL_H_INCLUDED */ +#endif /* ! GCC_REAL_H */