This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[middle-end, ColdFire 28/63] Change the canonical NaN representation
The NaNs generated by __builtin_nan() have a different significand to
the ones created by the ColdFire FPU. __builtin_nan() sets the msb
(to indicate a quiet NaN) and clears the rest, whereas the FPU sets
every bit.
MIPS diverges from the norm in a different way. On MIPS, quiet NaNs
have the msb clear and signalling NaNs have the msb set. However,
in a canonical NaN, all other bits of significand will be set.
So we have the following canonical significands for quiet NaNs:
Normal: 10000000....
MIPS: 01111111....
ColdFire: 11111111....
The problem is that both of the MIPS divergences (the inverted
sense of the msb, and canonical form of the lsbs) are controlled
by a single real_format flag. This patch splits it into two and
creates new real_formats for ColdFire. It fixes the ieee/copysign
test.
Note that the new formats are only chosen when using the ColdFire FPU.
We still want to use normal NaNs for soft float, at least until the
ColdFire libm libraries use the FPU encoding (if that ever happens).
The 68881 uses the same NaN encoding as ColdFire. I don't know if
we want to do the same thing there or not; Andreas didn't seem too
keen when I mentioned the problem in a glibc context.
Richard
gcc/
* real.h (real_format): Add a canonical_nan_lsbs_set field.
(coldfire_single_format): Declare.
(coldfire_double_format): Likewise.
* real.c (encode_ieee_single): Use canonical_nan_lsbs_set instead
of qnan_msb_set to determine the lower bits of a canonical
NaN significand.
(encode_ieee_double): Likewise.
(encode_ieee_quad): Likewise.
(ieee_single_format): Initialize canonical_nan_lsbs_set.
(mips_single_format): Likewise.
(ieee_double_format): Likewise.
(mips_double_format): Likewise.
(ieee_extended_motorola_format): Likewise.
(ieee_extended_intel_96_format): Likewise.
(ieee_extended_intel_128_format): Likewise.
(ieee_extended_intel_96_round_53_format): Likewise.
(ibm_extended_format): Likewise.
(mips_extended_format): Likewise.
(ieee_quad_format): Likewise.
(mips_quad_format): Likewise.
(vax_f_format): Likewise.
(vax_d_format): Likewise.
(vax_g_format): Likewise.
(i370_single_format): Likewise.
(i370_double_format): Likewise.
(decimal_single_format): Likewise.
(decimal_double_format): Likewise.
(decimal_quad_format): Likewise.
(c4x_single_format): Likewise.
(c4x_extended_format): Likewise.
(real_internal_format): Likewise.
(coldfire_single_format): New real_format.
(coldfire_double_format): Likewise.
* config/pdp11/pdp11.c (pdp11_f_format): Initialize
canonical_nan_lsbs_set.
(pdp11_d_format): Likewise.
* config/m68k/m68k.c (override_options): Override REAL_FORMAT_MODE
if TARGET_COLDFIRE_CPU.
Index: gcc/real.h
===================================================================
--- gcc/real.h 2007-01-09 13:18:12.000000000 +0000
+++ gcc/real.h 2007-01-09 15:02:10.000000000 +0000
@@ -155,6 +155,7 @@ struct real_format
bool has_denorm;
bool has_signed_zero;
bool qnan_msb_set;
+ bool canonical_nan_lsbs_set;
};
@@ -255,8 +256,10 @@ extern unsigned int real_hash (const REA
/* Target formats defined in real.c. */
extern const struct real_format ieee_single_format;
extern const struct real_format mips_single_format;
+extern const struct real_format coldfire_single_format;
extern const struct real_format ieee_double_format;
extern const struct real_format mips_double_format;
+extern const struct real_format coldfire_double_format;
extern const struct real_format ieee_extended_motorola_format;
extern const struct real_format ieee_extended_intel_96_format;
extern const struct real_format ieee_extended_intel_96_round_53_format;
Index: gcc/real.c
===================================================================
--- gcc/real.c 2007-01-09 13:18:12.000000000 +0000
+++ gcc/real.c 2007-01-09 15:02:10.000000000 +0000
@@ -2681,18 +2681,12 @@ encode_ieee_single (const struct real_fo
if (fmt->has_nans)
{
if (r->canonical)
- sig = 0;
+ sig = (fmt->canonical_nan_lsbs_set ? (1 << 22) - 1 : 0);
if (r->signalling == fmt->qnan_msb_set)
sig &= ~(1 << 22);
else
sig |= 1 << 22;
- /* We overload qnan_msb_set here: it's only clear for
- mips_ieee_single, which wants all mantissa bits but the
- quiet/signalling one set in canonical NaNs (at least
- Quiet ones). */
- if (r->canonical && !fmt->qnan_msb_set)
- sig |= (1 << 22) - 1;
- else if (sig == 0)
+ if (sig == 0)
sig = 1 << 21;
image |= 255 << 23;
@@ -2787,7 +2781,8 @@ const struct real_format ieee_single_for
true,
true,
true,
- true
+ true,
+ false
};
const struct real_format mips_single_format =
@@ -2806,9 +2801,29 @@ const struct real_format mips_single_for
true,
true,
true,
- false
+ false,
+ true
};
+const struct real_format coldfire_single_format =
+ {
+ encode_ieee_single,
+ decode_ieee_single,
+ 2,
+ 1,
+ 24,
+ 24,
+ -125,
+ 128,
+ 31,
+ 31,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
/* IEEE double-precision format. */
@@ -2860,21 +2875,23 @@ encode_ieee_double (const struct real_fo
if (fmt->has_nans)
{
if (r->canonical)
- sig_hi = sig_lo = 0;
+ {
+ if (fmt->canonical_nan_lsbs_set)
+ {
+ sig_hi = (1 << 19) - 1;
+ sig_lo = 0xffffffff;
+ }
+ else
+ {
+ sig_hi = 0;
+ sig_lo = 0;
+ }
+ }
if (r->signalling == fmt->qnan_msb_set)
sig_hi &= ~(1 << 19);
else
sig_hi |= 1 << 19;
- /* We overload qnan_msb_set here: it's only clear for
- mips_ieee_single, which wants all mantissa bits but the
- quiet/signalling one set in canonical NaNs (at least
- Quiet ones). */
- if (r->canonical && !fmt->qnan_msb_set)
- {
- sig_hi |= (1 << 19) - 1;
- sig_lo = 0xffffffff;
- }
- else if (sig_hi == 0 && sig_lo == 0)
+ if (sig_hi == 0 && sig_lo == 0)
sig_hi = 1 << 18;
image_hi |= 2047 << 20;
@@ -3012,7 +3029,8 @@ const struct real_format ieee_double_for
true,
true,
true,
- true
+ true,
+ false
};
const struct real_format mips_double_format =
@@ -3031,9 +3049,29 @@ const struct real_format mips_double_for
true,
true,
true,
- false
+ false,
+ true
};
+const struct real_format coldfire_double_format =
+ {
+ encode_ieee_double,
+ decode_ieee_double,
+ 2,
+ 1,
+ 53,
+ 53,
+ -1021,
+ 1024,
+ 63,
+ 63,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
/* IEEE extended real format. This comes in three flavors: Intel's as
a 12 byte image, Intel's as a 16 byte image, and Motorola's. Intel
@@ -3361,7 +3399,8 @@ const struct real_format ieee_extended_m
true,
true,
true,
- true
+ true,
+ false
};
const struct real_format ieee_extended_intel_96_format =
@@ -3380,7 +3419,8 @@ const struct real_format ieee_extended_i
true,
true,
true,
- true
+ true,
+ false
};
const struct real_format ieee_extended_intel_128_format =
@@ -3399,7 +3439,8 @@ const struct real_format ieee_extended_i
true,
true,
true,
- true
+ true,
+ false
};
/* The following caters to i386 systems that set the rounding precision
@@ -3420,7 +3461,8 @@ const struct real_format ieee_extended_i
true,
true,
true,
- true
+ true,
+ false
};
/* IBM 128-bit extended precision format: a pair of IEEE double precision
@@ -3506,7 +3548,8 @@ const struct real_format ibm_extended_fo
true,
true,
true,
- true
+ true,
+ false
};
const struct real_format mips_extended_format =
@@ -3525,7 +3568,8 @@ const struct real_format mips_extended_f
true,
true,
true,
- false
+ false,
+ true
};
@@ -3575,8 +3619,11 @@ encode_ieee_quad (const struct real_form
if (r->canonical)
{
- /* Don't use bits from the significand. The
- initialization above is right. */
+ if (fmt->canonical_nan_lsbs_set)
+ {
+ image3 |= 0x7fff;
+ image2 = image1 = image0 = 0xffffffff;
+ }
}
else if (HOST_BITS_PER_LONG == 32)
{
@@ -3598,16 +3645,7 @@ encode_ieee_quad (const struct real_form
image3 &= ~0x8000;
else
image3 |= 0x8000;
- /* We overload qnan_msb_set here: it's only clear for
- mips_ieee_single, which wants all mantissa bits but the
- quiet/signalling one set in canonical NaNs (at least
- Quiet ones). */
- if (r->canonical && !fmt->qnan_msb_set)
- {
- image3 |= 0x7fff;
- image2 = image1 = image0 = 0xffffffff;
- }
- else if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
+ if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
image3 |= 0x4000;
}
else
@@ -3792,7 +3830,8 @@ const struct real_format ieee_quad_forma
true,
true,
true,
- true
+ true,
+ false
};
const struct real_format mips_quad_format =
@@ -3811,7 +3850,8 @@ const struct real_format mips_quad_forma
true,
true,
true,
- false
+ false,
+ true
};
/* Descriptions of VAX floating point formats can be found beginning at
@@ -4109,6 +4149,7 @@ const struct real_format vax_f_format =
false,
false,
false,
+ false,
false
};
@@ -4128,6 +4169,7 @@ const struct real_format vax_d_format =
false,
false,
false,
+ false,
false
};
@@ -4147,6 +4189,7 @@ const struct real_format vax_g_format =
false,
false,
false,
+ false,
false
};
@@ -4323,6 +4366,7 @@ const struct real_format i370_single_for
false,
false, /* ??? The encoding does allow for "unnormals". */
false, /* ??? The encoding does allow for "unnormals". */
+ false,
false
};
@@ -4342,6 +4386,7 @@ const struct real_format i370_double_for
false,
false, /* ??? The encoding does allow for "unnormals". */
false, /* ??? The encoding does allow for "unnormals". */
+ false,
false
};
@@ -4416,7 +4461,8 @@ const struct real_format decimal_single_
true,
true,
true,
- true
+ true,
+ false
};
/* Double precision decimal floating point (IEEE 754R). */
@@ -4436,7 +4482,8 @@ const struct real_format decimal_double_
true,
true,
true,
- true
+ true,
+ false
};
/* Quad precision decimal floating point (IEEE 754R). */
@@ -4456,7 +4503,8 @@ const struct real_format decimal_quad_fo
true,
true,
true,
- true
+ true,
+ false
};
/* The "twos-complement" c4x format is officially defined as
@@ -4665,6 +4713,7 @@ const struct real_format c4x_single_form
false,
false,
false,
+ false,
false
};
@@ -4684,6 +4733,7 @@ const struct real_format c4x_extended_fo
false,
false,
false,
+ false,
false
};
@@ -4728,7 +4778,8 @@ const struct real_format real_internal_f
true,
false,
true,
- true
+ true,
+ false
};
/* Calculate the square root of X in mode MODE, and store the result
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c 2007-01-09 13:18:12.000000000 +0000
+++ gcc/config/pdp11/pdp11.c 2007-01-09 15:02:10.000000000 +0000
@@ -78,6 +78,7 @@ const struct real_format pdp11_f_format
false,
false,
false,
+ false,
false
};
@@ -96,6 +97,7 @@ const struct real_format pdp11_d_format
false,
false,
false,
+ false,
false
};
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c 2007-01-09 15:02:09.000000000 +0000
+++ gcc/config/m68k/m68k.c 2007-01-09 15:02:10.000000000 +0000
@@ -536,6 +536,12 @@ override_options (void)
: (m68k_cpu_flags & FL_COLDFIRE) != 0 ? FPUTYPE_COLDFIRE
: FPUTYPE_68881);
+ if (TARGET_COLDFIRE_FPU)
+ {
+ REAL_MODE_FORMAT (SFmode) = &coldfire_single_format;
+ REAL_MODE_FORMAT (DFmode) = &coldfire_double_format;
+ }
+
/* Sanity check to ensure that msep-data and mid-sahred-library are not
* both specified together. Doing so simply doesn't make sense.
*/