X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Flibgcc2.c;h=03cc448cab3e9e86f35a83bb73ed3c218ce2e6a3;hp=8a953ea8b761b5a5b9411ff84b496c15a5ed49ea;hb=3212edfa491e970255dd03c6991c868399c7be1d;hpb=0cf3a1b4a5ebad749c1c8af0291a315fa26e6ae2 diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 8a953ea8b76..03cc448cab3 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -1,7 +1,7 @@ /* More subroutines needed by GCC output code on some machines. */ /* Compile this one with gcc. */ /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -26,27 +26,14 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ - -/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is - supposedly valid even though this is a "target" file. */ -#include "auto-host.h" - -/* It is incorrect to include config.h here, because this file is being - compiled for the target, and hence definitions concerning only the host - do not apply. */ #include "tconfig.h" #include "tsystem.h" #include "coretypes.h" #include "tm.h" -/* Don't use `fancy_abort' here even if config.h says to use it. */ -#ifdef abort -#undef abort -#endif - #ifdef HAVE_GAS_HIDDEN #define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) #else @@ -73,7 +60,7 @@ __negdi2 (DWtype u) #ifdef L_addvsi3 Wtype -__addvsi3 (Wtype a, Wtype b) +__addvSI3 (Wtype a, Wtype b) { const Wtype w = a + b; @@ -82,11 +69,23 @@ __addvsi3 (Wtype a, Wtype b) return w; } +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__addvsi3 (SItype a, SItype b) +{ + const SItype w = a + b; + + if (b >= 0 ? w < a : w > a) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_addvdi3 DWtype -__addvdi3 (DWtype a, DWtype b) +__addvDI3 (DWtype a, DWtype b) { const DWtype w = a + b; @@ -99,20 +98,32 @@ __addvdi3 (DWtype a, DWtype b) #ifdef L_subvsi3 Wtype -__subvsi3 (Wtype a, Wtype b) +__subvSI3 (Wtype a, Wtype b) { - const DWtype w = a - b; + const Wtype w = a - b; if (b >= 0 ? w > a : w < a) abort (); return w; } +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__subvsi3 (SItype a, SItype b) +{ + const SItype w = a - b; + + if (b >= 0 ? w > a : w < a) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_subvdi3 DWtype -__subvdi3 (DWtype a, DWtype b) +__subvDI3 (DWtype a, DWtype b) { const DWtype w = a - b; @@ -124,22 +135,35 @@ __subvdi3 (DWtype a, DWtype b) #endif #ifdef L_mulvsi3 -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) Wtype -__mulvsi3 (Wtype a, Wtype b) +__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; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +#undef WORD_SIZE +#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) +SItype +__mulvsi3 (SItype a, SItype b) +{ + const DItype w = (DItype) a * (DItype) b; + + if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1)) abort (); return w; } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_negvsi2 Wtype -__negvsi2 (Wtype a) +__negvSI2 (Wtype a) { const Wtype w = -a; @@ -148,11 +172,23 @@ __negvsi2 (Wtype a) return w; } +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__negvsi2 (SItype a) +{ + const SItype w = -a; + + if (a >= 0 ? w > 0 : w < 0) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_negvdi2 DWtype -__negvdi2 (DWtype a) +__negvDI2 (DWtype a) { const DWtype w = -a; @@ -165,12 +201,30 @@ __negvdi2 (DWtype a) #ifdef L_absvsi2 Wtype -__absvsi2 (Wtype a) +__absvSI2 (Wtype a) { Wtype w = a; if (a < 0) #ifdef L_negvsi2 + w = __negvSI2 (a); +#else + w = -a; + + if (w < 0) + abort (); +#endif + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__absvsi2 (SItype a) +{ + SItype w = a; + + if (a < 0) +#ifdef L_negvsi2 w = __negvsi2 (a); #else w = -a; @@ -181,17 +235,18 @@ __absvsi2 (Wtype a) return w; } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_absvdi2 DWtype -__absvdi2 (DWtype a) +__absvDI2 (DWtype a) { DWtype w = a; if (a < 0) #ifdef L_negvdi2 - w = __negvdi2 (a); + w = __negvDI2 (a); #else w = -a; @@ -204,19 +259,18 @@ __absvdi2 (DWtype a) #endif #ifdef L_mulvdi3 -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) DWtype -__mulvdi3 (DWtype u, DWtype v) +__mulvDI3 (DWtype u, DWtype v) { /* The unchecked multiplication needs 3 Wtype x Wtype multiplications, but the checked multiplication needs only two. */ 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. */ @@ -235,7 +289,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; @@ -244,7 +298,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. */ @@ -258,7 +312,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; @@ -418,7 +472,6 @@ __ashrdi3 (DWtype u, word_type b) #ifdef L_ffssi2 #undef int -extern int __ffsSI2 (UWtype u); int __ffsSI2 (UWtype u) { @@ -434,7 +487,6 @@ __ffsSI2 (UWtype u) #ifdef L_ffsdi2 #undef int -extern int __ffsDI2 (DWtype u); int __ffsDI2 (DWtype u) { @@ -491,16 +543,16 @@ __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d) { if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1))) { - /* dividend, divisor, and quotient are nonnegative */ + /* Dividend, divisor, and quotient are nonnegative. */ sdiv_qrnnd (q, r, a1, a0, d); } else { - /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d. */ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1)); - /* Divide (c1*2^32 + c0) by d */ + /* Divide (c1*2^32 + c0) by d. */ sdiv_qrnnd (q, r, c1, c0, d); - /* Add 2^31 to quotient */ + /* Add 2^31 to quotient. */ q += (UWtype) 1 << (W_TYPE_SIZE - 1); } } @@ -596,7 +648,7 @@ __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)), #endif #ifdef L_clz -const UQItype __clz_tab[] = +const UQItype __clz_tab[256] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, @@ -605,13 +657,12 @@ const UQItype __clz_tab[] = 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; #endif #ifdef L_clzsi2 #undef int -extern int __clzSI2 (UWtype x); int __clzSI2 (UWtype x) { @@ -625,7 +676,6 @@ __clzSI2 (UWtype x) #ifdef L_clzdi2 #undef int -extern int __clzDI2 (UDWtype x); int __clzDI2 (UDWtype x) { @@ -645,7 +695,6 @@ __clzDI2 (UDWtype x) #ifdef L_ctzsi2 #undef int -extern int __ctzSI2 (UWtype x); int __ctzSI2 (UWtype x) { @@ -659,7 +708,6 @@ __ctzSI2 (UWtype x) #ifdef L_ctzdi2 #undef int -extern int __ctzDI2 (UDWtype x); int __ctzDI2 (UDWtype x) { @@ -677,13 +725,8 @@ __ctzDI2 (UDWtype x) } #endif -#if (defined (L_popcountsi2) || defined (L_popcountdi2) \ - || defined (L_popcount_tab)) -extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN; -#endif - #ifdef L_popcount_tab -const UQItype __popcount_tab[] = +const UQItype __popcount_tab[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, @@ -692,17 +735,16 @@ const UQItype __popcount_tab[] = 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; #endif #ifdef L_popcountsi2 #undef int -extern int __popcountSI2 (UWtype x); int __popcountSI2 (UWtype x) { - UWtype i, ret = 0; + int i, ret = 0; for (i = 0; i < W_TYPE_SIZE; i += 8) ret += __popcount_tab[(x >> i) & 0xff]; @@ -713,11 +755,10 @@ __popcountSI2 (UWtype x) #ifdef L_popcountdi2 #undef int -extern int __popcountDI2 (UDWtype x); int __popcountDI2 (UDWtype x) { - UWtype i, ret = 0; + int i, ret = 0; for (i = 0; i < 2*W_TYPE_SIZE; i += 8) ret += __popcount_tab[(x >> i) & 0xff]; @@ -728,7 +769,6 @@ __popcountDI2 (UDWtype x) #ifdef L_paritysi2 #undef int -extern int __paritySI2 (UWtype x); int __paritySI2 (UWtype x) { @@ -750,7 +790,6 @@ __paritySI2 (UWtype x) #ifdef L_paritydi2 #undef int -extern int __parityDI2 (UDWtype x); int __parityDI2 (UDWtype x) { @@ -1032,7 +1071,7 @@ __moddi3 (DWtype u, DWtype v) if (vv.s.high < 0) vv.ll = -vv.ll; - (void) __udivmoddi4 (uu.ll, vv.ll, &w); + (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w); if (c) w = -w; @@ -1098,10 +1137,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) && LIBGCC2_HAS_TF_MODE DWtype __fixunstfDI (TFtype a) { @@ -1109,11 +1145,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. @@ -1127,7 +1163,7 @@ __fixunstfDI (TFtype a) } #endif -#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) +#if defined(L_fixtfdi) && LIBGCC2_HAS_TF_MODE DWtype __fixtfdi (TFtype a) { @@ -1137,10 +1173,7 @@ __fixtfdi (TFtype a) } #endif -#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE DWtype __fixunsxfDI (XFtype a) { @@ -1148,11 +1181,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. @@ -1166,7 +1199,7 @@ __fixunsxfDI (XFtype a) } #endif -#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) +#if defined(L_fixxfdi) && LIBGCC2_HAS_XF_MODE DWtype __fixxfdi (XFtype a) { @@ -1176,29 +1209,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) && LIBGCC2_HAS_DF_MODE 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) && LIBGCC2_HAS_DF_MODE DWtype __fixdfdi (DFtype a) { @@ -1208,34 +1238,71 @@ __fixdfdi (DFtype a) } #endif -#ifdef L_fixunssfdi -#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) -#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) - +#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE DWtype -__fixunssfDI (SFtype original_a) +__fixunssfDI (SFtype a) { +#if LIBGCC2_HAS_DF_MODE /* 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 + significant 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 -#ifdef L_fixsfdi +#if defined(L_fixsfdi) && LIBGCC2_HAS_SF_MODE DWtype __fixsfdi (SFtype a) { @@ -1245,102 +1312,266 @@ __fixsfdi (SFtype a) } #endif -#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) -#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) && LIBGCC2_HAS_XF_MODE 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)); - +#if W_TYPE_SIZE > XF_SIZE +# error +#endif + 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_floatundixf) && LIBGCC2_HAS_XF_MODE +XFtype +__floatundixf (UDWtype u) +{ +#if W_TYPE_SIZE > XF_SIZE +# error +#endif + XFtype d = (UWtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; + return d; +} +#endif +#if defined(L_floatditf) && LIBGCC2_HAS_TF_MODE 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)); +#if W_TYPE_SIZE > TF_SIZE +# error +#endif + TFtype d = (Wtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; + return d; +} +#endif +#if defined(L_floatunditf) && LIBGCC2_HAS_TF_MODE +TFtype +__floatunditf (UDWtype u) +{ +#if W_TYPE_SIZE > TF_SIZE +# error +#endif + TFtype d = (UWtype) (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_floatdisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE) +#define DI_SIZE (W_TYPE_SIZE * 2) +#define F_MODE_OK(SIZE) (SIZE < DI_SIZE && SIZE > (DI_SIZE - SIZE + FSSIZE)) +#if defined(L_floatdisf) +#define FUNC __floatdisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatdidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif -DFtype -__floatdidf (DWtype u) +FSTYPE +FUNC (DWtype u) { - DFtype d = (Wtype) (u >> WORD_SIZE); - d *= HIGH_HALFWORD_COEFF; - d *= HIGH_HALFWORD_COEFF; - d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); +#if FSSIZE >= W_TYPE_SIZE + /* When the word size is small, we never get any rounding error. */ + FSTYPE f = (Wtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return f; +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype +#else +# error +#endif - return d; -} +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) + + /* Protect against double-rounding error. + 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 FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (! (- ((DWtype) 1 << FSIZE) < u + && u < ((DWtype) 1 << FSIZE))) + { + if ((UDWtype) u & (REP_BIT - 1)) + { + u &= ~ (REP_BIT - 1); + u |= REP_BIT; + } + } + + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (Wtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return (FSTYPE) f; +#else +#if FSSIZE >= W_TYPE_SIZE - 2 +# error #endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. 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 (FSTYPE)(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 = 1 + W_TYPE_SIZE - count; -#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) + /* Shift down the most significant bits. */ + hi = u >> shift; -#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT) -#define DF_SIZE DBL_MANT_DIG -#define SF_SIZE FLT_MANT_DIG + /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ + if (u & (((DWtype)1 << shift) - 1)) + hi |= 1; -SFtype -__floatdisf (DWtype u) + /* Convert the one word of data, and rescale. */ + FSTYPE f = hi; + f *= (UDWtype)1 << shift; + return f; +#endif +} +#endif + +#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE) +#define DI_SIZE (W_TYPE_SIZE * 2) +#define F_MODE_OK(SIZE) (SIZE < DI_SIZE && SIZE > (DI_SIZE - SIZE + FSSIZE)) +#if defined(L_floatundisf) +#define FUNC __floatundisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatundidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif + +FSTYPE +FUNC (UDWtype u) { +#if FSSIZE >= W_TYPE_SIZE + /* When the word size is small, we never get any rounding error. */ + FSTYPE f = (UWtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return f; +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype +#else +# error +#endif + +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) + /* 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. */ - if (DF_SIZE < DI_SIZE - && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) + 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 FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (u >= ((UDWtype) 1 << FSIZE)) { -#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) - if (! (- ((DWtype) 1 << DF_SIZE) < u - && u < ((DWtype) 1 << DF_SIZE))) + if ((UDWtype) u & (REP_BIT - 1)) { - if ((UDWtype) u & (REP_BIT - 1)) - { - u &= ~ (REP_BIT - 1); - u |= REP_BIT; - } + u &= ~ (REP_BIT - 1); + u |= REP_BIT; } } - /* 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)); - return (SFtype) f; + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (UWtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return (FSTYPE) f; +#else +#if FSSIZE == W_TYPE_SIZE - 1 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. 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 ((UWtype)u == u) + return (FSTYPE)(UWtype)u; + + /* Otherwise, find the power of two. */ + UWtype hi = u >> W_TYPE_SIZE; + + UWtype count, shift; + count_leading_zeros (count, hi); + + 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 & (((UDWtype)1 << shift) - 1)) + hi |= 1; + + /* Convert the one word of data, and rescale. */ + FSTYPE f = hi; + f *= (UDWtype)1 << shift; + return f; +#endif } #endif -#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 +#if defined(L_fixunsxfsi) && LIBGCC2_HAS_XF_MODE /* Reenable the normal types, in case limits.h needs them. */ #undef char #undef short @@ -1362,7 +1593,7 @@ __fixunsxfSI (XFtype a) } #endif -#ifdef L_fixunsdfsi +#if defined(L_fixunsdfsi) && LIBGCC2_HAS_DF_MODE /* Reenable the normal types, in case limits.h needs them. */ #undef char #undef short @@ -1384,7 +1615,7 @@ __fixunsdfSI (DFtype a) } #endif -#ifdef L_fixunssfsi +#if defined(L_fixunssfsi) && LIBGCC2_HAS_SF_MODE /* Reenable the normal types, in case limits.h needs them. */ #undef char #undef short @@ -1406,6 +1637,245 @@ __fixunssfSI (SFtype a) } #endif +/* Integer power helper used from __builtin_powi for non-constant + exponents. */ + +#if (defined(L_powisf2) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_powidf2) && LIBGCC2_HAS_DF_MODE) \ + || (defined(L_powixf2) && LIBGCC2_HAS_XF_MODE) \ + || (defined(L_powitf2) && LIBGCC2_HAS_TF_MODE) +# if defined(L_powisf2) +# define TYPE SFtype +# define NAME __powisf2 +# elif defined(L_powidf2) +# define TYPE DFtype +# define NAME __powidf2 +# elif defined(L_powixf2) +# define TYPE XFtype +# define NAME __powixf2 +# elif defined(L_powitf2) +# define TYPE TFtype +# define NAME __powitf2 +# endif + +#undef int +#undef unsigned +TYPE +NAME (TYPE x, int m) +{ + unsigned int n = m < 0 ? -m : m; + TYPE y = n % 2 ? x : 1; + while (n >>= 1) + { + x = x * x; + if (n % 2) + y = y * x; + } + return m < 0 ? 1/y : y; +} + +#endif + +#if ((defined(L_mulsc3) || defined(L_divsc3)) && LIBGCC2_HAS_SF_MODE) \ + || ((defined(L_muldc3) || defined(L_divdc3)) && LIBGCC2_HAS_DF_MODE) \ + || ((defined(L_mulxc3) || defined(L_divxc3)) && LIBGCC2_HAS_XF_MODE) \ + || ((defined(L_multc3) || defined(L_divtc3)) && LIBGCC2_HAS_TF_MODE) + +#undef float +#undef double +#undef long + +#if defined(L_mulsc3) || defined(L_divsc3) +# define MTYPE SFtype +# define CTYPE SCtype +# define MODE sc +# define CEXT f +# define NOTRUNC __FLT_EVAL_METHOD__ == 0 +#elif defined(L_muldc3) || defined(L_divdc3) +# define MTYPE DFtype +# define CTYPE DCtype +# define MODE dc +# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 +# define CEXT l +# define NOTRUNC 1 +# else +# define CEXT +# define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1 +# endif +#elif defined(L_mulxc3) || defined(L_divxc3) +# define MTYPE XFtype +# define CTYPE XCtype +# define MODE xc +# define CEXT l +# define NOTRUNC 1 +#elif defined(L_multc3) || defined(L_divtc3) +# define MTYPE TFtype +# define CTYPE TCtype +# define MODE tc +# define CEXT l +# define NOTRUNC 1 +#else +# error +#endif + +#define CONCAT3(A,B,C) _CONCAT3(A,B,C) +#define _CONCAT3(A,B,C) A##B##C + +#define CONCAT2(A,B) _CONCAT2(A,B) +#define _CONCAT2(A,B) A##B + +/* All of these would be present in a full C99 implementation of + and . Our problem is that only a few systems have such full + implementations. Further, libgcc_s.so isn't currently linked against + libm.so, and even for systems that do provide full C99, the extra overhead + of all programs using libgcc having to link against libm. So avoid it. */ + +#define isnan(x) __builtin_expect ((x) != (x), 0) +#define isfinite(x) __builtin_expect (!isnan((x) - (x)), 1) +#define isinf(x) __builtin_expect (!isnan(x) & !isfinite(x), 0) + +#define INFINITY CONCAT2(__builtin_inf, CEXT) () +#define I 1i + +/* Helpers to make the following code slightly less gross. */ +#define COPYSIGN CONCAT2(__builtin_copysign, CEXT) +#define FABS CONCAT2(__builtin_fabs, CEXT) + +/* Verify that MTYPE matches up with CEXT. */ +extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1]; + +/* Ensure that we've lost any extra precision. */ +#if NOTRUNC +# define TRUNC(x) +#else +# define TRUNC(x) __asm__ ("" : "=m"(x) : "m"(x)) +#endif + +#if defined(L_mulsc3) || defined(L_muldc3) \ + || defined(L_mulxc3) || defined(L_multc3) + +CTYPE +CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d) +{ + MTYPE ac, bd, ad, bc, x, y; + + ac = a * c; + bd = b * d; + ad = a * d; + bc = b * c; + + TRUNC (ac); + TRUNC (bd); + TRUNC (ad); + TRUNC (bc); + + x = ac - bd; + y = ad + bc; + + if (isnan (x) && isnan (y)) + { + /* Recover infinities that computed as NaN + iNaN. */ + _Bool recalc = 0; + if (isinf (a) || isinf (b)) + { + /* z is infinite. "Box" the infinity and change NaNs in + the other factor to 0. */ + a = COPYSIGN (isinf (a) ? 1 : 0, a); + b = COPYSIGN (isinf (b) ? 1 : 0, b); + if (isnan (c)) c = COPYSIGN (0, c); + if (isnan (d)) d = COPYSIGN (0, d); + recalc = 1; + } + if (isinf (c) || isinf (d)) + { + /* w is infinite. "Box" the infinity and change NaNs in + the other factor to 0. */ + c = COPYSIGN (isinf (c) ? 1 : 0, c); + d = COPYSIGN (isinf (d) ? 1 : 0, d); + if (isnan (a)) a = COPYSIGN (0, a); + if (isnan (b)) b = COPYSIGN (0, b); + recalc = 1; + } + if (!recalc + && (isinf (ac) || isinf (bd) + || isinf (ad) || isinf (bc))) + { + /* Recover infinities from overflow by changing NaNs to 0. */ + if (isnan (a)) a = COPYSIGN (0, a); + if (isnan (b)) b = COPYSIGN (0, b); + if (isnan (c)) c = COPYSIGN (0, c); + if (isnan (d)) d = COPYSIGN (0, d); + recalc = 1; + } + if (recalc) + { + x = INFINITY * (a * c - b * d); + y = INFINITY * (a * d + b * c); + } + } + + return x + I * y; +} +#endif /* complex multiply */ + +#if defined(L_divsc3) || defined(L_divdc3) \ + || defined(L_divxc3) || defined(L_divtc3) + +CTYPE +CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d) +{ + MTYPE denom, ratio, x, y; + + /* ??? We can get better behavior from logarithmic scaling instead of + the division. But that would mean starting to link libgcc against + libm. We could implement something akin to ldexp/frexp as gcc builtins + fairly easily... */ + if (FABS (c) < FABS (d)) + { + ratio = c / d; + denom = (c * ratio) + d; + x = ((a * ratio) + b) / denom; + y = ((b * ratio) - a) / denom; + } + else + { + ratio = d / c; + denom = (d * ratio) + c; + x = ((b * ratio) + a) / denom; + y = (b - (a * ratio)) / denom; + } + + /* Recover infinities and zeros that computed as NaN+iNaN; the only cases + are nonzero/zero, infinite/finite, and finite/infinite. */ + if (isnan (x) && isnan (y)) + { + if (denom == 0.0 && (!isnan (a) || !isnan (b))) + { + x = COPYSIGN (INFINITY, c) * a; + y = COPYSIGN (INFINITY, c) * b; + } + else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d)) + { + a = COPYSIGN (isinf (a) ? 1 : 0, a); + b = COPYSIGN (isinf (b) ? 1 : 0, b); + x = INFINITY * (a * c + b * d); + y = INFINITY * (b * c - a * d); + } + else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b)) + { + c = COPYSIGN (isinf (c) ? 1 : 0, c); + d = COPYSIGN (isinf (d) ? 1 : 0, d); + x = 0.0 * (a * c + b * d); + y = 0.0 * (b * c - a * d); + } + } + + return x + I * y; +} +#endif /* complex divide */ + +#endif /* all complex float routines */ + /* From here on down, the routines use normal data types. */ #define SItype bogus_type @@ -1487,13 +1957,26 @@ __clear_cache (char *beg __attribute__((__unused__)), #endif /* L_clear_cache */ +#ifdef L_enable_execute_stack +/* Attempt to turn on execute permission for the stack. */ + +#ifdef ENABLE_EXECUTE_STACK + ENABLE_EXECUTE_STACK +#else +void +__enable_execute_stack (void *addr __attribute__((__unused__))) +{} +#endif /* ENABLE_EXECUTE_STACK */ + +#endif /* L_enable_execute_stack */ + #ifdef L_trampoline /* Jump to a trampoline, loading the static chain address. */ #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN) -long +int getpagesize (void) { #ifdef _ALPHA_ @@ -1542,6 +2025,7 @@ TRANSFER_FROM_TRAMPOLINE #ifdef L__main #include "gbl-ctors.h" + /* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to give the same symbol without quotes for an alternative entry point. You @@ -1551,7 +2035,7 @@ TRANSFER_FROM_TRAMPOLINE #define SYMBOL__MAIN __main #endif -#ifdef INIT_SECTION_ASM_OP +#if defined (INIT_SECTION_ASM_OP) || defined (INIT_ARRAY_SECTION_ASM_OP) #undef HAS_INIT_SECTION #define HAS_INIT_SECTION #endif @@ -1664,4 +2148,3 @@ func_ptr __DTOR_LIST__[2]; #endif #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ #endif /* L_ctors */ -