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:
parent
1f73c62225
commit
efdc7e19ca
33 changed files with 6887 additions and 7241 deletions
|
@ -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
2698
contrib/paranoia.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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 ...
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 ***/
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
23
gcc/cse.c
23
gcc/cse.c
|
@ -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)) == '<')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[?];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
11
gcc/loop.c
11
gcc/loop.c
|
@ -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))) == '<'
|
||||
|
|
|
@ -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 ();
|
||||
|
|
10488
gcc/real.c
10488
gcc/real.c
File diff suppressed because it is too large
Load diff
369
gcc/real.h
369
gcc/real.h
|
@ -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));
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Reference in a new issue