mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 02:50:27 +08:00
real.h (struct real_format): New member round_towards_zero.
ChangeLog: * real.h (struct real_format): New member round_towards_zero. * real.c (round_for_format): Respect fmt->round_towards_zero. (ieee_single_format, mips_single_format, motorola_single_format, spu_single_format, ieee_double_format, mips_double_format, motorola_double_format, ieee_extended_motorola_format, ieee_extended_intel_96_format, ieee_extended_intel_128_format, ieee_extended_intel_96_round_53_format, ibm_extended_format, mips_extended_format, ieee_quad_format, mips_quad_format, vax_f_format, vax_d_format, vax_g_format): Initialize it. * config/pdp11/pdp11.c (pdp11_f_format, pdp11_d_format): Likewise. * builtins.s (do_mpfr_arg1): Consider round_towards_zero member of real_format to choose rounding mode when calling MPFR functions. (do_mpfr_arg2, do_mpfr_arg3, do_mpfr_sincos): Likewise. (do_mpfr_bessel_n, do_mpfr_remquo, do_mpfr_lgamma_r): Likewise. * real.h (real_to_decimal_for_mode): Add prototype. * real.c (real_to_decimal_for_mode): Renames old real_to_decimal. Respect target rounding mode when generating decimal representation. (real_to_decimal): New stub for backwards compatibility. * c-cppbuiltin.c (builtin_define_with_hex_fp_value): Use real_to_decimal_for_mode instead of real_to_decimal. * config/spu/spu.md ("floatdisf2", "floatunsdisf2"): New. testsuite/ChangeLog: * gcc.c-torture/execute/20031003-1.c (main): Update test to accommodate SPU single-precision rounding mode. * gcc.c-torture/execute/conversion.c (test_float_to_integer, test_float_to_longlong_integer): Likewise. * gcc.c-torture/execute/ieee/rbug.c (main): Likewise. * gcc.dg/hex-round-1.c: Skip test on SPU. * gcc.dg/hex-round-2.c: Likewise. Co-Authored-By: Trevor Smigiel <Trevor_Smigiel@playstation.sony.com> From-SVN: r139014
This commit is contained in:
parent
88f091f5ae
commit
3e479de394
@ -1,3 +1,31 @@
|
||||
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
Trevor Smigiel <trevor_smigiel@playstation.sony.com>
|
||||
|
||||
* real.h (struct real_format): New member round_towards_zero.
|
||||
* real.c (round_for_format): Respect fmt->round_towards_zero.
|
||||
(ieee_single_format, mips_single_format, motorola_single_format,
|
||||
spu_single_format, ieee_double_format, mips_double_format,
|
||||
motorola_double_format, ieee_extended_motorola_format,
|
||||
ieee_extended_intel_96_format, ieee_extended_intel_128_format,
|
||||
ieee_extended_intel_96_round_53_format, ibm_extended_format,
|
||||
mips_extended_format, ieee_quad_format, mips_quad_format,
|
||||
vax_f_format, vax_d_format, vax_g_format): Initialize it.
|
||||
* config/pdp11/pdp11.c (pdp11_f_format, pdp11_d_format): Likewise.
|
||||
|
||||
* builtins.s (do_mpfr_arg1): Consider round_towards_zero member of
|
||||
real_format to choose rounding mode when calling MPFR functions.
|
||||
(do_mpfr_arg2, do_mpfr_arg3, do_mpfr_sincos): Likewise.
|
||||
(do_mpfr_bessel_n, do_mpfr_remquo, do_mpfr_lgamma_r): Likewise.
|
||||
|
||||
* real.h (real_to_decimal_for_mode): Add prototype.
|
||||
* real.c (real_to_decimal_for_mode): Renames old real_to_decimal.
|
||||
Respect target rounding mode when generating decimal representation.
|
||||
(real_to_decimal): New stub for backwards compatibility.
|
||||
* c-cppbuiltin.c (builtin_define_with_hex_fp_value): Use
|
||||
real_to_decimal_for_mode instead of real_to_decimal.
|
||||
|
||||
* config/spu/spu.md ("floatdisf2", "floatunsdisf2"): New.
|
||||
|
||||
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
Trevor Smigiel <trevor_smigiel@playstation.sony.com>
|
||||
|
||||
|
@ -12867,14 +12867,16 @@ do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
|
||||
&& (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
|
||||
&& (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max)))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
int inexact;
|
||||
mpfr_t m;
|
||||
|
||||
mpfr_init2 (m, prec);
|
||||
mpfr_from_real (m, ra, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
inexact = func (m, m, GMP_RNDN);
|
||||
inexact = func (m, m, rnd);
|
||||
result = do_mpfr_ckconv (m, type, inexact);
|
||||
mpfr_clear (m);
|
||||
}
|
||||
@ -12909,7 +12911,9 @@ do_mpfr_arg2 (tree arg1, tree arg2, tree type,
|
||||
|
||||
if (real_isfinite (ra1) && real_isfinite (ra2))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
int inexact;
|
||||
mpfr_t m1, m2;
|
||||
|
||||
@ -12917,7 +12921,7 @@ do_mpfr_arg2 (tree arg1, tree arg2, tree type,
|
||||
mpfr_from_real (m1, ra1, GMP_RNDN);
|
||||
mpfr_from_real (m2, ra2, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
inexact = func (m1, m1, m2, GMP_RNDN);
|
||||
inexact = func (m1, m1, m2, rnd);
|
||||
result = do_mpfr_ckconv (m1, type, inexact);
|
||||
mpfr_clears (m1, m2, NULL);
|
||||
}
|
||||
@ -12955,7 +12959,9 @@ do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
|
||||
|
||||
if (real_isfinite (ra1) && real_isfinite (ra2) && real_isfinite (ra3))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
int inexact;
|
||||
mpfr_t m1, m2, m3;
|
||||
|
||||
@ -12964,7 +12970,7 @@ do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
|
||||
mpfr_from_real (m2, ra2, GMP_RNDN);
|
||||
mpfr_from_real (m3, ra3, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
inexact = func (m1, m1, m2, m3, GMP_RNDN);
|
||||
inexact = func (m1, m1, m2, m3, rnd);
|
||||
result = do_mpfr_ckconv (m1, type, inexact);
|
||||
mpfr_clears (m1, m2, m3, NULL);
|
||||
}
|
||||
@ -12998,7 +13004,9 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
|
||||
|
||||
if (real_isfinite (ra))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
tree result_s, result_c;
|
||||
int inexact;
|
||||
mpfr_t m, ms, mc;
|
||||
@ -13006,7 +13014,7 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
|
||||
mpfr_inits2 (prec, m, ms, mc, NULL);
|
||||
mpfr_from_real (m, ra, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_sin_cos (ms, mc, m, GMP_RNDN);
|
||||
inexact = mpfr_sin_cos (ms, mc, m, rnd);
|
||||
result_s = do_mpfr_ckconv (ms, type, inexact);
|
||||
result_c = do_mpfr_ckconv (mc, type, inexact);
|
||||
mpfr_clears (m, ms, mc, NULL);
|
||||
@ -13071,14 +13079,17 @@ do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
|
||||
&& real_isfinite (ra)
|
||||
&& (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
tree result_s, result_c;
|
||||
int inexact;
|
||||
mpfr_t m;
|
||||
|
||||
mpfr_init2 (m, prec);
|
||||
mpfr_from_real (m, ra, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
inexact = func (m, n, m, GMP_RNDN);
|
||||
inexact = func (m, n, m, rnd);
|
||||
result = do_mpfr_ckconv (m, type, inexact);
|
||||
mpfr_clear (m);
|
||||
}
|
||||
@ -13112,7 +13123,9 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
|
||||
|
||||
if (real_isfinite (ra0) && real_isfinite (ra1))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
tree result_rem;
|
||||
long integer_quo;
|
||||
mpfr_t m0, m1;
|
||||
@ -13121,7 +13134,7 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
|
||||
mpfr_from_real (m0, ra0, GMP_RNDN);
|
||||
mpfr_from_real (m1, ra1, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
mpfr_remquo (m0, &integer_quo, m0, m1, GMP_RNDN);
|
||||
mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
|
||||
/* Remquo is independent of the rounding mode, so pass
|
||||
inexact=0 to do_mpfr_ckconv(). */
|
||||
result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
|
||||
@ -13189,7 +13202,9 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
|
||||
&& ra->cl != rvc_zero
|
||||
&& !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
|
||||
{
|
||||
const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
const int prec = fmt->p;
|
||||
const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
|
||||
int inexact, sg;
|
||||
mpfr_t m;
|
||||
tree result_lg;
|
||||
@ -13197,7 +13212,7 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
|
||||
mpfr_init2 (m, prec);
|
||||
mpfr_from_real (m, ra, GMP_RNDN);
|
||||
mpfr_clear_flags ();
|
||||
inexact = mpfr_lgamma (m, &sg, m, GMP_RNDN);
|
||||
inexact = mpfr_lgamma (m, &sg, m, rnd);
|
||||
result_lg = do_mpfr_ckconv (m, type, inexact);
|
||||
mpfr_clear (m);
|
||||
if (result_lg)
|
||||
|
@ -852,7 +852,7 @@ builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value)
|
||||
/* Pass an object-like macro a hexadecimal floating-point value. */
|
||||
static void
|
||||
builtin_define_with_hex_fp_value (const char *macro,
|
||||
tree type ATTRIBUTE_UNUSED, int digits,
|
||||
tree type, int digits,
|
||||
const char *hex_str,
|
||||
const char *fp_suffix,
|
||||
const char *fp_cast)
|
||||
@ -871,7 +871,8 @@ builtin_define_with_hex_fp_value (const char *macro,
|
||||
then print it back out as decimal. */
|
||||
|
||||
real_from_string (&real, hex_str);
|
||||
real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
|
||||
real_to_decimal_for_mode (dec_str, &real, sizeof (dec_str), digits, 0,
|
||||
TYPE_MODE (type));
|
||||
|
||||
/* Assemble the macro in the following fashion
|
||||
macro = fp_cast [dec_str fp_suffix] */
|
||||
|
@ -78,6 +78,7 @@ const struct real_format pdp11_f_format =
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
@ -97,6 +98,7 @@ const struct real_format pdp11_d_format =
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
|
@ -664,6 +664,65 @@
|
||||
"frds\t%0,%1"
|
||||
[(set_attr "type" "fpd")])
|
||||
|
||||
(define_expand "floatdisf2"
|
||||
[(set (match_operand:SF 0 "register_operand" "")
|
||||
(float:SF (match_operand:DI 1 "register_operand" "")))]
|
||||
""
|
||||
{
|
||||
rtx c0 = gen_reg_rtx (SImode);
|
||||
rtx r0 = gen_reg_rtx (DImode);
|
||||
rtx r1 = gen_reg_rtx (SFmode);
|
||||
rtx r2 = gen_reg_rtx (SImode);
|
||||
rtx setneg = gen_reg_rtx (SImode);
|
||||
rtx isneg = gen_reg_rtx (SImode);
|
||||
rtx neg = gen_reg_rtx (DImode);
|
||||
rtx mask = gen_reg_rtx (DImode);
|
||||
|
||||
emit_move_insn (c0, GEN_INT (-0x80000000ll));
|
||||
|
||||
emit_insn (gen_negdi2 (neg, operands[1]));
|
||||
emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
|
||||
emit_insn (gen_extend_compare (mask, isneg));
|
||||
emit_insn (gen_selb (r0, neg, operands[1], mask));
|
||||
emit_insn (gen_andc_si (setneg, c0, isneg));
|
||||
|
||||
emit_insn (gen_floatunsdisf2 (r1, r0));
|
||||
|
||||
emit_insn (gen_iorsi3 (r2, gen_rtx_SUBREG (SImode, r1, 0), setneg));
|
||||
emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, r2, 0));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn_and_split "floatunsdisf2"
|
||||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||||
(unsigned_float:SF (match_operand:DI 1 "register_operand" "r")))
|
||||
(clobber (match_scratch:SF 2 "=r"))
|
||||
(clobber (match_scratch:SF 3 "=r"))
|
||||
(clobber (match_scratch:SF 4 "=r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(set (match_dup:SF 0)
|
||||
(unsigned_float:SF (match_dup:DI 1)))]
|
||||
{
|
||||
rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (operands[1]));
|
||||
rtx op2_v4sf = gen_rtx_REG (V4SFmode, REGNO (operands[2]));
|
||||
rtx op2_ti = gen_rtx_REG (TImode, REGNO (operands[2]));
|
||||
rtx op3_ti = gen_rtx_REG (TImode, REGNO (operands[3]));
|
||||
|
||||
REAL_VALUE_TYPE scale;
|
||||
real_2expN (&scale, 32, SFmode);
|
||||
|
||||
emit_insn (gen_floatunsv4siv4sf2 (op2_v4sf, op1_v4si));
|
||||
emit_insn (gen_shlqby_ti (op3_ti, op2_ti, GEN_INT (4)));
|
||||
|
||||
emit_move_insn (operands[4],
|
||||
CONST_DOUBLE_FROM_REAL_VALUE (scale, SFmode));
|
||||
emit_insn (gen_fma_sf (operands[0],
|
||||
operands[2], operands[4], operands[3]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
|
||||
(define_expand "floatsidf2"
|
||||
[(set (match_operand:DF 0 "register_operand" "")
|
||||
|
120
gcc/real.c
120
gcc/real.c
@ -1443,20 +1443,30 @@ rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den)
|
||||
/* Render R as a decimal floating point constant. Emit DIGITS significant
|
||||
digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the
|
||||
maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing
|
||||
zeros. */
|
||||
zeros. If MODE is VOIDmode, round to nearest value. Otherwise, round
|
||||
to a string that, when parsed back in mode MODE, yields the same value. */
|
||||
|
||||
#define M_LOG10_2 0.30102999566398119521
|
||||
|
||||
void
|
||||
real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
|
||||
size_t digits, int crop_trailing_zeros)
|
||||
real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig,
|
||||
size_t buf_size, size_t digits,
|
||||
int crop_trailing_zeros, enum machine_mode mode)
|
||||
{
|
||||
const struct real_format *fmt = NULL;
|
||||
const REAL_VALUE_TYPE *one, *ten;
|
||||
REAL_VALUE_TYPE r, pten, u, v;
|
||||
int dec_exp, cmp_one, digit;
|
||||
size_t max_digits;
|
||||
char *p, *first, *last;
|
||||
bool sign;
|
||||
bool round_up;
|
||||
|
||||
if (mode != VOIDmode)
|
||||
{
|
||||
fmt = REAL_MODE_FORMAT (mode);
|
||||
gcc_assert (fmt);
|
||||
}
|
||||
|
||||
r = *r_orig;
|
||||
switch (r.cl)
|
||||
@ -1672,17 +1682,31 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
|
||||
digit = rtd_divmod (&r, &pten);
|
||||
|
||||
/* Round the result. */
|
||||
if (digit == 5)
|
||||
if (fmt && fmt->round_towards_zero)
|
||||
{
|
||||
/* Round to nearest. If R is nonzero there are additional
|
||||
nonzero digits to be extracted. */
|
||||
/* If the format uses round towards zero when parsing the string
|
||||
back in, we need to always round away from zero here. */
|
||||
if (cmp_significand_0 (&r))
|
||||
digit++;
|
||||
/* Round to even. */
|
||||
else if ((p[-1] - '0') & 1)
|
||||
digit++;
|
||||
round_up = digit > 0;
|
||||
}
|
||||
if (digit > 5)
|
||||
else
|
||||
{
|
||||
if (digit == 5)
|
||||
{
|
||||
/* Round to nearest. If R is nonzero there are additional
|
||||
nonzero digits to be extracted. */
|
||||
if (cmp_significand_0 (&r))
|
||||
digit++;
|
||||
/* Round to even. */
|
||||
else if ((p[-1] - '0') & 1)
|
||||
digit++;
|
||||
}
|
||||
|
||||
round_up = digit > 5;
|
||||
}
|
||||
|
||||
if (round_up)
|
||||
{
|
||||
while (p > first)
|
||||
{
|
||||
@ -1716,6 +1740,26 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
|
||||
|
||||
/* Append the exponent. */
|
||||
sprintf (last, "e%+d", dec_exp);
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
/* Verify that we can read the original value back in. */
|
||||
if (mode != VOIDmode)
|
||||
{
|
||||
real_from_string (&r, str);
|
||||
real_convert (&r, mode, &r);
|
||||
gcc_assert (real_identical (&r, r_orig));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Likewise, except always uses round-to-nearest. */
|
||||
|
||||
void
|
||||
real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
|
||||
size_t digits, int crop_trailing_zeros)
|
||||
{
|
||||
real_to_decimal_for_mode (str, r_orig, buf_size,
|
||||
digits, crop_trailing_zeros, VOIDmode);
|
||||
}
|
||||
|
||||
/* Render R as a hexadecimal floating point constant. Emit DIGITS
|
||||
@ -2389,9 +2433,8 @@ static void
|
||||
round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||
{
|
||||
int p2, np2, i, w;
|
||||
unsigned long sticky;
|
||||
bool guard, lsb;
|
||||
int emin2m1, emax2;
|
||||
bool round_up = false;
|
||||
|
||||
if (r->decimal)
|
||||
{
|
||||
@ -2463,21 +2506,28 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||
}
|
||||
}
|
||||
|
||||
/* There are P2 true significand bits, followed by one guard bit,
|
||||
followed by one sticky bit, followed by stuff. Fold nonzero
|
||||
stuff into the sticky bit. */
|
||||
if (!fmt->round_towards_zero)
|
||||
{
|
||||
/* There are P2 true significand bits, followed by one guard bit,
|
||||
followed by one sticky bit, followed by stuff. Fold nonzero
|
||||
stuff into the sticky bit. */
|
||||
unsigned long sticky;
|
||||
bool guard, lsb;
|
||||
|
||||
sticky = 0;
|
||||
for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
|
||||
sticky |= r->sig[i];
|
||||
sticky |=
|
||||
r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
|
||||
sticky = 0;
|
||||
for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
|
||||
sticky |= r->sig[i];
|
||||
sticky |= r->sig[w]
|
||||
& (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
|
||||
|
||||
guard = test_significand_bit (r, np2 - 1);
|
||||
lsb = test_significand_bit (r, np2);
|
||||
guard = test_significand_bit (r, np2 - 1);
|
||||
lsb = test_significand_bit (r, np2);
|
||||
|
||||
/* Round to even. */
|
||||
if (guard && (sticky || lsb))
|
||||
/* Round to even. */
|
||||
round_up = guard && (sticky || lsb);
|
||||
}
|
||||
|
||||
if (round_up)
|
||||
{
|
||||
REAL_VALUE_TYPE u;
|
||||
get_zero (&u, 0);
|
||||
@ -2817,6 +2867,7 @@ const struct real_format ieee_single_format =
|
||||
128,
|
||||
31,
|
||||
31,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -2836,6 +2887,7 @@ const struct real_format mips_single_format =
|
||||
128,
|
||||
31,
|
||||
31,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -2855,6 +2907,7 @@ const struct real_format motorola_single_format =
|
||||
128,
|
||||
31,
|
||||
31,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -2885,6 +2938,7 @@ const struct real_format spu_single_format =
|
||||
129,
|
||||
31,
|
||||
31,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
@ -3092,6 +3146,7 @@ const struct real_format ieee_double_format =
|
||||
1024,
|
||||
63,
|
||||
63,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3111,6 +3166,7 @@ const struct real_format mips_double_format =
|
||||
1024,
|
||||
63,
|
||||
63,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3130,6 +3186,7 @@ const struct real_format motorola_double_format =
|
||||
1024,
|
||||
63,
|
||||
63,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3467,6 +3524,7 @@ const struct real_format ieee_extended_motorola_format =
|
||||
16384,
|
||||
95,
|
||||
95,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3486,6 +3544,7 @@ const struct real_format ieee_extended_intel_96_format =
|
||||
16384,
|
||||
79,
|
||||
79,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3505,6 +3564,7 @@ const struct real_format ieee_extended_intel_128_format =
|
||||
16384,
|
||||
79,
|
||||
79,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3526,6 +3586,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
|
||||
16384,
|
||||
79,
|
||||
79,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3612,6 +3673,7 @@ const struct real_format ibm_extended_format =
|
||||
1024,
|
||||
127,
|
||||
-1,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3631,6 +3693,7 @@ const struct real_format mips_extended_format =
|
||||
1024,
|
||||
127,
|
||||
-1,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3892,6 +3955,7 @@ const struct real_format ieee_quad_format =
|
||||
16384,
|
||||
127,
|
||||
127,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -3911,6 +3975,7 @@ const struct real_format mips_quad_format =
|
||||
16384,
|
||||
127,
|
||||
127,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -4214,6 +4279,7 @@ const struct real_format vax_f_format =
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
@ -4233,6 +4299,7 @@ const struct real_format vax_d_format =
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
@ -4252,6 +4319,7 @@ const struct real_format vax_g_format =
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
@ -4321,6 +4389,7 @@ const struct real_format decimal_single_format =
|
||||
96,
|
||||
31,
|
||||
31,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -4341,6 +4410,7 @@ const struct real_format decimal_double_format =
|
||||
384,
|
||||
63,
|
||||
63,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -4361,6 +4431,7 @@ const struct real_format decimal_quad_format =
|
||||
6144,
|
||||
127,
|
||||
127,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
@ -4404,6 +4475,7 @@ const struct real_format real_internal_format =
|
||||
MAX_EXP,
|
||||
-1,
|
||||
-1,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
|
@ -147,6 +147,9 @@ struct real_format
|
||||
or -1 for a complex encoding. */
|
||||
int signbit_rw;
|
||||
|
||||
/* Default rounding mode for operations on this format. */
|
||||
bool round_towards_zero;
|
||||
|
||||
/* Properties of the format. */
|
||||
bool has_nans;
|
||||
bool has_inf;
|
||||
@ -216,6 +219,11 @@ extern bool exact_real_truncate (enum machine_mode, const REAL_VALUE_TYPE *);
|
||||
extern void real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t,
|
||||
size_t, int);
|
||||
|
||||
/* Render R as a decimal floating point constant, rounded so as to be
|
||||
parsed back to the same value when interpreted in mode MODE. */
|
||||
extern void real_to_decimal_for_mode (char *, const REAL_VALUE_TYPE *, size_t,
|
||||
size_t, int, enum machine_mode);
|
||||
|
||||
/* Render R as a hexadecimal floating point constant. */
|
||||
extern void real_to_hexadecimal (char *, const REAL_VALUE_TYPE *,
|
||||
size_t, size_t, int);
|
||||
|
@ -1,3 +1,13 @@
|
||||
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* gcc.c-torture/execute/20031003-1.c (main): Update test to
|
||||
accommodate SPU single-precision rounding mode.
|
||||
* gcc.c-torture/execute/conversion.c (test_float_to_integer,
|
||||
test_float_to_longlong_integer): Likewise.
|
||||
* gcc.c-torture/execute/ieee/rbug.c (main): Likewise.
|
||||
* gcc.dg/hex-round-1.c: Skip test on SPU.
|
||||
* gcc.dg/hex-round-2.c: Likewise.
|
||||
|
||||
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* gcc.c-torture/execute/ieee/inf-2.c (testf): Skip on the SPU.
|
||||
|
@ -19,8 +19,14 @@ int main()
|
||||
#if INT_MAX == 2147483647
|
||||
if (f1() != 2147483647)
|
||||
abort ();
|
||||
#ifdef __SPU__
|
||||
/* SPU float rounds towards zero. */
|
||||
if (f2() != 0x7fffff80)
|
||||
abort ();
|
||||
#else
|
||||
if (f2() != 2147483647)
|
||||
abort ();
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -284,9 +284,15 @@ test_float_to_integer()
|
||||
abort();
|
||||
if (f2u(1.99) != 1)
|
||||
abort();
|
||||
#ifdef __SPU__
|
||||
/* SPU float rounds towards zero. */
|
||||
if (f2u((float) ((~0U) >> 1)) != 0x7fffff80)
|
||||
abort();
|
||||
#else
|
||||
if (f2u((float) ((~0U) >> 1)) != (~0U) >> 1 && /* 0x7fffffff */
|
||||
f2u((float) ((~0U) >> 1)) != ((~0U) >> 1) + 1)
|
||||
abort();
|
||||
#endif
|
||||
if (f2u((float) ~((~0U) >> 1)) != ~((~0U) >> 1)) /* 0x80000000 */
|
||||
abort();
|
||||
|
||||
@ -439,9 +445,15 @@ test_float_to_longlong_integer()
|
||||
abort();
|
||||
if (f2ull(1.99) != 1LL)
|
||||
abort();
|
||||
#ifdef __SPU__
|
||||
/* SPU float rounds towards zero. */
|
||||
if (f2ull((float) ((~0ULL) >> 1)) != 0x7fffff8000000000ULL)
|
||||
abort();
|
||||
#else
|
||||
if (f2ull((float) ((~0ULL) >> 1)) != (~0ULL) >> 1 && /* 0x7fffffff */
|
||||
f2ull((float) ((~0ULL) >> 1)) != ((~0ULL) >> 1) + 1)
|
||||
abort();
|
||||
#endif
|
||||
if (f2ull((float) ~((~0ULL) >> 1)) != ~((~0ULL) >> 1)) /* 0x80000000 */
|
||||
abort();
|
||||
|
||||
|
@ -41,8 +41,14 @@ main ()
|
||||
k = 0x8234508000000001ULL;
|
||||
x = s (k);
|
||||
k = (unsigned long long) x;
|
||||
#ifdef __SPU__
|
||||
/* SPU float rounds towards zero. */
|
||||
if (k != 0x8234500000000000ULL)
|
||||
abort ();
|
||||
#else
|
||||
if (k != 0x8234510000000000ULL)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Test for hexadecimal float rounding: bug 21720. */
|
||||
/* { dg-do link } */
|
||||
/* { dg-options "-O -std=gnu99" } */
|
||||
/* { dg-skip-if "SPU float rounds towards zero" { spu-*-* } } */
|
||||
|
||||
#include <float.h>
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
in number. */
|
||||
/* { dg-do link } */
|
||||
/* { dg-options "-O -std=gnu99" } */
|
||||
/* { dg-skip-if "SPU float rounds towards zero" { spu-*-* } } */
|
||||
|
||||
#include <float.h>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user