summaryrefslogtreecommitdiff
path: root/gcc/config/fp-bit.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2004-01-28 07:21:21 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2004-01-28 07:21:21 +0000
commit7dd4dac3d46ec4ccc37155d2164f9991867d3919 (patch)
tree4c12b2cd7e8aa5cda660f0dbb77db1ea2040a0c0 /gcc/config/fp-bit.c
parentec618ada42770de438fdda1f2ae7571965899063 (diff)
downloadgcc-7dd4dac3d46ec4ccc37155d2164f9991867d3919.tar.gz
* config/fp-bit.c (pack_d): When using paired doubles to implement
a long double, round the high part separately. (unpack_d): Fix the case in which the high part is a power of two and the low part is a nonzero value of the opposite sign. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76780 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/fp-bit.c')
-rw-r--r--gcc/config/fp-bit.c90
1 files changed, 58 insertions, 32 deletions
diff --git a/gcc/config/fp-bit.c b/gcc/config/fp-bit.c
index 51c67430535..a1ba156bf45 100644
--- a/gcc/config/fp-bit.c
+++ b/gcc/config/fp-bit.c
@@ -330,58 +330,76 @@ pack_d ( fp_number_type * src)
#else
# if defined TFLOAT && defined HALFFRACBITS
{
- halffractype high, low;
-
- high = (fraction >> (FRACBITS - HALFFRACBITS));
- high &= (((fractype)1) << HALFFRACBITS) - 1;
- high |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << HALFFRACBITS;
- high |= ((fractype) (sign & 1)) << (HALFFRACBITS | EXPBITS);
-
- low = (halffractype)fraction &
- ((((halffractype)1) << (FRACBITS - HALFFRACBITS)) - 1);
+ halffractype high, low, unity;
+ int lowsign, lowexp;
+
+ unity = (halffractype) 1 << HALFFRACBITS;
+
+ /* Set HIGH to the high double's significand, masking out the implicit 1.
+ Set LOW to the low double's full significand. */
+ high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
+ low = fraction & (unity * 2 - 1);
+
+ /* Get the initial sign and exponent of the low double. */
+ lowexp = exp - HALFFRACBITS - 1;
+ lowsign = sign;
+
+ /* HIGH should be rounded like a normal double, making |LOW| <=
+ 0.5 ULP of HIGH. Assume round-to-nearest. */
+ if (exp < EXPMAX)
+ if (low > unity || (low == unity && (high & 1) == 1))
+ {
+ /* Round HIGH up and adjust LOW to match. */
+ high++;
+ if (high == unity)
+ {
+ /* May make it infinite, but that's OK. */
+ high = 0;
+ exp++;
+ }
+ low = unity * 2 - low;
+ lowsign ^= 1;
+ }
+
+ high |= (halffractype) exp << HALFFRACBITS;
+ high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
if (exp == EXPMAX || exp == 0 || low == 0)
low = 0;
else
{
- exp -= HALFFRACBITS + 1;
-
- while (exp > 0
- && low < ((halffractype)1 << HALFFRACBITS))
+ while (lowexp > 0 && low < unity)
{
low <<= 1;
- exp--;
+ lowexp--;
}
- if (exp <= 0)
+ if (lowexp <= 0)
{
halffractype roundmsb, round;
+ int shift;
- exp = -exp + 1;
-
- roundmsb = (1 << (exp - 1));
+ shift = 1 - lowexp;
+ roundmsb = (1 << (shift - 1));
round = low & ((roundmsb << 1) - 1);
- low >>= exp;
- exp = 0;
+ low >>= shift;
+ lowexp = 0;
- if (round > roundmsb || (round == roundmsb && (low & 1)))
+ if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
{
low++;
- if (low >= ((halffractype)1 << HALFFRACBITS))
- /* We don't shift left, since it has just become the
- smallest normal number, whose implicit 1 bit is
- now indicated by the nonzero exponent. */
- exp++;
+ if (low == unity)
+ /* LOW rounds up to the smallest normal number. */
+ lowexp++;
}
}
- low &= ((halffractype)1 << HALFFRACBITS) - 1;
- low |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << HALFFRACBITS;
- low |= ((fractype) (sign & 1)) << (HALFFRACBITS | EXPBITS);
+ low &= unity - 1;
+ low |= (halffractype) lowexp << HALFFRACBITS;
+ low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
}
-
- dst.value_raw = (((fractype) high) << HALFSHIFT) | low;
+ dst.value_raw = ((fractype) high << HALFSHIFT) | low;
}
# else
dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
@@ -475,8 +493,16 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
xlow >>= -shift;
if (sign == lowsign)
fraction += xlow;
- else
+ else if (fraction >= xlow)
fraction -= xlow;
+ else
+ {
+ /* The high part is a power of two but the full number is lower.
+ This code will leave the implicit 1 in FRACTION, but we'd
+ have added that below anyway. */
+ fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
+ exp--;
+ }
}
}
# else