Commit 3e479de3 by Ulrich Weigand Committed by Ulrich Weigand

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
parent 88f091f5
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> 2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Trevor Smigiel <trevor_smigiel@playstation.sony.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>
* real.c (spu_single_format): New variable. * real.c (spu_single_format): New variable.
* real.h (spu_single_format): Declare. * real.h (spu_single_format): Declare.
......
...@@ -12867,14 +12867,16 @@ do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t), ...@@ -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)) && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))
&& (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max))) && (!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; int inexact;
mpfr_t m; mpfr_t m;
mpfr_init2 (m, prec); mpfr_init2 (m, prec);
mpfr_from_real (m, ra, GMP_RNDN); mpfr_from_real (m, ra, GMP_RNDN);
mpfr_clear_flags (); mpfr_clear_flags ();
inexact = func (m, m, GMP_RNDN); inexact = func (m, m, rnd);
result = do_mpfr_ckconv (m, type, inexact); result = do_mpfr_ckconv (m, type, inexact);
mpfr_clear (m); mpfr_clear (m);
} }
...@@ -12909,7 +12911,9 @@ do_mpfr_arg2 (tree arg1, tree arg2, tree type, ...@@ -12909,7 +12911,9 @@ do_mpfr_arg2 (tree arg1, tree arg2, tree type,
if (real_isfinite (ra1) && real_isfinite (ra2)) 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; int inexact;
mpfr_t m1, m2; mpfr_t m1, m2;
...@@ -12917,7 +12921,7 @@ do_mpfr_arg2 (tree arg1, tree arg2, tree type, ...@@ -12917,7 +12921,7 @@ do_mpfr_arg2 (tree arg1, tree arg2, tree type,
mpfr_from_real (m1, ra1, GMP_RNDN); mpfr_from_real (m1, ra1, GMP_RNDN);
mpfr_from_real (m2, ra2, GMP_RNDN); mpfr_from_real (m2, ra2, GMP_RNDN);
mpfr_clear_flags (); mpfr_clear_flags ();
inexact = func (m1, m1, m2, GMP_RNDN); inexact = func (m1, m1, m2, rnd);
result = do_mpfr_ckconv (m1, type, inexact); result = do_mpfr_ckconv (m1, type, inexact);
mpfr_clears (m1, m2, NULL); mpfr_clears (m1, m2, NULL);
} }
...@@ -12955,7 +12959,9 @@ do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type, ...@@ -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)) 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; int inexact;
mpfr_t m1, m2, m3; mpfr_t m1, m2, m3;
...@@ -12964,7 +12970,7 @@ do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type, ...@@ -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 (m2, ra2, GMP_RNDN);
mpfr_from_real (m3, ra3, GMP_RNDN); mpfr_from_real (m3, ra3, GMP_RNDN);
mpfr_clear_flags (); 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); result = do_mpfr_ckconv (m1, type, inexact);
mpfr_clears (m1, m2, m3, NULL); mpfr_clears (m1, m2, m3, NULL);
} }
...@@ -12998,7 +13004,9 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp) ...@@ -12998,7 +13004,9 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
if (real_isfinite (ra)) 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; tree result_s, result_c;
int inexact; int inexact;
mpfr_t m, ms, mc; mpfr_t m, ms, mc;
...@@ -13006,7 +13014,7 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp) ...@@ -13006,7 +13014,7 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
mpfr_inits2 (prec, m, ms, mc, NULL); mpfr_inits2 (prec, m, ms, mc, NULL);
mpfr_from_real (m, ra, GMP_RNDN); mpfr_from_real (m, ra, GMP_RNDN);
mpfr_clear_flags (); 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_s = do_mpfr_ckconv (ms, type, inexact);
result_c = do_mpfr_ckconv (mc, type, inexact); result_c = do_mpfr_ckconv (mc, type, inexact);
mpfr_clears (m, ms, mc, NULL); mpfr_clears (m, ms, mc, NULL);
...@@ -13071,14 +13079,17 @@ do_mpfr_bessel_n (tree arg1, tree arg2, tree type, ...@@ -13071,14 +13079,17 @@ do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
&& real_isfinite (ra) && real_isfinite (ra)
&& (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min))) && (!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; int inexact;
mpfr_t m; mpfr_t m;
mpfr_init2 (m, prec); mpfr_init2 (m, prec);
mpfr_from_real (m, ra, GMP_RNDN); mpfr_from_real (m, ra, GMP_RNDN);
mpfr_clear_flags (); mpfr_clear_flags ();
inexact = func (m, n, m, GMP_RNDN); inexact = func (m, n, m, rnd);
result = do_mpfr_ckconv (m, type, inexact); result = do_mpfr_ckconv (m, type, inexact);
mpfr_clear (m); mpfr_clear (m);
} }
...@@ -13112,7 +13123,9 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo) ...@@ -13112,7 +13123,9 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
if (real_isfinite (ra0) && real_isfinite (ra1)) 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; tree result_rem;
long integer_quo; long integer_quo;
mpfr_t m0, m1; mpfr_t m0, m1;
...@@ -13121,7 +13134,7 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo) ...@@ -13121,7 +13134,7 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
mpfr_from_real (m0, ra0, GMP_RNDN); mpfr_from_real (m0, ra0, GMP_RNDN);
mpfr_from_real (m1, ra1, GMP_RNDN); mpfr_from_real (m1, ra1, GMP_RNDN);
mpfr_clear_flags (); 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 /* Remquo is independent of the rounding mode, so pass
inexact=0 to do_mpfr_ckconv(). */ inexact=0 to do_mpfr_ckconv(). */
result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0); result_rem = do_mpfr_ckconv (m0, type, /*inexact=*/ 0);
...@@ -13189,7 +13202,9 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type) ...@@ -13189,7 +13202,9 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
&& ra->cl != rvc_zero && ra->cl != rvc_zero
&& !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type)))) && !(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; int inexact, sg;
mpfr_t m; mpfr_t m;
tree result_lg; tree result_lg;
...@@ -13197,7 +13212,7 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type) ...@@ -13197,7 +13212,7 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
mpfr_init2 (m, prec); mpfr_init2 (m, prec);
mpfr_from_real (m, ra, GMP_RNDN); mpfr_from_real (m, ra, GMP_RNDN);
mpfr_clear_flags (); 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); result_lg = do_mpfr_ckconv (m, type, inexact);
mpfr_clear (m); mpfr_clear (m);
if (result_lg) if (result_lg)
......
...@@ -852,7 +852,7 @@ builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value) ...@@ -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. */ /* Pass an object-like macro a hexadecimal floating-point value. */
static void static void
builtin_define_with_hex_fp_value (const char *macro, 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 *hex_str,
const char *fp_suffix, const char *fp_suffix,
const char *fp_cast) const char *fp_cast)
...@@ -871,7 +871,8 @@ builtin_define_with_hex_fp_value (const char *macro, ...@@ -871,7 +871,8 @@ builtin_define_with_hex_fp_value (const char *macro,
then print it back out as decimal. */ then print it back out as decimal. */
real_from_string (&real, hex_str); 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 /* Assemble the macro in the following fashion
macro = fp_cast [dec_str fp_suffix] */ macro = fp_cast [dec_str fp_suffix] */
......
...@@ -78,6 +78,7 @@ const struct real_format pdp11_f_format = ...@@ -78,6 +78,7 @@ const struct real_format pdp11_f_format =
false, false,
false, false,
false, false,
false,
false false
}; };
...@@ -97,6 +98,7 @@ const struct real_format pdp11_d_format = ...@@ -97,6 +98,7 @@ const struct real_format pdp11_d_format =
false, false,
false, false,
false, false,
false,
false false
}; };
......
...@@ -664,6 +664,65 @@ ...@@ -664,6 +664,65 @@
"frds\t%0,%1" "frds\t%0,%1"
[(set_attr "type" "fpd")]) [(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 ;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
(define_expand "floatsidf2" (define_expand "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "") [(set (match_operand:DF 0 "register_operand" "")
......
...@@ -1443,20 +1443,30 @@ rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den) ...@@ -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 /* 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 digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the
maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing 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 #define M_LOG10_2 0.30102999566398119521
void void
real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig,
size_t digits, int crop_trailing_zeros) 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; const REAL_VALUE_TYPE *one, *ten;
REAL_VALUE_TYPE r, pten, u, v; REAL_VALUE_TYPE r, pten, u, v;
int dec_exp, cmp_one, digit; int dec_exp, cmp_one, digit;
size_t max_digits; size_t max_digits;
char *p, *first, *last; char *p, *first, *last;
bool sign; bool sign;
bool round_up;
if (mode != VOIDmode)
{
fmt = REAL_MODE_FORMAT (mode);
gcc_assert (fmt);
}
r = *r_orig; r = *r_orig;
switch (r.cl) switch (r.cl)
...@@ -1672,6 +1682,16 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, ...@@ -1672,6 +1682,16 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
digit = rtd_divmod (&r, &pten); digit = rtd_divmod (&r, &pten);
/* Round the result. */ /* Round the result. */
if (fmt && fmt->round_towards_zero)
{
/* 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_up = digit > 0;
}
else
{
if (digit == 5) if (digit == 5)
{ {
/* Round to nearest. If R is nonzero there are additional /* Round to nearest. If R is nonzero there are additional
...@@ -1682,7 +1702,11 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, ...@@ -1682,7 +1702,11 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
else if ((p[-1] - '0') & 1) else if ((p[-1] - '0') & 1)
digit++; digit++;
} }
if (digit > 5)
round_up = digit > 5;
}
if (round_up)
{ {
while (p > first) while (p > first)
{ {
...@@ -1716,6 +1740,26 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, ...@@ -1716,6 +1740,26 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
/* Append the exponent. */ /* Append the exponent. */
sprintf (last, "e%+d", dec_exp); 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 /* Render R as a hexadecimal floating point constant. Emit DIGITS
...@@ -2389,9 +2433,8 @@ static void ...@@ -2389,9 +2433,8 @@ static void
round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
{ {
int p2, np2, i, w; int p2, np2, i, w;
unsigned long sticky;
bool guard, lsb;
int emin2m1, emax2; int emin2m1, emax2;
bool round_up = false;
if (r->decimal) if (r->decimal)
{ {
...@@ -2463,21 +2506,28 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) ...@@ -2463,21 +2506,28 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
} }
} }
if (!fmt->round_towards_zero)
{
/* There are P2 true significand bits, followed by one guard bit, /* There are P2 true significand bits, followed by one guard bit,
followed by one sticky bit, followed by stuff. Fold nonzero followed by one sticky bit, followed by stuff. Fold nonzero
stuff into the sticky bit. */ stuff into the sticky bit. */
unsigned long sticky;
bool guard, lsb;
sticky = 0; sticky = 0;
for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i) for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
sticky |= r->sig[i]; sticky |= r->sig[i];
sticky |= sticky |= r->sig[w]
r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1); & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
guard = test_significand_bit (r, np2 - 1); guard = test_significand_bit (r, np2 - 1);
lsb = test_significand_bit (r, np2); lsb = test_significand_bit (r, np2);
/* Round to even. */ /* Round to even. */
if (guard && (sticky || lsb)) round_up = guard && (sticky || lsb);
}
if (round_up)
{ {
REAL_VALUE_TYPE u; REAL_VALUE_TYPE u;
get_zero (&u, 0); get_zero (&u, 0);
...@@ -2817,6 +2867,7 @@ const struct real_format ieee_single_format = ...@@ -2817,6 +2867,7 @@ const struct real_format ieee_single_format =
128, 128,
31, 31,
31, 31,
false,
true, true,
true, true,
true, true,
...@@ -2836,6 +2887,7 @@ const struct real_format mips_single_format = ...@@ -2836,6 +2887,7 @@ const struct real_format mips_single_format =
128, 128,
31, 31,
31, 31,
false,
true, true,
true, true,
true, true,
...@@ -2855,6 +2907,7 @@ const struct real_format motorola_single_format = ...@@ -2855,6 +2907,7 @@ const struct real_format motorola_single_format =
128, 128,
31, 31,
31, 31,
false,
true, true,
true, true,
true, true,
...@@ -2885,6 +2938,7 @@ const struct real_format spu_single_format = ...@@ -2885,6 +2938,7 @@ const struct real_format spu_single_format =
129, 129,
31, 31,
31, 31,
true,
false, false,
false, false,
true, true,
...@@ -3092,6 +3146,7 @@ const struct real_format ieee_double_format = ...@@ -3092,6 +3146,7 @@ const struct real_format ieee_double_format =
1024, 1024,
63, 63,
63, 63,
false,
true, true,
true, true,
true, true,
...@@ -3111,6 +3166,7 @@ const struct real_format mips_double_format = ...@@ -3111,6 +3166,7 @@ const struct real_format mips_double_format =
1024, 1024,
63, 63,
63, 63,
false,
true, true,
true, true,
true, true,
...@@ -3130,6 +3186,7 @@ const struct real_format motorola_double_format = ...@@ -3130,6 +3186,7 @@ const struct real_format motorola_double_format =
1024, 1024,
63, 63,
63, 63,
false,
true, true,
true, true,
true, true,
...@@ -3467,6 +3524,7 @@ const struct real_format ieee_extended_motorola_format = ...@@ -3467,6 +3524,7 @@ const struct real_format ieee_extended_motorola_format =
16384, 16384,
95, 95,
95, 95,
false,
true, true,
true, true,
true, true,
...@@ -3486,6 +3544,7 @@ const struct real_format ieee_extended_intel_96_format = ...@@ -3486,6 +3544,7 @@ const struct real_format ieee_extended_intel_96_format =
16384, 16384,
79, 79,
79, 79,
false,
true, true,
true, true,
true, true,
...@@ -3505,6 +3564,7 @@ const struct real_format ieee_extended_intel_128_format = ...@@ -3505,6 +3564,7 @@ const struct real_format ieee_extended_intel_128_format =
16384, 16384,
79, 79,
79, 79,
false,
true, true,
true, true,
true, true,
...@@ -3526,6 +3586,7 @@ const struct real_format ieee_extended_intel_96_round_53_format = ...@@ -3526,6 +3586,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
16384, 16384,
79, 79,
79, 79,
false,
true, true,
true, true,
true, true,
...@@ -3612,6 +3673,7 @@ const struct real_format ibm_extended_format = ...@@ -3612,6 +3673,7 @@ const struct real_format ibm_extended_format =
1024, 1024,
127, 127,
-1, -1,
false,
true, true,
true, true,
true, true,
...@@ -3631,6 +3693,7 @@ const struct real_format mips_extended_format = ...@@ -3631,6 +3693,7 @@ const struct real_format mips_extended_format =
1024, 1024,
127, 127,
-1, -1,
false,
true, true,
true, true,
true, true,
...@@ -3892,6 +3955,7 @@ const struct real_format ieee_quad_format = ...@@ -3892,6 +3955,7 @@ const struct real_format ieee_quad_format =
16384, 16384,
127, 127,
127, 127,
false,
true, true,
true, true,
true, true,
...@@ -3911,6 +3975,7 @@ const struct real_format mips_quad_format = ...@@ -3911,6 +3975,7 @@ const struct real_format mips_quad_format =
16384, 16384,
127, 127,
127, 127,
false,
true, true,
true, true,
true, true,
...@@ -4214,6 +4279,7 @@ const struct real_format vax_f_format = ...@@ -4214,6 +4279,7 @@ const struct real_format vax_f_format =
false, false,
false, false,
false, false,
false,
false false
}; };
...@@ -4233,6 +4299,7 @@ const struct real_format vax_d_format = ...@@ -4233,6 +4299,7 @@ const struct real_format vax_d_format =
false, false,
false, false,
false, false,
false,
false false
}; };
...@@ -4252,6 +4319,7 @@ const struct real_format vax_g_format = ...@@ -4252,6 +4319,7 @@ const struct real_format vax_g_format =
false, false,
false, false,
false, false,
false,
false false
}; };
...@@ -4321,6 +4389,7 @@ const struct real_format decimal_single_format = ...@@ -4321,6 +4389,7 @@ const struct real_format decimal_single_format =
96, 96,
31, 31,
31, 31,
false,
true, true,
true, true,
true, true,
...@@ -4341,6 +4410,7 @@ const struct real_format decimal_double_format = ...@@ -4341,6 +4410,7 @@ const struct real_format decimal_double_format =
384, 384,
63, 63,
63, 63,
false,
true, true,
true, true,
true, true,
...@@ -4361,6 +4431,7 @@ const struct real_format decimal_quad_format = ...@@ -4361,6 +4431,7 @@ const struct real_format decimal_quad_format =
6144, 6144,
127, 127,
127, 127,
false,
true, true,
true, true,
true, true,
...@@ -4404,6 +4475,7 @@ const struct real_format real_internal_format = ...@@ -4404,6 +4475,7 @@ const struct real_format real_internal_format =
MAX_EXP, MAX_EXP,
-1, -1,
-1, -1,
false,
true, true,
true, true,
false, false,
......
...@@ -147,6 +147,9 @@ struct real_format ...@@ -147,6 +147,9 @@ struct real_format
or -1 for a complex encoding. */ or -1 for a complex encoding. */
int signbit_rw; int signbit_rw;
/* Default rounding mode for operations on this format. */
bool round_towards_zero;
/* Properties of the format. */ /* Properties of the format. */
bool has_nans; bool has_nans;
bool has_inf; bool has_inf;
...@@ -216,6 +219,11 @@ extern bool exact_real_truncate (enum machine_mode, const REAL_VALUE_TYPE *); ...@@ -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, extern void real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t,
size_t, int); 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. */ /* Render R as a hexadecimal floating point constant. */
extern void real_to_hexadecimal (char *, const REAL_VALUE_TYPE *, extern void real_to_hexadecimal (char *, const REAL_VALUE_TYPE *,
size_t, size_t, int); size_t, size_t, int);
......
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> 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. * gcc.c-torture/execute/ieee/inf-2.c (testf): Skip on the SPU.
2008-08-12 Jakub Jelinek <jakub@redhat.com> 2008-08-12 Jakub Jelinek <jakub@redhat.com>
......
...@@ -19,9 +19,15 @@ int main() ...@@ -19,9 +19,15 @@ int main()
#if INT_MAX == 2147483647 #if INT_MAX == 2147483647
if (f1() != 2147483647) if (f1() != 2147483647)
abort (); abort ();
#ifdef __SPU__
/* SPU float rounds towards zero. */
if (f2() != 0x7fffff80)
abort ();
#else
if (f2() != 2147483647) if (f2() != 2147483647)
abort (); abort ();
#endif #endif
#endif
return 0; return 0;
} }
...@@ -284,9 +284,15 @@ test_float_to_integer() ...@@ -284,9 +284,15 @@ test_float_to_integer()
abort(); abort();
if (f2u(1.99) != 1) if (f2u(1.99) != 1)
abort(); abort();
#ifdef __SPU__
/* SPU float rounds towards zero. */
if (f2u((float) ((~0U) >> 1)) != 0x7fffff80)
abort();
#else
if (f2u((float) ((~0U) >> 1)) != (~0U) >> 1 && /* 0x7fffffff */ if (f2u((float) ((~0U) >> 1)) != (~0U) >> 1 && /* 0x7fffffff */
f2u((float) ((~0U) >> 1)) != ((~0U) >> 1) + 1) f2u((float) ((~0U) >> 1)) != ((~0U) >> 1) + 1)
abort(); abort();
#endif
if (f2u((float) ~((~0U) >> 1)) != ~((~0U) >> 1)) /* 0x80000000 */ if (f2u((float) ~((~0U) >> 1)) != ~((~0U) >> 1)) /* 0x80000000 */
abort(); abort();
...@@ -439,9 +445,15 @@ test_float_to_longlong_integer() ...@@ -439,9 +445,15 @@ test_float_to_longlong_integer()
abort(); abort();
if (f2ull(1.99) != 1LL) if (f2ull(1.99) != 1LL)
abort(); abort();
#ifdef __SPU__
/* SPU float rounds towards zero. */
if (f2ull((float) ((~0ULL) >> 1)) != 0x7fffff8000000000ULL)
abort();
#else
if (f2ull((float) ((~0ULL) >> 1)) != (~0ULL) >> 1 && /* 0x7fffffff */ if (f2ull((float) ((~0ULL) >> 1)) != (~0ULL) >> 1 && /* 0x7fffffff */
f2ull((float) ((~0ULL) >> 1)) != ((~0ULL) >> 1) + 1) f2ull((float) ((~0ULL) >> 1)) != ((~0ULL) >> 1) + 1)
abort(); abort();
#endif
if (f2ull((float) ~((~0ULL) >> 1)) != ~((~0ULL) >> 1)) /* 0x80000000 */ if (f2ull((float) ~((~0ULL) >> 1)) != ~((~0ULL) >> 1)) /* 0x80000000 */
abort(); abort();
......
...@@ -41,8 +41,14 @@ main () ...@@ -41,8 +41,14 @@ main ()
k = 0x8234508000000001ULL; k = 0x8234508000000001ULL;
x = s (k); x = s (k);
k = (unsigned long long) x; k = (unsigned long long) x;
#ifdef __SPU__
/* SPU float rounds towards zero. */
if (k != 0x8234500000000000ULL)
abort ();
#else
if (k != 0x8234510000000000ULL) if (k != 0x8234510000000000ULL)
abort (); abort ();
#endif
exit (0); exit (0);
} }
......
/* Test for hexadecimal float rounding: bug 21720. */ /* Test for hexadecimal float rounding: bug 21720. */
/* { dg-do link } */ /* { dg-do link } */
/* { dg-options "-O -std=gnu99" } */ /* { dg-options "-O -std=gnu99" } */
/* { dg-skip-if "SPU float rounds towards zero" { spu-*-* } } */
#include <float.h> #include <float.h>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
in number. */ in number. */
/* { dg-do link } */ /* { dg-do link } */
/* { dg-options "-O -std=gnu99" } */ /* { dg-options "-O -std=gnu99" } */
/* { dg-skip-if "SPU float rounds towards zero" { spu-*-* } } */
#include <float.h> #include <float.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment