/* 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, 2004, 2005 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
This file is part of GCC.
#define ATTRIBUTE_HIDDEN
#endif
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+/* Work out the largest "word" size that we can deal with on this target. */
+#if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_MAX_UNITS_PER_WORD 8
+#elif (MIN_UNITS_PER_WORD > 2 \
+ || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
+# define LIBGCC2_MAX_UNITS_PER_WORD 4
+#else
+# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
+#endif
+
+/* Work out what word size we are using for this compilation.
+ The value can be set on the command line. */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
+
#include "libgcc2.h"
\f
#ifdef DECLARE_LIBRARY_RENAMES
\f
/* Unless shift functions are defined with full ANSI prototypes,
- parameter b will be promoted to int if word_type is smaller than an int. */
+ parameter b will be promoted to int if shift_count_type is smaller than an int. */
#ifdef L_lshrdi3
DWtype
-__lshrdi3 (DWtype u, word_type b)
+__lshrdi3 (DWtype u, shift_count_type b)
{
if (b == 0)
return u;
const DWunion uu = {.ll = u};
- const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ const shift_count_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
DWunion w;
if (bm <= 0)
#ifdef L_ashldi3
DWtype
-__ashldi3 (DWtype u, word_type b)
+__ashldi3 (DWtype u, shift_count_type b)
{
if (b == 0)
return u;
const DWunion uu = {.ll = u};
- const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ const shift_count_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
DWunion w;
if (bm <= 0)
#ifdef L_ashrdi3
DWtype
-__ashrdi3 (DWtype u, word_type b)
+__ashrdi3 (DWtype u, shift_count_type b)
{
if (b == 0)
return u;
const DWunion uu = {.ll = u};
- const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ const shift_count_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
DWunion w;
if (bm <= 0)
}
#endif
\f
+#ifdef L_bswapsi2
+SItype
+__bswapsi2 (SItype u)
+{
+ return ((((u) & 0xff000000) >> 24)
+ | (((u) & 0x00ff0000) >> 8)
+ | (((u) & 0x0000ff00) << 8)
+ | (((u) & 0x000000ff) << 24));
+}
+#endif
+#ifdef L_bswapdi2
+DItype
+__bswapdi2 (DItype u)
+{
+ return ((((u) & 0xff00000000000000ull) >> 56)
+ | (((u) & 0x00ff000000000000ull) >> 40)
+ | (((u) & 0x0000ff0000000000ull) >> 24)
+ | (((u) & 0x000000ff00000000ull) >> 8)
+ | (((u) & 0x00000000ff000000ull) << 8)
+ | (((u) & 0x0000000000ff0000ull) << 24)
+ | (((u) & 0x000000000000ff00ull) << 40)
+ | (((u) & 0x00000000000000ffull) << 56));
+}
+#endif
#ifdef L_ffssi2
#undef int
int
#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,
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
\f
}
#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,
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
\f
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];
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];
DWtype
__divdi3 (DWtype u, DWtype v)
{
- word_type c = 0;
+ Wtype c = 0;
DWunion uu = {.ll = u};
DWunion vv = {.ll = v};
DWtype w;
DWtype
__moddi3 (DWtype u, DWtype v)
{
- word_type c = 0;
+ Wtype c = 0;
DWunion uu = {.ll = u};
DWunion vv = {.ll = v};
DWtype w;
#endif
\f
#ifdef L_cmpdi2
-word_type
+cmp_return_type
__cmpdi2 (DWtype a, DWtype b)
{
const DWunion au = {.ll = a};
#endif
#ifdef L_ucmpdi2
-word_type
+cmp_return_type
__ucmpdi2 (DWtype a, DWtype b)
{
const DWunion au = {.ll = a};
#endif
\f
#if defined(L_fixunstfdi) && LIBGCC2_HAS_TF_MODE
-DWtype
+UDWtype
__fixunstfDI (TFtype a)
{
if (a < 0)
#endif
#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE
-DWtype
+UDWtype
__fixunsxfDI (XFtype a)
{
if (a < 0)
#endif
#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
-DWtype
+UDWtype
__fixunsdfDI (DFtype a)
{
/* Get high part of result. The division here will just moves the radix
#endif
#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE
-DWtype
+UDWtype
__fixunssfDI (SFtype a)
{
#if LIBGCC2_HAS_DF_MODE
XFtype
__floatdixf (DWtype u)
{
+#if W_TYPE_SIZE > XF_SIZE
+# error
+#endif
XFtype d = (Wtype) (u >> W_TYPE_SIZE);
d *= Wtype_MAXp1_F;
d += (UWtype)u;
}
#endif
+#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)
{
+#if W_TYPE_SIZE > TF_SIZE
+# error
+#endif
TFtype d = (Wtype) (u >> W_TYPE_SIZE);
d *= Wtype_MAXp1_F;
d += (UWtype)u;
}
#endif
-#if defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE
-DFtype
-__floatdidf (DWtype u)
+#if defined(L_floatunditf) && LIBGCC2_HAS_TF_MODE
+TFtype
+__floatunditf (UDWtype u)
{
- DFtype d = (Wtype) (u >> W_TYPE_SIZE);
+#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
-#if defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE
+#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE)
#define DI_SIZE (W_TYPE_SIZE * 2)
-#define SF_SIZE FLT_MANT_DIG
+#define F_MODE_OK(SIZE) \
+ (SIZE < DI_SIZE \
+ && SIZE > (DI_SIZE - SIZE + FSSIZE) \
+ && !AVOID_FP_TYPE_CONVERSION(SIZE))
+#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
-SFtype
-__floatdisf (DWtype u)
+FSTYPE
+FUNC (DWtype u)
{
-#if SF_SIZE >= W_TYPE_SIZE
+#if FSSIZE >= W_TYPE_SIZE
/* When the word size is small, we never get any rounding error. */
- SFtype f = (Wtype) (u >> W_TYPE_SIZE);
+ FSTYPE f = (Wtype) (u >> W_TYPE_SIZE);
f *= Wtype_MAXp1_F;
f += (UWtype)u;
return f;
-#elif LIBGCC2_HAS_DF_MODE
-
-#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
+#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 - DF_SIZE))
+#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 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))
+ of the FSTYPE. A fixed mask and bit position handles all usual
+ configurations. */
+ if (! (- ((DWtype) 1 << FSIZE) < u
+ && u < ((DWtype) 1 << FSIZE)))
{
- 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 >> W_TYPE_SIZE);
+ /* 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 (SFtype) f;
+ return (FSTYPE) 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 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 (SFtype)(Wtype)u;
+ return (FSTYPE)(Wtype)u;
/* Otherwise, find the power of two. */
Wtype hi = u >> W_TYPE_SIZE;
/* No leading bits means u == minimum. */
if (count == 0)
- return -(Wtype_MAXp1_F * Wtype_MAXp1_F / 2);
+ return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2));
- shift = W_TYPE_SIZE - count;
+ shift = 1 + 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))
+ if ((UWtype)u << (W_TYPE_SIZE - shift))
hi |= 1;
/* Convert the one word of data, and rescale. */
- SFtype f = hi;
- f *= (UWtype)1 << shift;
+ FSTYPE f = hi, e;
+ if (shift == W_TYPE_SIZE)
+ e = Wtype_MAXp1_F;
+ /* The following two cases could be merged if we knew that the target
+ supported a native unsigned->float conversion. More often, we only
+ have a signed conversion, and have to add extra fixup code. */
+ else if (shift == W_TYPE_SIZE - 1)
+ e = Wtype_MAXp1_F / 2;
+ else
+ e = (Wtype)1 << shift;
+ return f * e;
+#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) \
+ && !AVOID_FP_TYPE_CONVERSION(SIZE))
+#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 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))
+ {
+ 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 = (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 ((UWtype)u << (W_TYPE_SIZE - shift))
+ hi |= 1;
+
+ /* Convert the one word of data, and rescale. */
+ FSTYPE f = hi, e;
+ if (shift == W_TYPE_SIZE)
+ e = Wtype_MAXp1_F;
+ /* The following two cases could be merged if we knew that the target
+ supported a native unsigned->float conversion. More often, we only
+ have a signed conversion, and have to add extra fixup code. */
+ else if (shift == W_TYPE_SIZE - 1)
+ e = Wtype_MAXp1_F / 2;
+ else
+ e = (Wtype)1 << shift;
+ return f * e;
#endif
}
#endif
# define MTYPE TFtype
# define CTYPE TCtype
# define MODE tc
-# define CEXT l
+# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
+# define CEXT l
+# else
+# define CEXT LIBGCC2_TF_CEXT
+# endif
# define NOTRUNC 1
#else
# error
{
MTYPE denom, ratio, x, y;
- /* ??? We can get better behavior from logarithmic scaling instead of
+ /* ??? 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... */
are nonzero/zero, infinite/finite, and finite/infinite. */
if (isnan (x) && isnan (y))
{
- if (denom == 0.0 && (!isnan (a) || !isnan (b)))
+ if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b)))
{
x = COPYSIGN (INFINITY, c) * a;
y = COPYSIGN (INFINITY, c) * b;
#endif
#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
#endif /* L_ctors */
+#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */