| 2007-01-05 Jakub Jelinek <jakub@redhat.com> |
| |
| 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 <joseph@codesourcery.com> |
| |
| * 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 <fjahanian@apple.com> |
| |
| * 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 <rth@redhat.com> |
| |
| * 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 <rguenth@gcc.gnu.org> |
| |
| 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. |
| |
| |
| |
| @@ -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 |
| } |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 <math.h> |
| + and <complex.h>. 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 |