diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-16 22:55:33 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-16 22:55:33 +0000 |
commit | fe2f56931c21fbf9551a4433e0e0389c5abf85a5 (patch) | |
tree | 2c8f7da1df0ca3c8c4ec10b9017f84b06b17368b /gcc/libgcc2.c | |
parent | ccd90aaa3dbf50d8b05431904eaf6b3ea2f7d254 (diff) | |
download | gcc-fe2f56931c21fbf9551a4433e0e0389c5abf85a5.tar.gz |
PR 19920
* libgcc2.c (WORD_SIZE): Remove all definitions; replace uses
with W_TYPE_SIZE.
(HIGH_WORD_COEFF, HIGH_HALFWORD_COEFF): Remove all definitions;
replace uses with Wtype_MAXp1_F.
(L_fixunstfdi, L_fixtfdi, L_floatditf, L_fixunsxfdi, L_fixxfdi,
L_floatdixf, L_fixunsxfsi, L_fixunsdfdi, L_floatdidf, L_fixunsdfsi,
L_powidf2, L_powixf2, L_powitf2, L_muldc3, L_divdc3, L_mulxc3,
L_divxc3, L_multc3, L_divtc3): Protect with HAVE_DFMODE, HAVE_XFMODE,
and HAVE_TFMODE as appropriate.
(__fixunssfDI): Provide an implementation that doesn't need DFmode.
(__floatdisf): Likewise.
* libgcc2.h (LIBGCC2_DOUBLE_TYPE_SIZE): New.
(HAVE_DFMODE, HAVE_XFMODE, HAVE_TFMODE): New.
(Wtype_MAXp1_F): New.
(DFtype, DCtype, __fixdfdi, __floatdidf, __fixunsdfSI, __fixunsdfDI,
__powidf2, __divdc3, __muldc3): Protect with HAVE_DFMODE.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95121 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r-- | gcc/libgcc2.c | 245 |
1 files changed, 148 insertions, 97 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 56a9bc4e87a..9bdb1c71228 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -148,13 +148,12 @@ __subvDI3 (DWtype a, DWtype b) #endif #ifdef L_mulvsi3 -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) Wtype __mulvSI3 (Wtype a, Wtype b) { const DWtype w = (DWtype) a * (DWtype) b; - if ((Wtype) (w >> WORD_SIZE) != (Wtype) w >> (WORD_SIZE - 1)) + if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1)) abort (); return w; @@ -273,7 +272,6 @@ __absvDI2 (DWtype a) #endif #ifdef L_mulvdi3 -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) DWtype __mulvDI3 (DWtype u, DWtype v) { @@ -282,10 +280,10 @@ __mulvDI3 (DWtype u, DWtype v) const DWunion uu = {.ll = u}; const DWunion vv = {.ll = v}; - if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1)) + if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1)) { /* u fits in a single Wtype. */ - if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1)) + if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1)) { /* v fits in a single Wtype as well. */ /* A single multiplication. No overflow risk. */ @@ -304,7 +302,7 @@ __mulvDI3 (DWtype u, DWtype v) if (uu.s.low < 0) w1.ll -= vv.ll; w1.ll += (UWtype) w0.s.high; - if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1)) + if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1)) { w0.s.high = w1.s.low; return w0.ll; @@ -313,7 +311,7 @@ __mulvDI3 (DWtype u, DWtype v) } else { - if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1)) + if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1)) { /* v fits into a single Wtype. */ /* Two multiplications. */ @@ -327,7 +325,7 @@ __mulvDI3 (DWtype u, DWtype v) if (vv.s.low < 0) w1.ll -= uu.ll; w1.ll += (UWtype) w0.s.high; - if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1)) + if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1)) { w0.s.high = w1.s.low; return w0.ll; @@ -1157,10 +1155,7 @@ __ucmpdi2 (DWtype a, DWtype b) } #endif -#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_fixunstfdi) && defined(HAVE_TFMODE) DWtype __fixunstfDI (TFtype a) { @@ -1168,11 +1163,11 @@ __fixunstfDI (TFtype a) return 0; /* Compute high word of result, as a flonum. */ - const TFtype b = (a / HIGH_WORD_COEFF); + const TFtype b = (a / Wtype_MAXp1_F); /* Convert that to fixed (but not to DWtype!), and shift it into the high word. */ UDWtype v = (UWtype) b; - v <<= WORD_SIZE; + v <<= W_TYPE_SIZE; /* Remove high part from the TFtype, leaving the low part as flonum. */ a -= (TFtype)v; /* Convert that to fixed (but not to DWtype!) and add it in. @@ -1186,7 +1181,7 @@ __fixunstfDI (TFtype a) } #endif -#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) +#if defined(L_fixtfdi) && defined(HAVE_TFMODE) DWtype __fixtfdi (TFtype a) { @@ -1196,10 +1191,7 @@ __fixtfdi (TFtype a) } #endif -#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_fixunsxfdi) && defined(HAVE_XFMODE) DWtype __fixunsxfDI (XFtype a) { @@ -1207,11 +1199,11 @@ __fixunsxfDI (XFtype a) return 0; /* Compute high word of result, as a flonum. */ - const XFtype b = (a / HIGH_WORD_COEFF); + const XFtype b = (a / Wtype_MAXp1_F); /* Convert that to fixed (but not to DWtype!), and shift it into the high word. */ UDWtype v = (UWtype) b; - v <<= WORD_SIZE; + v <<= W_TYPE_SIZE; /* Remove high part from the XFtype, leaving the low part as flonum. */ a -= (XFtype)v; /* Convert that to fixed (but not to DWtype!) and add it in. @@ -1225,7 +1217,7 @@ __fixunsxfDI (XFtype a) } #endif -#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) +#if defined(L_fixxfdi) && defined(HAVE_XFMODE) DWtype __fixxfdi (XFtype a) { @@ -1235,29 +1227,26 @@ __fixxfdi (XFtype a) } #endif -#ifdef L_fixunsdfdi -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_fixunsdfdi) && defined(HAVE_DFMODE) DWtype __fixunsdfDI (DFtype a) { /* Get high part of result. The division here will just moves the radix point and will not cause any rounding. Then the conversion to integral type chops result as desired. */ - const UWtype hi = a / HIGH_WORD_COEFF; + const UWtype hi = a / Wtype_MAXp1_F; /* Get low part of result. Convert `hi' to floating type and scale it back, then subtract this from the number being converted. This leaves the low part. Convert that to integral type. */ - const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF); + const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F; /* Assemble result from the two parts. */ - return ((UDWtype) hi << WORD_SIZE) | lo; + return ((UDWtype) hi << W_TYPE_SIZE) | lo; } #endif -#ifdef L_fixdfdi +#if defined(L_fixdfdi) && defined(HAVE_DFMODE) DWtype __fixdfdi (DFtype a) { @@ -1268,29 +1257,66 @@ __fixdfdi (DFtype a) #endif #ifdef L_fixunssfdi -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - DWtype -__fixunssfDI (SFtype original_a) +__fixunssfDI (SFtype a) { +#if defined(HAVE_DFMODE) /* Convert the SFtype to a DFtype, because that is surely not going to lose any bits. Some day someone else can write a faster version that avoids converting to DFtype, and verify it really works right. */ - const DFtype a = original_a; + const DFtype dfa = a; /* Get high part of result. The division here will just moves the radix point and will not cause any rounding. Then the conversion to integral type chops result as desired. */ - const UWtype hi = a / HIGH_WORD_COEFF; + const UWtype hi = dfa / Wtype_MAXp1_F; /* Get low part of result. Convert `hi' to floating type and scale it back, then subtract this from the number being converted. This leaves the low part. Convert that to integral type. */ - const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF); + const UWtype lo = dfa - (DFtype) hi * Wtype_MAXp1_F; /* Assemble result from the two parts. */ - return ((UDWtype) hi << WORD_SIZE) | lo; + return ((UDWtype) hi << W_TYPE_SIZE) | lo; +#elif FLT_MANT_DIG < W_TYPE_SIZE + if (a < 1) + return 0; + if (a < Wtype_MAXp1_F) + return (UWtype)a; + if (a < Wtype_MAXp1_F * Wtype_MAXp1_F) + { + /* Since we know that there are fewer significant bits in the SFmode + quantity than in a word, we know that we can convert out all the + signficant bits in one step, and thus avoid losing bits. */ + + /* ??? This following loop essentially performs frexpf. If we could + use the real libm function, or poke at the actual bits of the fp + format, it would be significantly faster. */ + + UWtype shift = 0, counter; + SFtype msb; + + a /= Wtype_MAXp1_F; + for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1) + { + SFtype counterf = (UWtype)1 << counter; + if (a >= counterf) + { + shift |= counter; + a /= counterf; + } + } + + /* Rescale into the range of one word, extract the bits of that + one word, and shift the result into position. */ + a *= Wtype_MAXp1_F; + counter = a; + return (DWtype)counter << shift; + } + return -1; +#else +# error +#endif } #endif @@ -1304,79 +1330,72 @@ __fixsfdi (SFtype a) } #endif -#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_floatdixf) && defined(HAVE_XFMODE) XFtype __floatdixf (DWtype u) { - XFtype d = (Wtype) (u >> WORD_SIZE); - d *= HIGH_HALFWORD_COEFF; - d *= HIGH_HALFWORD_COEFF; - d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); - + XFtype d = (Wtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; return d; } #endif -#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_floatditf) && defined(HAVE_TFMODE) TFtype __floatditf (DWtype u) { - TFtype d = (Wtype) (u >> WORD_SIZE); - d *= HIGH_HALFWORD_COEFF; - d *= HIGH_HALFWORD_COEFF; - d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); - + TFtype d = (Wtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; return d; } #endif -#ifdef L_floatdidf -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_floatdidf) && defined(HAVE_DFMODE) DFtype __floatdidf (DWtype u) { - DFtype d = (Wtype) (u >> WORD_SIZE); - d *= HIGH_HALFWORD_COEFF; - d *= HIGH_HALFWORD_COEFF; - d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); - + DFtype d = (Wtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; return d; } #endif #ifdef L_floatdisf -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - -#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT) -#define DF_SIZE DBL_MANT_DIG +#define DI_SIZE (W_TYPE_SIZE * 2) #define SF_SIZE FLT_MANT_DIG SFtype __floatdisf (DWtype u) { +#if SF_SIZE >= W_TYPE_SIZE + /* When the word size is small, we never get any rounding error. */ + SFtype f = (Wtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return f; +#elif defined(HAVE_DFMODE) + +#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 +#define DF_SIZE DBL_MANT_DIG +#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 +#define DF_SIZE LDBL_MANT_DIG +#else +# error +#endif + +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) + /* Protect against double-rounding error. - Represent any low-order bits, that might be truncated in DFmode, - by a bit that won't be lost. The bit can go in anywhere below the - rounding position of the SFmode. A fixed mask and bit position - handles all usual configurations. It doesn't handle the case - of 128-bit DImode, however. */ + Represent any low-order bits, that might be truncated by a bit that + won't be lost. The bit can go in anywhere below the rounding position + of the SFmode. A fixed mask and bit position handles all usual + configurations. It doesn't handle the case of 128-bit DImode, however. */ if (DF_SIZE < DI_SIZE && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) { -#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) if (! (- ((DWtype) 1 << DF_SIZE) < u && u < ((DWtype) 1 << DF_SIZE))) { @@ -1387,19 +1406,52 @@ __floatdisf (DWtype u) } } } - /* Do the calculation in DFmode - so that we don't lose any of the precision of the high word - while multiplying it. */ - DFtype f = (Wtype) (u >> WORD_SIZE); - f *= HIGH_HALFWORD_COEFF; - f *= HIGH_HALFWORD_COEFF; - f += (UWtype) (u & (HIGH_WORD_COEFF - 1)); + /* Do the calculation in DFmode so that we don't lose any of the + precision of the high word while multiplying it. */ + DFtype f = (Wtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; return (SFtype) f; +#else + /* Finally, the word size is larger than the number of bits in SFmode, + and we've got no DFmode. The only way to avoid double rounding is + to special case the extraction. */ + + /* If there are no high bits set, fall back to one conversion. */ + if ((Wtype)u == u) + return (SFtype)(Wtype)u; + + /* Otherwise, find the power of two. */ + Wtype hi = u >> W_TYPE_SIZE; + if (hi < 0) + hi = -hi; + + UWtype count, shift; + count_leading_zeros (count, hi); + + /* No leading bits means u == minimum. */ + if (count == 0) + return -(Wtype_MAXp1_F * Wtype_MAXp1_F / 2); + + shift = W_TYPE_SIZE - count; + + /* Shift down the most significant bits. */ + hi = u >> shift; + + /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ + if (u & ((1 << shift) - 1)) + hi |= 1; + + /* Convert the one word of data, and rescale. */ + SFtype f = hi; + f *= (UWtype)1 << shift; + return f; +#endif } #endif -#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80 +#if defined(L_fixunsxfsi) && defined(HAVE_XFMODE) /* Reenable the normal types, in case limits.h needs them. */ #undef char #undef short @@ -1421,7 +1473,7 @@ __fixunsxfSI (XFtype a) } #endif -#ifdef L_fixunsdfsi +#if defined(L_fixunsdfsi) && defined(HAVE_DFMODE) /* Reenable the normal types, in case limits.h needs them. */ #undef char #undef short @@ -1468,9 +1520,10 @@ __fixunssfSI (SFtype a) /* Integer power helper used from __builtin_powi for non-constant exponents. */ -#if defined(L_powisf2) || defined(L_powidf2) \ - || (defined(L_powixf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) \ - || (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) +#if defined(L_powisf2) \ + || (defined(L_powidf2) && defined(HAVE_DFMODE)) \ + || (defined(L_powixf2) && defined(HAVE_XFMODE)) \ + || (defined(L_powitf2) && defined(HAVE_TFMODE)) # if defined(L_powisf2) # define TYPE SFtype # define NAME __powisf2 @@ -1502,11 +1555,9 @@ NAME (TYPE x, Wtype m) #endif #if defined(L_mulsc3) || defined(L_divsc3) \ - || defined(L_muldc3) || defined(L_divdc3) \ - || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80 \ - && (defined(L_mulxc3) || defined(L_divxc3))) \ - || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 \ - && (defined(L_multc3) || defined(L_divtc3))) + || ((defined(L_muldc3) || defined(L_divdc3)) && defined(HAVE_DFMODE)) \ + || ((defined(L_mulxc3) || defined(L_divxc3)) && defined(HAVE_XFMODE)) \ + || ((defined(L_multc3) || defined(L_divtc3)) && defined(HAVE_TFMODE)) #undef float #undef double |