2007-01-05 Jakub Jelinek PR c/30360 * libgcc2.c (__divdc3): Compare c and d against 0.0 instead of denom against 0.0. 2005-11-22 Joseph S. Myers * libgcc-std.ver (GCC_4.2.0): New version. * libgcc2.c (__floatundixf, __floatunditf, __floatundidf, __floatundisf): New functions. * libgcc2.h (__floatundixf, __floatunditf, __floatundidf, __floatundisf): Declare. * mklibgcc.in (lib2funcs): Add _floatundidf, _floatundisf, _floatundixf, and _floatunditf. 2005-03-30 Fariborz Jahanian * libgcc2.h (__powisf2, __powidf2, __powixf2, __powitf2): Change 2nd argument type to int. * libgcc2.c: Change prototype of __powi* functions to use int. 2005-02-11 Richard Henderson * libgcc2.c (__divsc3, __divdc3, __divxc3, __divtc3, __mulsc3, __muldc3, __mulxc3, __multc3): New. * libgcc2.h: Declare them. * libgcc-std.ver: Export them. * mklibgcc.in (lib2funcs): Build them. 2005-02-09 Richard Guenther PR middle-end/19402 * libgcc2.h: Add prototypes for __builtin_powi[lf]. * libgcc2.c: Add __builtin_powi[lf] implementation. * mklibgcc.in: Add __builtin_powi[lf] to lib2funcs. --- gcc/libgcc-std.ver.jj 2007-03-02 09:27:16.000000000 +0100 +++ gcc/libgcc-std.ver 2007-03-02 10:32:27.000000000 +0100 @@ -235,7 +235,39 @@ GCC_3.4.4 { __subvti3 } -%inherit GCC_4.2.0 GCC_3.4.4 +%inherit GCC_4.0.0 GCC_3.4.4 +GCC_4.0.0 { + # libgcc2 __builtin_powi helpers. + __powisf2 + __powidf2 + __powixf2 + __powitf2 + + # c99 compliant complex arithmetic + __divsc3 + __divdc3 + __divxc3 + __divtc3 + __mulsc3 + __muldc3 + __mulxc3 + __multc3 +} + +%inherit GCC_4.2.0 GCC_4.0.0 GCC_4.2.0 { + # unsigned-to-floating conversions + __floatunsisf + __floatunsidf + __floatunsixf + __floatunsitf + __floatundidf + __floatundisf + __floatundixf + __floatunditf + __floatuntidf + __floatuntisf + __floatuntixf + __floatuntitf _Unwind_GetIPInfo } --- gcc/libgcc2.h.jj 2006-10-05 00:37:01.000000000 +0200 +++ gcc/libgcc2.h 2007-03-02 11:26:31.000000000 +0100 @@ -88,12 +88,16 @@ typedef unsigned int UTItype __attribute typedef float SFtype __attribute__ ((mode (SF))); typedef float DFtype __attribute__ ((mode (DF))); +typedef _Complex float SCtype; +typedef _Complex double DCtype; #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 typedef float XFtype __attribute__ ((mode (XF))); +typedef _Complex long double XCtype; #endif #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 typedef float TFtype __attribute__ ((mode (TF))); +typedef _Complex long double TCtype; #endif #else /* BITS_PER_UNIT != 8 */ @@ -216,6 +220,10 @@ typedef int word_type __attribute__ ((mo #define __floatditf __NDW(float,tf) #define __floatdidf __NDW(float,df) #define __floatdisf __NDW(float,sf) +#define __floatundixf __NDW(floatun,xf) +#define __floatunditf __NDW(floatun,tf) +#define __floatundidf __NDW(floatun,df) +#define __floatundisf __NDW(floatun,sf) #define __fixunsxfSI __NW(fixunsxf,) #define __fixunstfSI __NW(fixunstf,) #define __fixunsdfSI __NW(fixunsdf,) @@ -293,27 +301,47 @@ extern SItype __negvsi2 (SItype); #endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #if BITS_PER_UNIT == 8 +#undef int extern DWtype __fixdfdi (DFtype); extern DWtype __fixsfdi (SFtype); extern DFtype __floatdidf (DWtype); extern SFtype __floatdisf (DWtype); +extern DFtype __floatundidf (UDWtype); +extern SFtype __floatundisf (UDWtype); extern UWtype __fixunsdfSI (DFtype); extern UWtype __fixunssfSI (SFtype); extern DWtype __fixunsdfDI (DFtype); extern DWtype __fixunssfDI (SFtype); +extern SFtype __powisf2 (SFtype, int); +extern DFtype __powidf2 (DFtype, int); + +extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype); +extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype); +extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype); +extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype); #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 extern DWtype __fixxfdi (XFtype); extern DWtype __fixunsxfDI (XFtype); extern XFtype __floatdixf (DWtype); +extern XFtype __floatundixf (UDWtype); extern UWtype __fixunsxfSI (XFtype); +extern XFtype __powixf2 (XFtype, int); +extern XCtype __divxc3 (XFtype, XFtype, XFtype, XFtype); +extern XCtype __mulxc3 (XFtype, XFtype, XFtype, XFtype); #endif #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 extern DWtype __fixunstfDI (TFtype); extern DWtype __fixtfdi (TFtype); extern TFtype __floatditf (DWtype); +extern TFtype __floatunditf (UDWtype); +extern TFtype __powitf2 (TFtype, int); +extern TCtype __divtc3 (TFtype, TFtype, TFtype, TFtype); +extern TCtype __multc3 (TFtype, TFtype, TFtype, TFtype); #endif + +#define int bogus_type #endif /* BITS_PER_UNIT == 8 */ /* DWstructs are pairs of Wtype values in the order determined by --- gcc/mklibgcc.in.jj 2006-10-05 00:37:01.000000000 +0200 +++ gcc/mklibgcc.in 2007-03-02 10:31:58.000000000 +0100 @@ -58,7 +58,9 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash _enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3 _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors _ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab - _popcountsi2 _popcountdi2 _paritysi2 _paritydi2' + _popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2 + _powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3 + _divxc3 _divtc3 _floatundidf _floatundisf _floatundixf _floatunditf' # Disable SHLIB_LINK if shared libgcc not enabled. if [ "@enable_shared@" = "no" ]; then --- gcc/libgcc2.c.jj 2006-10-05 00:37:01.000000000 +0200 +++ gcc/libgcc2.c 2007-03-02 10:58:07.000000000 +0100 @@ -1331,6 +1331,23 @@ __floatdixf (DWtype u) } #endif +#if defined(L_floatundixf) && (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) + +XFtype +__floatundixf (UDWtype u) +{ + XFtype d = (UWtype) (u >> WORD_SIZE); + d *= HIGH_HALFWORD_COEFF; + d *= HIGH_HALFWORD_COEFF; + d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); + + 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)) @@ -1348,6 +1365,23 @@ __floatditf (DWtype u) } #endif +#if defined(L_floatunditf) && (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) + +TFtype +__floatunditf (UDWtype u) +{ + TFtype d = (UWtype) (u >> WORD_SIZE); + d *= HIGH_HALFWORD_COEFF; + d *= HIGH_HALFWORD_COEFF; + d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); + + return d; +} +#endif + #ifdef L_floatdidf #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) @@ -1365,6 +1399,23 @@ __floatdidf (DWtype u) } #endif +#ifdef L_floatundidf +#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) + +DFtype +__floatundidf (UDWtype u) +{ + DFtype d = (UWtype) (u >> WORD_SIZE); + d *= HIGH_HALFWORD_COEFF; + d *= HIGH_HALFWORD_COEFF; + d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); + + return d; +} +#endif + #ifdef L_floatdisf #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) @@ -1409,6 +1460,49 @@ __floatdisf (DWtype u) } #endif +#ifdef L_floatundisf +#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 SF_SIZE FLT_MANT_DIG + +SFtype +__floatundisf (UDWtype u) +{ + /* 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)) + { +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) + if (u >= ((UDWtype) 1 << DF_SIZE)) + { + if ((UDWtype) u & (REP_BIT - 1)) + { + 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 = (UWtype) (u >> WORD_SIZE); + f *= HIGH_HALFWORD_COEFF; + f *= HIGH_HALFWORD_COEFF; + f += (UWtype) (u & (HIGH_WORD_COEFF - 1)); + + return (SFtype) f; +} +#endif + #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 /* Reenable the normal types, in case limits.h needs them. */ #undef char @@ -1475,6 +1569,246 @@ __fixunssfSI (SFtype a) } #endif +/* 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 == 96) \ + || (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) +# 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) \ + || defined(L_muldc3) || defined(L_divdc3) \ + || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 \ + && (defined(L_mulxc3) || defined(L_divxc3))) \ + || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 \ + && (defined(L_multc3) || defined(L_divtc3))) + +#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 (c == 0.0 && d == 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