Commit ad59ba20 by Richard Henderson Committed by Richard Henderson

real.h (struct real_value): Add signalling.

        * 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.

From-SVN: r64935
parent 940bbb74
2003-03-27 Richard Henderson <rth@redhat.com>
* 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 <hainque@act-europe.fr> 2003-03-27 Olivier Hainque <hainque@act-europe.fr>
PR ada/9953 PR ada/9953
......
...@@ -158,7 +158,6 @@ get_canonical_qnan (r, sign) ...@@ -158,7 +158,6 @@ get_canonical_qnan (r, sign)
memset (r, 0, sizeof (*r)); memset (r, 0, sizeof (*r));
r->class = rvc_nan; r->class = rvc_nan;
r->sign = sign; r->sign = sign;
r->sig[SIGSZ-1] = SIG_MSB >> 1;
} }
static inline void static inline void
...@@ -169,7 +168,7 @@ get_canonical_snan (r, sign) ...@@ -169,7 +168,7 @@ get_canonical_snan (r, sign)
memset (r, 0, sizeof (*r)); memset (r, 0, sizeof (*r));
r->class = rvc_nan; r->class = rvc_nan;
r->sign = sign; r->sign = sign;
r->sig[SIGSZ-1] = SIG_MSB >> 2; r->signalling = 1;
} }
static inline void static inline void
...@@ -1235,6 +1234,8 @@ real_identical (a, b) ...@@ -1235,6 +1234,8 @@ real_identical (a, b)
return false; return false;
/* FALLTHRU */ /* FALLTHRU */
case rvc_nan: case rvc_nan:
if (a->signalling != b->signalling)
return false;
for (i = 0; i < SIGSZ; ++i) for (i = 0; i < SIGSZ; ++i)
if (a->sig[i] != b->sig[i]) if (a->sig[i] != b->sig[i])
return false; return false;
...@@ -2249,23 +2250,7 @@ real_nan (r, str, quiet, mode) ...@@ -2249,23 +2250,7 @@ real_nan (r, str, quiet, mode)
r->sig[SIGSZ-1] &= ~SIG_MSB; r->sig[SIGSZ-1] &= ~SIG_MSB;
/* Force quiet or signalling NaN. */ /* Force quiet or signalling NaN. */
if (quiet) r->signalling = !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);
} }
return true; return true;
...@@ -2325,14 +2310,6 @@ round_for_format (fmt, r) ...@@ -2325,14 +2310,6 @@ round_for_format (fmt, r)
case rvc_nan: case rvc_nan:
clear_significand_below (r, np2); 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; return;
case rvc_normal: case rvc_normal:
...@@ -2642,10 +2619,15 @@ encode_ieee_single (fmt, buf, r) ...@@ -2642,10 +2619,15 @@ encode_ieee_single (fmt, buf, r)
case rvc_nan: case rvc_nan:
if (fmt->has_nans) 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 |= 255 << 23;
image |= sig; image |= sig;
if (!fmt->qnan_msb_set)
image ^= 1 << 23 | 1 << 22;
} }
else else
image |= 0x7fffffff; image |= 0x7fffffff;
...@@ -2703,8 +2685,7 @@ decode_ieee_single (fmt, r, buf) ...@@ -2703,8 +2685,7 @@ decode_ieee_single (fmt, r, buf)
{ {
r->class = rvc_nan; r->class = rvc_nan;
r->sign = sign; r->sign = sign;
if (!fmt->qnan_msb_set) r->signalling = ((image >> 22) & 1) ^ fmt->qnan_msb_set;
image ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
r->sig[SIGSZ-1] = image; r->sig[SIGSZ-1] = image;
} }
else else
...@@ -2791,10 +2772,15 @@ encode_ieee_double (fmt, buf, r) ...@@ -2791,10 +2772,15 @@ encode_ieee_double (fmt, buf, r)
case rvc_nan: case rvc_nan:
if (fmt->has_nans) 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 |= 2047 << 20;
image_hi |= sig_hi; image_hi |= sig_hi;
if (!fmt->qnan_msb_set)
image_hi ^= 1 << 19 | 1 << 18;
image_lo = sig_lo; image_lo = sig_lo;
} }
else else
...@@ -2884,6 +2870,7 @@ decode_ieee_double (fmt, r, buf) ...@@ -2884,6 +2870,7 @@ decode_ieee_double (fmt, r, buf)
{ {
r->class = rvc_nan; r->class = rvc_nan;
r->sign = sign; r->sign = sign;
r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set;
if (HOST_BITS_PER_LONG == 32) if (HOST_BITS_PER_LONG == 32)
{ {
r->sig[SIGSZ-1] = image_hi; r->sig[SIGSZ-1] = image_hi;
...@@ -2891,9 +2878,6 @@ decode_ieee_double (fmt, r, buf) ...@@ -2891,9 +2878,6 @@ decode_ieee_double (fmt, r, buf)
} }
else else
r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo; 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 else
{ {
...@@ -2999,8 +2983,12 @@ encode_ieee_extended (fmt, buf, r) ...@@ -2999,8 +2983,12 @@ encode_ieee_extended (fmt, buf, r)
sig_hi = sig_lo >> 31 >> 1; sig_hi = sig_lo >> 31 >> 1;
sig_lo &= 0xffffffff; sig_lo &= 0xffffffff;
} }
if (!fmt->qnan_msb_set) if (r->signalling == fmt->qnan_msb_set)
sig_hi ^= 1 << 30 | 1 << 29; 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 /* Intel requires the explicit integer bit to be set, otherwise
it considers the value a "pseudo-nan". Motorola docs say it it considers the value a "pseudo-nan". Motorola docs say it
...@@ -3131,6 +3119,7 @@ decode_ieee_extended (fmt, r, buf) ...@@ -3131,6 +3119,7 @@ decode_ieee_extended (fmt, r, buf)
{ {
r->class = rvc_nan; r->class = rvc_nan;
r->sign = sign; r->sign = sign;
r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set;
if (HOST_BITS_PER_LONG == 32) if (HOST_BITS_PER_LONG == 32)
{ {
r->sig[SIGSZ-1] = sig_hi; r->sig[SIGSZ-1] = sig_hi;
...@@ -3138,9 +3127,6 @@ decode_ieee_extended (fmt, r, buf) ...@@ -3138,9 +3127,6 @@ decode_ieee_extended (fmt, r, buf)
} }
else else
r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo; 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 else
{ {
...@@ -3395,9 +3381,12 @@ encode_ieee_quad (fmt, buf, r) ...@@ -3395,9 +3381,12 @@ encode_ieee_quad (fmt, buf, r)
image0 &= 0xffffffff; image0 &= 0xffffffff;
image2 &= 0xffffffff; image2 &= 0xffffffff;
} }
if (r->signalling == fmt->qnan_msb_set)
if (!fmt->qnan_msb_set) image3 &= ~0x8000;
image3 ^= 1 << 15 | 1 << 14; else
image3 |= 0x8000;
if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
image3 |= 0x4000;
} }
else else
{ {
...@@ -3522,6 +3511,7 @@ decode_ieee_quad (fmt, r, buf) ...@@ -3522,6 +3511,7 @@ decode_ieee_quad (fmt, r, buf)
{ {
r->class = rvc_nan; r->class = rvc_nan;
r->sign = sign; r->sign = sign;
r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set;
if (HOST_BITS_PER_LONG == 32) if (HOST_BITS_PER_LONG == 32)
{ {
...@@ -3536,9 +3526,6 @@ decode_ieee_quad (fmt, r, buf) ...@@ -3536,9 +3526,6 @@ decode_ieee_quad (fmt, r, buf)
r->sig[1] = (image3 << 31 << 1) | image2; r->sig[1] = (image3 << 31 << 1) | image2;
} }
lshift_significand (r, r, SIGNIFICAND_BITS - 113); lshift_significand (r, r, SIGNIFICAND_BITS - 113);
if (!fmt->qnan_msb_set)
r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
} }
else else
{ {
......
...@@ -35,7 +35,7 @@ enum real_value_class { ...@@ -35,7 +35,7 @@ enum real_value_class {
}; };
#define SIGNIFICAND_BITS (128 + HOST_BITS_PER_LONG) #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 MAX_EXP ((1 << (EXP_BITS - 1)) - 1)
#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG) #define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
#define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1)) #define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
...@@ -44,6 +44,7 @@ struct real_value GTY(()) ...@@ -44,6 +44,7 @@ struct real_value GTY(())
{ {
ENUM_BITFIELD (real_value_class) class : 2; ENUM_BITFIELD (real_value_class) class : 2;
unsigned int sign : 1; unsigned int sign : 1;
unsigned int signalling : 1;
signed int exp : EXP_BITS; signed int exp : EXP_BITS;
unsigned long sig[SIGSZ]; unsigned long sig[SIGSZ];
}; };
......
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