diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b76daafe4aa..a706e78f8c3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2003-03-27 Richard Henderson + + * real.h (struct real_value): Add signalling. + (EXP_BITS): Decrement. + * real.c (get_canonical_qnan): Don't set MSB-1. + (get_canonical_snan): Likewise. Set signalling. + (real_identical): Compare signalling. + (round_for_format): Remove force-one-bit on code. + (real_nan): Likewise. Set signalling. + (encode_ieee_single): Add force-one-bit code; honor signalling. + (encode_ieee_double, encode_ieee_extended, encode_ieee_quad): Likewise. + (decode_ieee_single): Set signalling. + (decode_ieee_double, decode_ieee_extended, decode_ieee_quad): Likewise. + 2003-03-27 Olivier Hainque PR ada/9953 diff --git a/gcc/real.c b/gcc/real.c index 1e70bf7d4d9..f6074f99639 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -158,7 +158,6 @@ get_canonical_qnan (r, sign) memset (r, 0, sizeof (*r)); r->class = rvc_nan; r->sign = sign; - r->sig[SIGSZ-1] = SIG_MSB >> 1; } static inline void @@ -169,7 +168,7 @@ get_canonical_snan (r, sign) memset (r, 0, sizeof (*r)); r->class = rvc_nan; r->sign = sign; - r->sig[SIGSZ-1] = SIG_MSB >> 2; + r->signalling = 1; } static inline void @@ -1235,6 +1234,8 @@ real_identical (a, b) return false; /* FALLTHRU */ case rvc_nan: + if (a->signalling != b->signalling) + return false; for (i = 0; i < SIGSZ; ++i) if (a->sig[i] != b->sig[i]) return false; @@ -2249,23 +2250,7 @@ real_nan (r, str, quiet, mode) r->sig[SIGSZ-1] &= ~SIG_MSB; /* Force quiet or signalling NaN. */ - if (quiet) - r->sig[SIGSZ-1] |= SIG_MSB >> 1; - else - r->sig[SIGSZ-1] &= ~(SIG_MSB >> 1); - - /* Force at least one bit of the significand set. */ - for (d = 0; d < SIGSZ; ++d) - if (r->sig[d]) - break; - if (d == SIGSZ) - r->sig[SIGSZ-1] |= SIG_MSB >> 2; - - /* Our intermediate format forces QNaNs to have MSB-1 set. - If the target format has QNaNs with the top bit unset, - mirror the output routines and invert the top two bits. */ - if (!fmt->qnan_msb_set) - r->sig[SIGSZ-1] ^= (SIG_MSB >> 1) | (SIG_MSB >> 2); + r->signalling = !quiet; } return true; @@ -2325,14 +2310,6 @@ round_for_format (fmt, r) case rvc_nan: clear_significand_below (r, np2); - - /* If we've cleared the entire significand, we need one bit - set for this to continue to be a NaN. */ - for (i = 0; i < SIGSZ; ++i) - if (r->sig[i]) - break; - if (i == SIGSZ) - r->sig[SIGSZ-1] = SIG_MSB >> 2; return; case rvc_normal: @@ -2642,10 +2619,15 @@ encode_ieee_single (fmt, buf, r) case rvc_nan: if (fmt->has_nans) { + if (r->signalling == fmt->qnan_msb_set) + sig &= ~(1 << 22); + else + sig |= 1 << 22; + if (sig == 0) + sig = 1 << 21; + image |= 255 << 23; image |= sig; - if (!fmt->qnan_msb_set) - image ^= 1 << 23 | 1 << 22; } else image |= 0x7fffffff; @@ -2703,8 +2685,7 @@ decode_ieee_single (fmt, r, buf) { r->class = rvc_nan; r->sign = sign; - if (!fmt->qnan_msb_set) - image ^= (SIG_MSB >> 1 | SIG_MSB >> 2); + r->signalling = ((image >> 22) & 1) ^ fmt->qnan_msb_set; r->sig[SIGSZ-1] = image; } else @@ -2791,10 +2772,15 @@ encode_ieee_double (fmt, buf, r) case rvc_nan: if (fmt->has_nans) { + if (r->signalling == fmt->qnan_msb_set) + sig_hi &= ~(1 << 19); + else + sig_hi |= 1 << 19; + if (sig_hi == 0 && sig_lo == 0) + sig_hi = 1 << 18; + image_hi |= 2047 << 20; image_hi |= sig_hi; - if (!fmt->qnan_msb_set) - image_hi ^= 1 << 19 | 1 << 18; image_lo = sig_lo; } else @@ -2884,6 +2870,7 @@ decode_ieee_double (fmt, r, buf) { r->class = rvc_nan; r->sign = sign; + r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set; if (HOST_BITS_PER_LONG == 32) { r->sig[SIGSZ-1] = image_hi; @@ -2891,9 +2878,6 @@ decode_ieee_double (fmt, r, buf) } else r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo; - - if (!fmt->qnan_msb_set) - r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2); } else { @@ -2999,8 +2983,12 @@ encode_ieee_extended (fmt, buf, r) sig_hi = sig_lo >> 31 >> 1; sig_lo &= 0xffffffff; } - if (!fmt->qnan_msb_set) - sig_hi ^= 1 << 30 | 1 << 29; + if (r->signalling == fmt->qnan_msb_set) + sig_hi &= ~(1 << 30); + else + sig_hi |= 1 << 30; + if ((sig_hi & 0x7fffffff) == 0 && sig_lo == 0) + sig_hi = 1 << 29; /* Intel requires the explicit integer bit to be set, otherwise it considers the value a "pseudo-nan". Motorola docs say it @@ -3131,6 +3119,7 @@ decode_ieee_extended (fmt, r, buf) { r->class = rvc_nan; r->sign = sign; + r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set; if (HOST_BITS_PER_LONG == 32) { r->sig[SIGSZ-1] = sig_hi; @@ -3138,9 +3127,6 @@ decode_ieee_extended (fmt, r, buf) } else r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo; - - if (!fmt->qnan_msb_set) - r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2); } else { @@ -3395,9 +3381,12 @@ encode_ieee_quad (fmt, buf, r) image0 &= 0xffffffff; image2 &= 0xffffffff; } - - if (!fmt->qnan_msb_set) - image3 ^= 1 << 15 | 1 << 14; + if (r->signalling == fmt->qnan_msb_set) + image3 &= ~0x8000; + else + image3 |= 0x8000; + if (((image3 & 0xffff) | image2 | image1 | image0) == 0) + image3 |= 0x4000; } else { @@ -3522,6 +3511,7 @@ decode_ieee_quad (fmt, r, buf) { r->class = rvc_nan; r->sign = sign; + r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set; if (HOST_BITS_PER_LONG == 32) { @@ -3536,9 +3526,6 @@ decode_ieee_quad (fmt, r, buf) r->sig[1] = (image3 << 31 << 1) | image2; } lshift_significand (r, r, SIGNIFICAND_BITS - 113); - - if (!fmt->qnan_msb_set) - r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2); } else { diff --git a/gcc/real.h b/gcc/real.h index 00551065555..d16231acae8 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -35,7 +35,7 @@ enum real_value_class { }; #define SIGNIFICAND_BITS (128 + HOST_BITS_PER_LONG) -#define EXP_BITS (32 - 3) +#define EXP_BITS (32 - 4) #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)) @@ -44,6 +44,7 @@ struct real_value GTY(()) { ENUM_BITFIELD (real_value_class) class : 2; unsigned int sign : 1; + unsigned int signalling : 1; signed int exp : EXP_BITS; unsigned long sig[SIGSZ]; };