summaryrefslogtreecommitdiff
path: root/gcc/libgcc2.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-16 22:55:33 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2005-02-16 22:55:33 +0000
commitfe2f56931c21fbf9551a4433e0e0389c5abf85a5 (patch)
tree2c8f7da1df0ca3c8c4ec10b9017f84b06b17368b /gcc/libgcc2.c
parentccd90aaa3dbf50d8b05431904eaf6b3ea2f7d254 (diff)
downloadgcc-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.c245
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