This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: mips SNaN/QNaN is swapped
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: cgd at broadcom dot com, gcc-patches at gcc dot gnu dot org
- Date: 01 Apr 2003 11:13:46 -0300
- Subject: Re: mips SNaN/QNaN is swapped
- Organization: GCC Team, Red Hat
- References: <orr88we85f.fsf@free.redhat.lsd.ic.unicamp.br><orisu8e2f3.fsf@free.redhat.lsd.ic.unicamp.br><20030325034356.GE15567@redhat.com><orsmtbaido.fsf@free.redhat.lsd.ic.unicamp.br><20030327012642.GA29837@redhat.com><orn0jhfpyh.fsf@free.redhat.lsd.ic.unicamp.br><20030327093138.GC16558@redhat.com><mailpost.1048757677.18699@news-sj1-1> <yov5r88sbvvu.fsf@broadcom.com><or4r5iq4ze.fsf@free.redhat.lsd.ic.unicamp.br><20030401053433.GA25974@redhat.com>
On Apr 1, 2003, Richard Henderson <rth at redhat dot com> wrote:
> You've missed the needed change to real_identical. In this case,
> if canonical, you should ignore the significand. This implies a
> needed change to real_hash as well.
> And further implies that canonical should ignore the existing value
> of sig.
This revised patch corrects the two problems above. Ok to install if
it bootstraps on athlon-pc-linux-gnu and generates the correct bit
patterns on native, x-mips64-linux and x-mips-sgi-irix6.5?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva at redhat dot com>
* real.h (EXP_BITS): Make room for...
(struct real_value): ... added canonical bit.
(struct real_format): Added pnan.
(mips_single_format, mips_double_format, mips_extended_format,
mips_quad_format): New.
* real.c: Copy p to pnan in all formats.
(get_canonical_qnan, get_canonical_snan): Set canonical bit.
(real_nan): Use pnan to compute significand's shift.
(real_identical): Disregard significand in canonical
NaNs.
(real_hash): Likewise. Take signalling into account.
(encode_ieee_single, encode_ieee_double, encode_ieee_quad):
Disregard significand bits in canonical NaNs. Set all bits of
canonical NaN if !qnan_msb_set.
(encode_ibm_extended, decode_ibm_extended): Likewise. Use
qnan_msb_set to tell the base double format.
(ibm_extended_format): Use 53 as pnan.
(mips_single_format, mips_double_format, mips_extended_format,
mips_quad_format): Copied from the corresponding ieee/ibm
formats, with qnan_msb_set false.
* config/mips/iris6.h (MIPS_TFMODE_FORMAT): Use mips_extended_format.
* config/mips/linux64.h (MIPS_TFMODE_FORMAT): Use mips_quad_format.
* config/mips/mips.c (override_options): Use mips_single_format
and mips_double_format. Default TFmode to mips_quad_format.
* config/mips/t-linux64 (tp-bit.c): Define QUIET_NAN_NEGATED.
* config/mips/t-irix6: Likewise.
* config/mips/t-mips (fp-bit.c, dp-bit.c): Likewise.
* config/fp-bit.c (pack_d, unpack_d): Obey it.
Index: gcc/real.c
===================================================================
RCS file: /cvs/uberbaum/gcc/real.c,v
retrieving revision 1.114
diff -u -p -r1.114 real.c
--- gcc/real.c 31 Mar 2003 21:02:10 -0000 1.114
+++ gcc/real.c 1 Apr 2003 14:10:41 -0000
@@ -158,6 +158,7 @@ get_canonical_qnan (r, sign)
memset (r, 0, sizeof (*r));
r->class = rvc_nan;
r->sign = sign;
+ r->canonical = 1;
}
static inline void
@@ -169,6 +170,7 @@ get_canonical_snan (r, sign)
r->class = rvc_nan;
r->sign = sign;
r->signalling = 1;
+ r->canonical = 1;
}
static inline void
@@ -1212,7 +1214,7 @@ real_isnegzero (r)
/* Compare two floating-point objects for bitwise identity. */
-extern bool
+bool
real_identical (a, b)
const REAL_VALUE_TYPE *a, *b;
{
@@ -1237,6 +1239,9 @@ real_identical (a, b)
case rvc_nan:
if (a->signalling != b->signalling)
return false;
+ /* The significand is ignored for canonical NaNs. */
+ if (a->canonical || b->canonical)
+ return a->canonical == b->canonical;
break;
default:
@@ -2246,7 +2251,7 @@ real_nan (r, str, quiet, mode)
/* Shift the significand into place such that the bits
are in the most significant bits for the format. */
- lshift_significand (r, r, SIGNIFICAND_BITS - fmt->p);
+ lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan);
/* Our MSB is always unset for NaNs. */
r->sig[SIGSZ-1] &= ~SIG_MSB;
@@ -2569,6 +2574,10 @@ real_hash (r)
/* FALLTHRU */
case rvc_nan:
+ if (r->signalling)
+ h ^= (unsigned int)-1;
+ if (r->canonical)
+ break;
if (sizeof(unsigned long) > sizeof(unsigned int))
for (i = 0; i < SIGSZ; ++i)
{
@@ -2621,11 +2630,19 @@ encode_ieee_single (fmt, buf, r)
case rvc_nan:
if (fmt->has_nans)
{
+ if (r->canonical)
+ sig = 0;
if (r->signalling == fmt->qnan_msb_set)
sig &= ~(1 << 22);
else
sig |= 1 << 22;
- if (sig == 0)
+ /* 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)
sig = 1 << 21;
image |= 255 << 23;
@@ -2712,6 +2729,7 @@ const struct real_format ieee_single_for
2,
1,
24,
+ 24,
-125,
128,
31,
@@ -2722,6 +2740,24 @@ const struct real_format ieee_single_for
true
};
+const struct real_format mips_single_format =
+ {
+ encode_ieee_single,
+ decode_ieee_single,
+ 2,
+ 1,
+ 24,
+ 24,
+ -125,
+ 128,
+ 31,
+ true,
+ true,
+ true,
+ true,
+ false
+ };
+
/* IEEE double-precision format. */
@@ -2774,11 +2810,22 @@ encode_ieee_double (fmt, buf, r)
case rvc_nan:
if (fmt->has_nans)
{
+ if (r->canonical)
+ sig_hi = sig_lo = 0;
if (r->signalling == fmt->qnan_msb_set)
sig_hi &= ~(1 << 19);
else
sig_hi |= 1 << 19;
- if (sig_hi == 0 && sig_lo == 0)
+ /* 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)
sig_hi = 1 << 18;
image_hi |= 2047 << 20;
@@ -2909,6 +2956,7 @@ const struct real_format ieee_double_for
2,
1,
53,
+ 53,
-1021,
1024,
63,
@@ -2919,6 +2967,24 @@ const struct real_format ieee_double_for
true
};
+const struct real_format mips_double_format =
+ {
+ encode_ieee_double,
+ decode_ieee_double,
+ 2,
+ 1,
+ 53,
+ 53,
+ -1021,
+ 1024,
+ 63,
+ true,
+ true,
+ true,
+ true,
+ false
+ };
+
/* IEEE extended double precision format. This comes in three
flavours: Intel's as a 12 byte image, Intel's as a 16 byte image,
@@ -3167,6 +3233,7 @@ const struct real_format ieee_extended_m
2,
1,
64,
+ 64,
-16382,
16384,
95,
@@ -3184,6 +3251,7 @@ const struct real_format ieee_extended_i
2,
1,
64,
+ 64,
-16381,
16384,
79,
@@ -3201,6 +3269,7 @@ const struct real_format ieee_extended_i
2,
1,
64,
+ 64,
-16381,
16384,
79,
@@ -3228,11 +3297,14 @@ static void decode_ibm_extended PARAMS (
static void
encode_ibm_extended (fmt, buf, r)
- const struct real_format *fmt ATTRIBUTE_UNUSED;
+ const struct real_format *fmt;
long *buf;
const REAL_VALUE_TYPE *r;
{
REAL_VALUE_TYPE u, v;
+ const struct real_format *base_fmt;
+
+ base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
switch (r->class)
{
@@ -3247,7 +3319,7 @@ encode_ibm_extended (fmt, buf, r)
case rvc_inf:
case rvc_nan:
/* Both doubles set to Inf / NaN. */
- encode_ieee_double (&ieee_double_format, &buf[0], r);
+ encode_ieee_double (base_fmt, &buf[0], r);
buf[2] = buf[0];
buf[3] = buf[1];
return;
@@ -3270,13 +3342,13 @@ encode_ibm_extended (fmt, buf, r)
{
/* v = remainder containing additional 53 bits of significand. */
do_add (&v, r, &u, 1);
- round_for_format (&ieee_double_format, &v);
+ round_for_format (base_fmt, &v);
}
- round_for_format (&ieee_double_format, &u);
+ round_for_format (base_fmt, &u);
- encode_ieee_double (&ieee_double_format, &buf[0], &u);
- encode_ieee_double (&ieee_double_format, &buf[2], &v);
+ encode_ieee_double (base_fmt, &buf[0], &u);
+ encode_ieee_double (base_fmt, &buf[2], &v);
break;
default:
@@ -3291,12 +3363,14 @@ decode_ibm_extended (fmt, r, buf)
const long *buf;
{
REAL_VALUE_TYPE u, v;
+ const struct real_format *base_fmt;
- decode_ieee_double (&ieee_double_format, &u, &buf[0]);
+ base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
+ decode_ieee_double (base_fmt, &u, &buf[0]);
if (u.class != rvc_zero && u.class != rvc_inf && u.class != rvc_nan)
{
- decode_ieee_double (&ieee_double_format, &v, &buf[2]);
+ decode_ieee_double (base_fmt, &v, &buf[2]);
do_add (r, &u, &v, 0);
}
else
@@ -3310,6 +3384,7 @@ const struct real_format ibm_extended_fo
2,
1,
53 + 53,
+ 53,
-1021 + 53,
1024,
-1,
@@ -3320,6 +3395,24 @@ const struct real_format ibm_extended_fo
true
};
+const struct real_format mips_extended_format =
+ {
+ encode_ibm_extended,
+ decode_ibm_extended,
+ 2,
+ 1,
+ 53 + 53,
+ 53,
+ -1021 + 53,
+ 1024,
+ -1,
+ true,
+ true,
+ true,
+ true,
+ false
+ };
+
/* IEEE quad precision format. */
@@ -3367,7 +3460,12 @@ encode_ieee_quad (fmt, buf, r)
{
image3 |= 32767 << 16;
- if (HOST_BITS_PER_LONG == 32)
+ if (r->canonical)
+ {
+ /* Don't use bits from the significand. The
+ initialization above is right. */
+ }
+ else if (HOST_BITS_PER_LONG == 32)
{
image0 = u.sig[0];
image1 = u.sig[1];
@@ -3387,7 +3485,16 @@ encode_ieee_quad (fmt, buf, r)
image3 &= ~0x8000;
else
image3 |= 0x8000;
- if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
+ /* 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)
image3 |= 0x4000;
}
else
@@ -3565,6 +3672,7 @@ const struct real_format ieee_quad_forma
2,
1,
113,
+ 113,
-16381,
16384,
127,
@@ -3574,6 +3682,24 @@ const struct real_format ieee_quad_forma
true,
true
};
+
+const struct real_format mips_quad_format =
+ {
+ encode_ieee_quad,
+ decode_ieee_quad,
+ 2,
+ 1,
+ 113,
+ 113,
+ -16381,
+ 16384,
+ 127,
+ true,
+ true,
+ true,
+ true,
+ false
+ };
/* Descriptions of VAX floating point formats can be found beginning at
@@ -3873,6 +3999,7 @@ const struct real_format vax_f_format =
2,
1,
24,
+ 24,
-127,
127,
15,
@@ -3890,6 +4017,7 @@ const struct real_format vax_d_format =
2,
1,
56,
+ 56,
-127,
127,
15,
@@ -3907,6 +4035,7 @@ const struct real_format vax_g_format =
2,
1,
53,
+ 53,
-1023,
1023,
15,
@@ -4089,6 +4218,7 @@ const struct real_format i370_single_for
16,
4,
6,
+ 6,
-64,
63,
31,
@@ -4106,6 +4236,7 @@ const struct real_format i370_double_for
16,
4,
14,
+ 14,
-64,
63,
63,
@@ -4321,6 +4452,7 @@ const struct real_format c4x_single_form
2,
1,
24,
+ 24,
-126,
128,
-1,
@@ -4338,6 +4470,7 @@ const struct real_format c4x_extended_fo
2,
1,
32,
+ 32,
-126,
128,
-1,
@@ -4383,6 +4516,7 @@ const struct real_format real_internal_f
decode_internal,
2,
1,
+ SIGNIFICAND_BITS - 2,
SIGNIFICAND_BITS - 2,
-MAX_EXP,
MAX_EXP,
Index: gcc/real.h
===================================================================
RCS file: /cvs/uberbaum/gcc/real.h,v
retrieving revision 1.63
diff -u -p -r1.63 real.h
--- gcc/real.h 31 Mar 2003 14:30:27 -0000 1.63
+++ gcc/real.h 1 Apr 2003 14:10:42 -0000
@@ -35,7 +35,7 @@ enum real_value_class {
};
#define SIGNIFICAND_BITS (128 + HOST_BITS_PER_LONG)
-#define EXP_BITS (32 - 4)
+#define EXP_BITS (32 - 5)
#define MAX_EXP ((1 << (EXP_BITS - 1)) - 1)
#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
#define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
@@ -45,6 +45,7 @@ struct real_value GTY(())
ENUM_BITFIELD (real_value_class) class : 2;
unsigned int sign : 1;
unsigned int signalling : 1;
+ unsigned int canonical : 1;
signed int exp : EXP_BITS;
unsigned long sig[SIGSZ];
};
@@ -119,6 +120,9 @@ struct real_format
/* Size of the significand in digits of radix B. */
int p;
+ /* Size of the significant of a NaN, in digits of radix B. */
+ int pnan;
+
/* The minimum negative integer, x, such that b**(x-1) is normalized. */
int emin;
@@ -222,12 +226,16 @@ extern unsigned int real_hash PARAMS ((c
/* 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 ieee_double_format;
+extern const struct real_format mips_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_128_format;
extern const struct real_format ibm_extended_format;
+extern const struct real_format mips_extended_format;
extern const struct real_format ieee_quad_format;
+extern const struct real_format mips_quad_format;
extern const struct real_format vax_f_format;
extern const struct real_format vax_d_format;
extern const struct real_format vax_g_format;
Index: gcc/config/fp-bit.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/fp-bit.c,v
retrieving revision 1.39
diff -u -p -r1.39 fp-bit.c
--- gcc/config/fp-bit.c 26 Jan 2003 10:06:57 -0000 1.39
+++ gcc/config/fp-bit.c 1 Apr 2003 14:10:42 -0000
@@ -210,7 +210,11 @@ pack_d ( fp_number_type * src)
exp = EXPMAX;
if (src->class == CLASS_QNAN || 1)
{
+#ifdef QUIET_NAN_NEGATED
+ fraction |= QUIET_NAN - 1;
+#else
fraction |= QUIET_NAN;
+#endif
}
}
else if (isinf (src))
@@ -521,7 +525,11 @@ unpack_d (FLO_union_type * src, fp_numbe
else
{
/* Nonzero fraction, means nan */
+#ifdef QUIET_NAN_NEGATED
+ if ((fraction & QUIET_NAN) == 0)
+#else
if (fraction & QUIET_NAN)
+#endif
{
dst->class = CLASS_QNAN;
}
Index: gcc/config/mips/iris6.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/iris6.h,v
retrieving revision 1.58
diff -u -p -r1.58 iris6.h
--- gcc/config/mips/iris6.h 19 Mar 2003 18:18:36 -0000 1.58
+++ gcc/config/mips/iris6.h 1 Apr 2003 14:10:43 -0000
@@ -525,4 +525,4 @@ do { \
-_SYSTYPE_SVR4 -woff 131 \
%{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
-#define MIPS_TFMODE_FORMAT ibm_extended_format
+#define MIPS_TFMODE_FORMAT mips_extended_format
Index: gcc/config/mips/linux64.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/linux64.h,v
retrieving revision 1.2
diff -u -p -r1.2 linux64.h
--- gcc/config/mips/linux64.h 11 Mar 2003 23:31:01 -0000 1.2
+++ gcc/config/mips/linux64.h 1 Apr 2003 14:10:43 -0000
@@ -98,4 +98,4 @@ Boston, MA 02111-1307, USA. */
for long double. There's no need to override this here, since
ieee_quad_format is the default, but let's put this here to make
sure nobody thinks we just forgot to set it to something else. */
-#define MIPS_TFMODE_FORMAT ieee_quad_format
+#define MIPS_TFMODE_FORMAT mips_quad_format
Index: gcc/config/mips/mips.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/mips.c,v
retrieving revision 1.252
diff -u -p -r1.252 mips.c
--- gcc/config/mips/mips.c 19 Feb 2003 18:03:09 -0000 1.252
+++ gcc/config/mips/mips.c 1 Apr 2003 14:10:50 -0000
@@ -5714,8 +5714,12 @@ override_options ()
else
mips16 = 0;
+ real_format_for_mode[SFmode - QFmode] = &mips_single_format;
+ real_format_for_mode[DFmode - QFmode] = &mips_double_format;
#ifdef MIPS_TFMODE_FORMAT
real_format_for_mode[TFmode - QFmode] = &MIPS_TFMODE_FORMAT;
+#else
+ real_format_for_mode[TFmode - QFmode] = &mips_quad_format;
#endif
mips_print_operand_punct['?'] = 1;
Index: gcc/config/mips/t-iris6
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/t-iris6,v
retrieving revision 1.17
diff -u -p -r1.17 t-iris6
--- gcc/config/mips/t-iris6 28 Jan 2003 02:18:43 -0000 1.17
+++ gcc/config/mips/t-iris6 1 Apr 2003 14:10:50 -0000
@@ -27,6 +27,7 @@ tp-bit.c: $(srcdir)/config/fp-bit.c
echo '#ifdef __MIPSEL__' > tp-bit.c
echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
echo '#endif' >> tp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
echo '#if __LDBL_MANT_DIG__ == 106' >> tp-bit.c
echo '# define TFLOAT' >> tp-bit.c
cat $(srcdir)/config/fp-bit.c >> tp-bit.c
Index: gcc/config/mips/t-linux64
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/t-linux64,v
retrieving revision 1.1
diff -u -p -r1.1 t-linux64
--- gcc/config/mips/t-linux64 19 Jan 2003 13:04:24 -0000 1.1
+++ gcc/config/mips/t-linux64 1 Apr 2003 14:10:50 -0000
@@ -13,6 +13,7 @@ tp-bit.c: $(srcdir)/config/fp-bit.c
echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
echo '#endif' >> tp-bit.c
echo '#if __LDBL_MANT_DIG__ == 113' >> tp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
echo '# define TFLOAT' >> tp-bit.c
cat $(srcdir)/config/fp-bit.c >> tp-bit.c
echo '#endif' >> tp-bit.c
Index: gcc/config/mips/t-mips
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/t-mips,v
retrieving revision 1.5
diff -u -p -r1.5 t-mips
--- gcc/config/mips/t-mips 29 Jul 2002 22:21:41 -0000 1.5
+++ gcc/config/mips/t-mips 1 Apr 2003 14:10:50 -0000
@@ -9,6 +9,7 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#ifdef __MIPSEL__' > dp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
echo '#endif' >> dp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
fp-bit.c: $(srcdir)/config/fp-bit.c
@@ -16,4 +17,5 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#ifdef __MIPSEL__' >> fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
echo '#endif' >> fp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva at {redhat dot com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva at {lsd dot ic dot unicamp dot br, gnu.org}
Free Software Evangelist Professional serial bug killer