real.c, real.h: Rewrite from scratch.

gcc/
	* real.c, real.h: Rewrite from scratch.

	* Makefile.in (simplify-rtx.o): Depend on TREE_H.
	(paranoia): New target.
	* builtins.c (fold_builtin_inf): Use new real.h interface.
	* c-common.c (builtin_define_with_hex_fp_value): Likewise.
	* c-lex.c (interpret_float): Likewise.
	* emit-rtl.c (gen_lowpart_common): Likewise.
	* optabs.c (expand_float): Use real_2expN.
	* config/ia64/ia64.md (divsi3, udivsi3): Likewise.
	* defaults.h (INTEL_EXTENDED_IEEE_FORMAT): New.
	(FLOAT_WORDS_BIG_ENDIAN): New.
	* cse.c (find_comparison_args): Don't pass FLOAT_STORE_FLAG_VALUE
	directly to REAL_VALUE_NEGATIVE.
	* loop.c (canonicalize_condition): Likewise.
	* simplify-rtx.c: Include tree.h.
	(simplify_unary_operation): Don't handle FIX and UNSIGNED_FIX
	with floating-point result modes.
	* toplev.c (backend_init): Call init_real_once.

	* fold-const.c (force_fit_type): Don't call CHECK_FLOAT_VALUE.
	* tree.c (build_real): Likewise.
	* config/alpha/alpha.c, config/vax/vax.c (float_strings,
	float_values, inited_float_values, check_float_value): Remove.
	* config/alpha/alpha.h, config/m68hc11/m68hc11.h,
	config/m88k/m88k.h, config/vax/vax.h (CHECK_FLOAT_VALUE): Remove.
	* doc/tm.texi (CHECK_FLOAT_VALUE): Remove.

gcc/f/
	* target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_
	directly to ffetarget_make_real1.
	(ffetarget_real2): Similarly.
	* target.h (ffetarget_cvt_r1_to_rv_, ffetarget_cvt_rv_to_r2_,
	ffetarget_cvt_r2_to_rv_): Use new real.h interface and simplify.

gcc/java/
	* jcf-parse.c (get_constant): Runtime check for IEEE format;
	use new real.h interface.
	* jcf-write.c (find_constant_index): Use new real.h interface.
	* lex.c (IS_ZERO): Use REAL_VALUES_EQUAL.

contrib/
	* paranoia.cc: New file.

From-SVN: r57198
This commit is contained in:
Richard Henderson 2002-09-16 09:36:39 -07:00 committed by Richard Henderson
parent 1f73c62225
commit efdc7e19ca
33 changed files with 6887 additions and 7241 deletions

View File

@ -1,3 +1,7 @@
2002-09-16 Richard Henderson <rth@redhat.com>
* paranoia.cc: New file.
2002-09-04 Richard Henderson <rth@redhat.com>
* enquire.c: Remove.

2698
contrib/paranoia.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,34 @@
2002-09-16 Richard Henderson <rth@redhat.com>
* real.c, real.h: Rewrite from scratch.
* Makefile.in (simplify-rtx.o): Depend on TREE_H.
(paranoia): New target.
* builtins.c (fold_builtin_inf): Use new real.h interface.
* c-common.c (builtin_define_with_hex_fp_value): Likewise.
* c-lex.c (interpret_float): Likewise.
* emit-rtl.c (gen_lowpart_common): Likewise.
* optabs.c (expand_float): Use real_2expN.
* config/ia64/ia64.md (divsi3, udivsi3): Likewise.
* defaults.h (INTEL_EXTENDED_IEEE_FORMAT): New.
(FLOAT_WORDS_BIG_ENDIAN): New.
* cse.c (find_comparison_args): Don't pass FLOAT_STORE_FLAG_VALUE
directly to REAL_VALUE_NEGATIVE.
* loop.c (canonicalize_condition): Likewise.
* simplify-rtx.c: Include tree.h.
(simplify_unary_operation): Don't handle FIX and UNSIGNED_FIX
with floating-point result modes.
* toplev.c (backend_init): Call init_real_once.
* fold-const.c (force_fit_type): Don't call CHECK_FLOAT_VALUE.
* tree.c (build_real): Likewise.
* config/alpha/alpha.c, config/vax/vax.c (float_strings,
float_values, inited_float_values, check_float_value): Remove.
* config/alpha/alpha.h, config/m68hc11/m68hc11.h,
config/m88k/m88k.h, config/vax/vax.h (CHECK_FLOAT_VALUE): Remove.
* doc/tm.texi (CHECK_FLOAT_VALUE): Remove.
(VAX_HALFWORD_ORDER): Remove.
2002-09-16 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390.c: (legitimize_la_operand): Remove, replace by ...

View File

@ -1473,7 +1473,7 @@ jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H)
output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H)
cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h
@ -3260,6 +3260,15 @@ ${QMTEST_DIR}/gpp-expected.qmr: ${QMTEST_DIR}/context
.PHONY: qmtest-g++
# Run Paranoia on real.c.
paranoia.o: $(srcdir)/../contrib/paranoia.cc $(CONFIG_H) $(SYSTEM_H) \
real.h $(TREE_H)
g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
paranoia: paranoia.o real.o $(LIBIBERTY)
g++ -o $@ paranoia.o real.o $(LIBIBERTY)
# These exist for maintenance purposes.
# Update the tags table.

View File

@ -4140,10 +4140,13 @@ fold_builtin_inf (type, warn)
tree type;
int warn;
{
REAL_VALUE_TYPE real;
if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
warning ("target format does not support infinity");
return build_real (type, ereal_inf (TYPE_MODE (type)));
real_inf (&real);
return build_real (type, real);
}
/* Used by constant folding to eliminate some builtin calls early. EXP is

View File

@ -5266,7 +5266,7 @@ builtin_define_with_int_value (macro, value)
static void
builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
const char *macro;
tree type;
tree type ATTRIBUTE_UNUSED;
int digits;
const char *hex_str;
const char *fp_suffix;
@ -5284,8 +5284,8 @@ builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
it's easy to get the exact correct value), parse it as a real,
then print it back out as decimal. */
real = REAL_VALUE_HTOF (hex_str, TYPE_MODE (type));
REAL_VALUE_TO_DECIMAL (real, dec_str, digits);
real_from_string (&real, hex_str);
real_to_decimal (dec_str, &real, digits);
sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
cpp_define (parse_in, buf);

View File

@ -925,13 +925,8 @@ interpret_float (token, flags)
memcpy (copy, token->val.str.text, copylen);
copy[copylen] = '\0';
/* The second argument, machine_mode, of REAL_VALUE_ATOF tells the
desired precision of the binary result of decimal-to-binary
conversion. */
if (flags & CPP_N_HEX)
real = REAL_VALUE_HTOF (copy, TYPE_MODE (type));
else
real = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
real_from_string (&real, copy);
real_convert (&real, TYPE_MODE (type), &real);
/* A diagnostic is required for "soft" overflow by some ISO C
testsuites. This is not pedwarn, because some people don't want

View File

@ -8880,83 +8880,6 @@ alpha_reorg (insns)
}
}
/* Check a floating-point value for validity for a particular machine mode. */
static const char * const float_strings[] =
{
/* These are for FLOAT_VAX. */
"1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
"-1.70141173319264430e+38",
"2.93873587705571877e-39", /* 2^-128 */
"-2.93873587705571877e-39",
/* These are for the default broken IEEE mode, which traps
on infinity or denormal numbers. */
"3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */
"-3.402823466385288598117e+38",
"1.1754943508222875079687e-38", /* 2^-126 */
"-1.1754943508222875079687e-38",
};
static REAL_VALUE_TYPE float_values[8];
static int inited_float_values = 0;
int
check_float_value (mode, d, overflow)
enum machine_mode mode;
REAL_VALUE_TYPE *d;
int overflow ATTRIBUTE_UNUSED;
{
if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT)
return 0;
if (inited_float_values == 0)
{
int i;
for (i = 0; i < 8; i++)
float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
inited_float_values = 1;
}
if (mode == SFmode)
{
REAL_VALUE_TYPE r;
REAL_VALUE_TYPE *fvptr;
if (TARGET_FLOAT_VAX)
fvptr = &float_values[0];
else
fvptr = &float_values[4];
memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
if (REAL_VALUES_LESS (fvptr[0], r))
{
memcpy (d, &fvptr[0], sizeof (REAL_VALUE_TYPE));
return 1;
}
else if (REAL_VALUES_LESS (r, fvptr[1]))
{
memcpy (d, &fvptr[1], sizeof (REAL_VALUE_TYPE));
return 1;
}
else if (REAL_VALUES_LESS (dconst0, r)
&& REAL_VALUES_LESS (r, fvptr[2]))
{
memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
return 1;
}
else if (REAL_VALUES_LESS (r, dconst0)
&& REAL_VALUES_LESS (fvptr[3], r))
{
memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
return 1;
}
}
return 0;
}
#ifdef OBJECT_FORMAT_ELF
/* Switch to the section to which we should output X. The only thing

View File

@ -1779,11 +1779,6 @@ do { \
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*$%s%ld", (PREFIX), (long)(NUM))
/* Check a floating-point value for validity for a particular machine mode. */
#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
/* We use the default ASCII-output routine, except that we don't write more
than 50 characters since the assembler doesn't support very long lines. */

View File

@ -1990,6 +1990,7 @@
"INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@ -2005,14 +2006,9 @@
expand_float (op2_tf, operands[2], 0);
/* 2^-34 */
#if 0
twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
(REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
real_2expN (&twon34_r, -34);
twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
#else
twon34 = gen_reg_rtx (TFmode);
convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
@ -2051,6 +2047,7 @@
"INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@ -2066,14 +2063,9 @@
expand_float (op2_tf, operands[2], 1);
/* 2^-34 */
#if 0
twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
(REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
real_2expN (&twon34_r, -34);
twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
#else
twon34 = gen_reg_rtx (TFmode);
convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));

View File

@ -303,11 +303,6 @@ extern const struct processor_costs *m68hc11_cost;
this size or smaller can be used for structures and unions with the
appropriate sizes. */
#define MAX_FIXED_MODE_SIZE 64
/* Floats are checked in a generic way. */
/* #define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) */
/* target machine storage layout */

View File

@ -389,14 +389,6 @@ extern int flag_pic; /* -fpic */
/* Maximum size (in bits) to use for the largest integral type that
replaces a BLKmode type. */
/* #define MAX_FIXED_MODE_SIZE 0 */
/* Check a `double' value for validity for a particular machine mode.
This is defined to avoid crashes outputting certain constants.
Since we output the number in hex, the assembler won't choke on it. */
/* #define CHECK_FLOAT_VALUE(MODE,VALUE) */
/* A code distinguishing the floating point format of the target machine. */
/* #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT */
/*** Register Usage ***/

View File

@ -696,75 +696,6 @@ vax_rtx_cost (x)
}
return c;
}
/* Check a `double' value for validity for a particular machine mode. */
static const char *const float_strings[] =
{
"1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
"-1.70141173319264430e+38",
"2.93873587705571877e-39", /* 2^-128 */
"-2.93873587705571877e-39"
};
static REAL_VALUE_TYPE float_values[4];
static int inited_float_values = 0;
int
check_float_value (mode, d, overflow)
enum machine_mode mode;
REAL_VALUE_TYPE *d;
int overflow;
{
if (inited_float_values == 0)
{
int i;
for (i = 0; i < 4; i++)
{
float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
}
inited_float_values = 1;
}
if (overflow)
{
memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
return 1;
}
if ((mode) == SFmode)
{
REAL_VALUE_TYPE r;
memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
if (REAL_VALUES_LESS (float_values[0], r))
{
memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
return 1;
}
else if (REAL_VALUES_LESS (r, float_values[1]))
{
memcpy (d, &float_values[1], sizeof (REAL_VALUE_TYPE));
return 1;
}
else if (REAL_VALUES_LESS (dconst0, r)
&& REAL_VALUES_LESS (r, float_values[2]))
{
memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
return 1;
}
else if (REAL_VALUES_LESS (r, dconst0)
&& REAL_VALUES_LESS (float_values[3], r))
{
memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
return 1;
}
}
return 0;
}
#if VMS_TARGET
/* Additional support code for VMS target. */

View File

@ -885,32 +885,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define UDIVSI3_LIBCALL "*udiv"
#define UMODSI3_LIBCALL "*urem"
/* Check a `double' value for validity for a particular machine mode. */
/* note that it is very hard to accidentally create a number that fits in a
double but not in a float, since their ranges are almost the same */
#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
/* For future reference:
D Float: 9 bit, sign magnitude, excess 128 binary exponent
normalized 56 bit fraction, redundant bit not represented
approximately 16 decimal digits of precision
The values to use if we trust decimal to binary conversions:
#define MAX_D_FLOAT 1.7014118346046923e+38
#define MIN_D_FLOAT .29387358770557188e-38
G float: 12 bit, sign magnitude, excess 1024 binary exponent
normalized 53 bit fraction, redundant bit not represented
approximately 15 decimal digits precision
The values to use if we trust decimal to binary conversions:
#define MAX_G_FLOAT .898846567431157e+308
#define MIN_G_FLOAT .556268464626800e-308
*/
/* Tell final.c how to eliminate redundant test instructions. */

View File

@ -3147,13 +3147,17 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<')
{
#ifdef FLOAT_STORE_FLAG_VALUE
REAL_VALUE_TYPE fsfv;
#endif
if (code == NE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
&& code == LT && STORE_FLAG_VALUE == -1)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
&& (REAL_VALUE_NEGATIVE
(FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
&& (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
x = arg1;
@ -3162,8 +3166,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
&& code == GE && STORE_FLAG_VALUE == -1)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
&& (REAL_VALUE_NEGATIVE
(FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
&& (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
x = arg1, reverse_code = 1;
@ -3199,6 +3203,9 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
for (; p; p = p->next_same_value)
{
enum machine_mode inner_mode = GET_MODE (p->exp);
#ifdef FLOAT_STORE_FLAG_VALUE
REAL_VALUE_TYPE fsfv;
#endif
/* If the entry isn't valid, skip it. */
if (! exp_equiv_p (p->exp, p->exp, 1, 0))
@ -3223,8 +3230,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == LT
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
&& (REAL_VALUE_NEGATIVE
(FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
&& (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
&& GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
@ -3243,8 +3250,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == GE
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
&& (REAL_VALUE_NEGATIVE
(FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
&& (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
&& GET_RTX_CLASS (GET_CODE (p->exp)) == '<')

View File

@ -564,6 +564,17 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
&& !ROUND_TOWARDS_ZERO)
#endif
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
#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. */
#ifndef FLOAT_WORDS_BIG_ENDIAN
#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
#endif
#ifndef TARGET_FLT_EVAL_METHOD
#define TARGET_FLT_EVAL_METHOD 0
#endif

View File

@ -1291,22 +1291,6 @@ You need not define this macro if it always returns @code{word_mode}.
You would most commonly define this macro if the @code{allocate_stack}
pattern needs to support both a 32- and a 64-bit mode.
@findex CHECK_FLOAT_VALUE
@item CHECK_FLOAT_VALUE (@var{mode}, @var{value}, @var{overflow})
A C statement to validate the value @var{value} (of type
@code{double}) for mode @var{mode}. This means that you check whether
@var{value} fits within the possible range of values for mode
@var{mode} on this target machine. The mode @var{mode} is always
a mode of class @code{MODE_FLOAT}. @var{overflow} is nonzero if
the value is already known to be out of range.
If @var{value} is not valid or if @var{overflow} is nonzero, you should
set @var{overflow} to 1 and then assign some valid value to @var{value}.
Allowing an invalid value to go through the compiler can produce
incorrect assembler code which may even cause Unix assemblers to crash.
This macro need not be defined if there is no work for it to do.
@findex TARGET_FLOAT_FORMAT
@item TARGET_FLOAT_FORMAT
A code distinguishing the floating point format of the target machine.
@ -1343,13 +1327,6 @@ defined for them.
The ordering of the component words of floating point values stored in
memory is controlled by @code{FLOAT_WORDS_BIG_ENDIAN}.
@findex VAX_HALFWORD_ORDER
@item VAX_HALFWORD_ORDER
This macro is only used if @code{TARGET_FLOAT_FORMAT} is
@code{VAX_FLOAT_FORMAT}. If defaulted or defined as 1, the halfwords of
the generated floating point data are in the order used by the VAX. If
defined as 0, they are reversed, which is used by the PDP-11 target.
@findex MODE_HAS_NANS
@item MODE_HAS_NANS (@var{mode})
When defined, this macro should be true if @var{mode} has a NaN

View File

@ -1042,10 +1042,9 @@ gen_lowpart_common (mode, x)
&& GET_CODE (x) == CONST_INT)
{
REAL_VALUE_TYPE r;
HOST_WIDE_INT i;
long i = INTVAL (x);
i = INTVAL (x);
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
real_from_target (&r, &i, mode);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
else if (GET_MODE_CLASS (mode) == MODE_FLOAT
@ -1054,8 +1053,8 @@ gen_lowpart_common (mode, x)
&& GET_MODE (x) == VOIDmode)
{
REAL_VALUE_TYPE r;
HOST_WIDE_INT i[2];
HOST_WIDE_INT low, high;
long i[2];
if (GET_CODE (x) == CONST_INT)
{
@ -1068,18 +1067,17 @@ gen_lowpart_common (mode, x)
high = CONST_DOUBLE_HIGH (x);
}
#if HOST_BITS_PER_WIDE_INT == 32
if (HOST_BITS_PER_WIDE_INT > 32)
high = low >> 31 >> 1;
/* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
target machine. */
if (WORDS_BIG_ENDIAN)
i[0] = high, i[1] = low;
else
i[0] = low, i[1] = high;
#else
i[0] = low;
#endif
r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
real_from_target (&r, i, mode);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
else if ((GET_MODE_CLASS (mode) == MODE_INT

View File

@ -1,3 +1,11 @@
2002-09-16 Richard Henderson <rth@redhat.com>
* target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_
directly to ffetarget_make_real1.
(ffetarget_real2): Similarly.
* target.h (ffetarget_cvt_r1_to_rv_, ffetarget_cvt_rv_to_r2_,
ffetarget_cvt_r2_to_rv_): Use new real.h interface and simplify.
2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
* intdoc.texi: Regenerate.

View File

@ -2277,9 +2277,11 @@ ffetarget_real1 (ffetargetReal1 *value, ffelexToken integer,
*p = '\0';
ffetarget_make_real1 (value,
FFETARGET_ATOF_ (ptr,
SFmode));
{
REAL_VALUE_TYPE rv;
rv = FFETARGET_ATOF_ (ptr, SFmode);
ffetarget_make_real1 (value, rv);
}
if (sz > ARRAY_SIZE (ffetarget_string_))
malloc_kill_ks (malloc_pool_image (), ptr, sz);
@ -2363,9 +2365,11 @@ ffetarget_real2 (ffetargetReal2 *value, ffelexToken integer,
*p = '\0';
ffetarget_make_real2 (value,
FFETARGET_ATOF_ (ptr,
DFmode));
{
REAL_VALUE_TYPE rv;
rv = FFETARGET_ATOF_ (ptr, DFmode);
ffetarget_make_real2 (value, rv);
}
if (sz > ARRAY_SIZE (ffetarget_string_))
malloc_kill_ks (malloc_pool_image (), ptr, sz);

View File

@ -331,54 +331,30 @@ typedef ? ffetargetLogical8;
?
#endif
#if FFETARGET_okREAL1
#ifdef FFETARGET_32bit_longs
typedef long int ffetargetReal1;
#define ffetargetReal1_f "l"
#define ffetarget_cvt_r1_to_rv_ REAL_VALUE_UNTO_TARGET_SINGLE
#define ffetarget_cvt_rv_to_r1_ REAL_VALUE_TO_TARGET_SINGLE
#else
typedef int ffetargetReal1;
#define ffetargetReal1_f ""
#define ffetarget_cvt_r1_to_rv_(in) \
({ REAL_VALUE_TYPE _rv; \
_rv = REAL_VALUE_UNTO_TARGET_SINGLE ((long) (in)); \
#define ffetarget_cvt_r1_to_rv_(in) \
({ REAL_VALUE_TYPE _rv; \
long _in = (in); \
real_from_target (&_rv, &_in, mode_for_size (32, MODE_FLOAT, 0)); \
_rv; })
#define ffetarget_cvt_rv_to_r1_(in, out) \
({ long _tmp; \
REAL_VALUE_TO_TARGET_SINGLE ((in), _tmp); \
(out) = (ffetargetReal1) _tmp; })
#endif
#endif
#if FFETARGET_okREAL2
#ifdef FFETARGET_32bit_longs
typedef struct
{
long int v[2];
}
ffetargetReal2;
#define ffetargetReal2_f "l"
#define ffetarget_cvt_r2_to_rv_ REAL_VALUE_UNTO_TARGET_DOUBLE
#define ffetarget_cvt_rv_to_r2_ REAL_VALUE_TO_TARGET_DOUBLE
#else
typedef struct
{
int v[2];
}
ffetargetReal2;
typedef struct { int v[2]; } ffetargetReal2;
#define ffetargetReal2_f ""
#define ffetarget_cvt_r2_to_rv_(in) \
({ REAL_VALUE_TYPE _rv; \
long _tmp[2]; \
_tmp[0] = (in)[0]; \
_tmp[1] = (in)[1]; \
_rv = REAL_VALUE_UNTO_TARGET_DOUBLE (_tmp); \
#define ffetarget_cvt_r2_to_rv_(in) \
({ REAL_VALUE_TYPE _rv; long _tmp[2]; \
_tmp[0] = (in)[0]; _tmp[1] = (in)[1]; \
real_from_target (&_rv, _tmp, mode_for_size (64, MODE_FLOAT, 0)); \
_rv; })
#define ffetarget_cvt_rv_to_r2_(in, out) \
({ long _tmp[2]; \
REAL_VALUE_TO_TARGET_DOUBLE ((in), _tmp); \
(out)[0] = (int) (_tmp[0]); \
(out)[1] = (int) (_tmp[1]); })
#endif
#define ffetarget_cvt_rv_to_r2_(in, out) \
({ long _tmp[2]; \
REAL_VALUE_TO_TARGET_DOUBLE ((in), _tmp); \
(out)[0] = (int)_tmp[0]; (out)[1] = (int)_tmp[1]; })
#endif
#if FFETARGET_okREAL3
typedef long ffetargetReal3[?];

View File

@ -178,10 +178,7 @@ decode (words, low, hi)
Return 1 if a signed overflow occurs, 0 otherwise. If OVERFLOW is
nonzero, a signed overflow has already occurred in calculating T, so
propagate it.
Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE,
if it exists. */
propagate it. */
int
force_fit_type (t, overflow)
@ -194,10 +191,8 @@ force_fit_type (t, overflow)
if (TREE_CODE (t) == REAL_CST)
{
#ifdef CHECK_FLOAT_VALUE
CHECK_FLOAT_VALUE (TYPE_MODE (TREE_TYPE (t)), TREE_REAL_CST (t),
overflow);
#endif
/* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
Consider doing it via real_convert now. */
return overflow;
}

View File

@ -1,3 +1,10 @@
2002-09-16 Richard Henderson <rth@redhat.com>
* jcf-parse.c (get_constant): Runtime check for IEEE format;
use new real.h interface.
* jcf-write.c (find_constant_index): Use new real.h interface.
* lex.c (IS_ZERO): Use REAL_VALUES_EQUAL.
2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
* lang.c: Follow spelling conventions.

View File

@ -290,47 +290,44 @@ get_constant (jcf, index)
force_fit_type (value, 0);
break;
}
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
case CONSTANT_Float:
{
jint num = JPOOL_INT(jcf, index);
REAL_VALUE_TYPE d;
d = REAL_VALUE_FROM_TARGET_SINGLE (num);
value = build_real (float_type_node, d);
break;
}
/* ??? Even more ideal would be to import the number using the
IEEE decode routines, then use whatever format the target
actually uses. This would enable Java on VAX to kind work. */
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
{
jint num = JPOOL_INT(jcf, index);
long buf = num;
REAL_VALUE_TYPE d;
real_from_target (&d, &buf, SFmode);
value = build_real (float_type_node, d);
break;
}
else
goto bad;
case CONSTANT_Double:
{
HOST_WIDE_INT num[2];
REAL_VALUE_TYPE d;
HOST_WIDE_INT lo, hi;
num[0] = JPOOL_UINT (jcf, index);
lshift_double (num[0], 0, 32, 64, &lo, &hi, 0);
num[0] = JPOOL_UINT (jcf, index+1);
add_double (lo, hi, num[0], 0, &lo, &hi);
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
{
long buf[2], lo, hi;
REAL_VALUE_TYPE d;
/* Since ereal_from_double expects an array of HOST_WIDE_INT
in the target's format, we swap the elements for big endian
targets, unless HOST_WIDE_INT is sufficiently large to
contain a target double, in which case the 2nd element
is ignored.
hi = JPOOL_UINT (jcf, index);
lo = JPOOL_UINT (jcf, index+1);
if (FLOAT_WORDS_BIG_ENDIAN)
buf[0] = hi, buf[1] = lo;
else
buf[0] = lo, buf[1] = hi;
real_from_target (&d, buf, DFmode);
value = build_real (double_type_node, d);
break;
}
else
goto bad;
FIXME: Is this always right for cross targets? */
if (FLOAT_WORDS_BIG_ENDIAN && sizeof(num[0]) < 8)
{
num[0] = hi;
num[1] = lo;
}
else
{
num[0] = lo;
num[1] = hi;
}
d = REAL_VALUE_FROM_TARGET_DOUBLE (num);
value = build_real (double_type_node, d);
break;
}
#endif /* TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT */
case CONSTANT_String:
{
tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));

View File

@ -826,21 +826,18 @@ find_constant_index (value, state)
else if (TREE_CODE (value) == REAL_CST)
{
long words[2];
real_to_target (words, &TREE_REAL_CST (value),
TYPE_MODE (TREE_TYPE (value)));
words[0] &= 0xffffffff;
words[1] &= 0xffffffff;
if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
{
words[0] = etarsingle (TREE_REAL_CST (value)) & 0xFFFFFFFF;
return find_constant1 (&state->cpool, CONSTANT_Float,
(jword)words[0]);
}
return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
else
{
etardouble (TREE_REAL_CST (value), words);
return find_constant2 (&state->cpool, CONSTANT_Double,
(jword)(words[1-FLOAT_WORDS_BIG_ENDIAN] &
0xFFFFFFFF),
(jword)(words[FLOAT_WORDS_BIG_ENDIAN] &
0xFFFFFFFF));
}
return find_constant2 (&state->cpool, CONSTANT_Double,
(jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
(jword)words[FLOAT_WORDS_BIG_ENDIAN]);
}
else if (TREE_CODE (value) == STRING_CST)
return find_string_constant (&state->cpool, value);

View File

@ -834,7 +834,7 @@ java_parse_escape_sequence ()
}
#ifndef JC1_LITE
#define IS_ZERO(X) (ereal_cmp (X, dconst0) == 0)
#define IS_ZERO(X) REAL_VALUES_EQUAL (X, dconst0)
/* Subroutine of java_lex: converts floating-point literals to tree
nodes. LITERAL_TOKEN is the input literal, JAVA_LVAL is where to

View File

@ -9292,6 +9292,9 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
if (set)
{
enum machine_mode inner_mode = GET_MODE (SET_DEST (set));
#ifdef FLOAT_STORE_FLAG_VALUE
REAL_VALUE_TYPE fsfv;
#endif
/* ??? We may not combine comparisons done in a CCmode with
comparisons not done in a CCmode. This is to aid targets
@ -9319,8 +9322,8 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == LT
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
&& (REAL_VALUE_NEGATIVE
(FLOAT_STORE_FLAG_VALUE (inner_mode))))
&& (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
REAL_VALUE_NEGATIVE (fsfv)))
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))
@ -9339,8 +9342,8 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == GE
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
&& (REAL_VALUE_NEGATIVE
(FLOAT_STORE_FLAG_VALUE (inner_mode))))
&& (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
REAL_VALUE_NEGATIVE (fsfv)))
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'

View File

@ -4626,10 +4626,8 @@ expand_float (to, from, unsignedp)
emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
0, label);
/* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
Rather than setting up a dconst_dot_5, let's hope SCO
fixes the bug. */
offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
temp = expand_binop (fmode, add_optab, target,
CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
target, 0, OPTAB_LIB_WIDEN);
@ -4812,7 +4810,7 @@ expand_fix (to, from, unsignedp)
rtx limit, lab1, lab2, insn;
bitsize = GET_MODE_BITSIZE (GET_MODE (to));
offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
real_2expN (&offset, bitsize - 1);
limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
lab1 = gen_label_rtx ();
lab2 = gen_label_rtx ();

10490
gcc/real.c

File diff suppressed because it is too large Load Diff

View File

@ -2,96 +2,44 @@
Copyright (C) 1989, 1991, 1994, 1996, 1997, 1998,
1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GCC.
This file is part of GCC.
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.
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.
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.
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 GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, 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 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
#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. */
#ifndef TARGET_FLOAT_FORMAT
#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
#ifndef HOST_FLOAT_FORMAT
#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
#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
#ifndef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 64
#endif
/* 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
/* **** 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 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
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. */
@ -99,7 +47,7 @@ struct realvaluetype GTY(()) {
/* 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).
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. */
@ -126,134 +74,177 @@ struct realvaluetype GTY(()) {
# endif
#endif
extern unsigned int significand_size PARAMS ((enum machine_mode));
#define REAL_ARITHMETIC(value, code, d1, d2) \
earith (&(value), (code), &(d1), &(d2))
/* 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_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 *, int));
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 *));
/* Initialize the emulator. */
extern void init_real_once PARAMS ((void));
#define REAL_VALUES_EQUAL(x, y) (ereal_cmp ((x), (y)) == 0)
/* true if x < y : */
#define REAL_VALUES_LESS(x, y) (ereal_cmp ((x), (y)) == -1)
#define REAL_VALUE_LDEXP(x, n) ereal_ldexp (x, n)
/* 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 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) \
(!memcmp ((char *) &(x), (char *) &(y), sizeof (REAL_VALUE_TYPE)))
/* These return REAL_VALUE_TYPE: */
#define REAL_VALUE_RNDZINT(x) (etrunci (x))
#define REAL_VALUE_UNSIGNED_RNDZINT(x) (etruncui (x))
/* Truncate the floating-point value X to mode MODE. */
#define REAL_VALUE_TRUNCATE(mode, x) real_value_truncate (mode, x)
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))
/* 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_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))
/* 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. */
#define REAL_VALUE_ISINF(x) (target_isinf (x))
extern bool real_isinf PARAMS ((const REAL_VALUE_TYPE *));
/* Determine whether a floating-point value X is a NaN. */
#define REAL_VALUE_ISNAN(x) (target_isnan (x))
extern bool real_isnan PARAMS ((const REAL_VALUE_TYPE *));
/* Determine whether a floating-point value X is negative. */
#define REAL_VALUE_NEGATIVE(x) (target_negative (x))
extern bool real_isneg PARAMS ((const REAL_VALUE_TYPE *));
/* Determine whether a floating-point value X is minus zero. */
#define REAL_VALUE_MINUS_ZERO(x) \
((ereal_cmp (x, dconst0) == 0) && (ereal_isneg (x) != 0 ))
extern bool real_isnegzero PARAMS ((const REAL_VALUE_TYPE *));
#define REAL_VALUE_TO_INT ereal_to_int
/* Compare two floating-point objects for bitwise identity. */
extern bool real_identical PARAMS ((const REAL_VALUE_TYPE *,
const REAL_VALUE_TYPE *));
/* 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)
/* Extend or truncate to a new mode. */
extern void real_convert PARAMS ((REAL_VALUE_TYPE *,
enum machine_mode,
const REAL_VALUE_TYPE *));
#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
ereal_from_uint (&d, lo, hi, mode)
/* 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. */
#ifndef TARGET_FLOAT_FORMAT
#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
#define REAL_ARITHMETIC(value, code, d1, d2) \
real_arithmetic (&(value), code, &(d1), &(d2))
#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))
/* Determine whether a floating-point value X is infinite. */
#define REAL_VALUE_ISINF(x) real_isinf (&(x))
/* Determine whether a floating-point value X is a NaN. */
#define REAL_VALUE_ISNAN(x) real_isnan (&(x))
/* Determine whether a floating-point value X is negative. */
#define REAL_VALUE_NEGATIVE(x) real_isneg (&(x))
/* Determine whether a floating-point value X is minus zero. */
#define REAL_VALUE_MINUS_ZERO(x) real_isnegzero (&(x))
/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
(LONG_DOUBLE_TYPE_SIZE == 64 ? etardouble ((IN), (OUT)) \
: LONG_DOUBLE_TYPE_SIZE == 96 ? etarldouble ((IN), (OUT)) \
: LONG_DOUBLE_TYPE_SIZE == 128 ? etartdouble ((IN), (OUT)) \
: abort ())
#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) (etardouble ((IN), (OUT)))
#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
real_to_target (OUT, &(IN), \
mode_for_size (LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT, 0))
#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0))
/* IN is a REAL_VALUE_TYPE. OUT is a long. */
#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) ((OUT) = etarsingle ((IN)))
#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0)))
/* Inverse of REAL_VALUE_TO_TARGET_DOUBLE. */
#define REAL_VALUE_UNTO_TARGET_DOUBLE(d) (ereal_unto_double (d))
#define REAL_VALUE_TO_DECIMAL(r, s, dig) \
real_to_decimal (s, &(r), dig)
/* Inverse of REAL_VALUE_TO_TARGET_SINGLE. */
#define REAL_VALUE_UNTO_TARGET_SINGLE(f) (ereal_unto_float (f))
#define REAL_VALUE_FROM_INT(r, lo, hi, mode) \
real_from_integer (&(r), mode, lo, hi, 0)
/* 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))
#define REAL_VALUE_FROM_UNSIGNED_INT(r, lo, hi, mode) \
real_from_integer (&(r), mode, lo, hi, 1)
/* f is a HOST_WIDE_INT containing a single precision target float value. */
#define REAL_VALUE_FROM_TARGET_SINGLE(f) (ereal_from_float (f))
extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
REAL_VALUE_TYPE));
/* Conversions to decimal ASCII string. */
#define REAL_VALUE_TO_DECIMAL(r, s, dig) (ereal_to_decimal (r, s, dig))
#define REAL_VALUE_TO_INT(plow, phigh, r) \
real_to_integer2 (plow, phigh, &(r))
extern REAL_VALUE_TYPE real_arithmetic2 PARAMS ((int, const REAL_VALUE_TYPE *,
const REAL_VALUE_TYPE *));
#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 **** */
@ -264,35 +255,23 @@ extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconstm1;
/* 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. */
union tree_node;
REAL_VALUE_TYPE real_value_from_int_cst PARAMS ((union tree_node *,
union tree_node *));
union tree_node *));
#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \
/* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */
#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));
/* 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 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));
extern REAL_VALUE_TYPE ereal_atof PARAMS ((const char *, enum machine_mode));
extern REAL_VALUE_TYPE ereal_inf PARAMS ((enum machine_mode));
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));

View File

@ -22,8 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "tree.h"
#include "tm_p.h"
#include "regs.h"
#include "hard-reg-set.h"
@ -603,8 +603,6 @@ simplify_unary_operation (code, mode, op, op_mode)
case NEG: d = REAL_VALUE_NEGATE (d); break;
case FLOAT_TRUNCATE: d = real_value_truncate (mode, d); break;
case FLOAT_EXTEND: /* All this does is change the mode. */ break;
case FIX: d = REAL_VALUE_RNDZINT (d); break;
case UNSIGNED_FIX: d = REAL_VALUE_UNSIGNED_RNDZINT (d); break;
default:
abort ();
}

View File

@ -66,6 +66,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "reload.h"
#include "dwarf2asm.h"
#include "integrate.h"
#include "real.h"
#include "debug.h"
#include "target.h"
#include "langhooks.h"
@ -5155,6 +5156,9 @@ backend_init ()
/* init_emit_once uses reg_raw_mode and therefore must be called
after init_regs which initialized reg_raw_mode. */
init_regs ();
/* Similarly, init_emit_once uses floating point numbers, and
thus must follow init_real_once. */
init_real_once ();
init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
#ifdef VMS_DEBUGGING_INFO

View File

@ -474,11 +474,8 @@ build_real (type, d)
REAL_VALUE_TYPE *dp;
int overflow = 0;
/* Check for valid float value for this type on this target machine;
if not, can print error message and store a valid value in D. */
#ifdef CHECK_FLOAT_VALUE
CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
#endif
/* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
Consider doing it via real_convert now. */
v = make_node (REAL_CST);
dp = ggc_alloc (sizeof (REAL_VALUE_TYPE));