2009-04-03 15:46:17

by Bastian Blank

[permalink] [raw]
Subject: [RFC][PATCH 0/5] Add and use libgcc

Hi

gcc always expects to be able to use the symbols in libgcc for
operations that are unsupported on the CPU. Linux added functions if
needed or just worked around such operations. Sometimes it even
describes the compiler as broken, even if it is properly documented by
gcc themself.

This patchset adds a copy of libgcc to the kernel and uses it if to do
such unsupported operations. This way we can remove the usage of
workarounds like do_div.

Unsolved problems:
- It currently uses the gcc-included longlong division support which is marked
as possibly trapping.
- The libgcc sources are currently unmodifed copies from gcc, this means
it needs some headers with fixed names.

Bastian

--
Leave bigotry in your quarters; there's no room for it on the bridge.
-- Kirk, "Balance of Terror", stardate 1709.2


2009-04-03 15:45:39

by Bastian Blank

[permalink] [raw]
Subject: Re: [RFC][PATCH 0/5] Add and use libgcc

gcc always expects to be able to use the symbols in libgcc for
operations that are unsupported on the CPU. Linux added functions if
needed or just worked around such operations.

Signed-off-by: Bastian Blank <[email protected]>
---
lib/libgcc/libgcc2.c | 2223 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libgcc/libgcc2.h | 466 +++++++++++
2 files changed, 2689 insertions(+), 0 deletions(-)
create mode 100644 lib/libgcc/libgcc2.c
create mode 100644 lib/libgcc/libgcc2.h

diff --git a/lib/libgcc/libgcc2.c b/lib/libgcc/libgcc2.c
new file mode 100644
index 0000000..792bfe6
--- /dev/null
+++ b/lib/libgcc/libgcc2.c
@@ -0,0 +1,2223 @@
+/* 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, 2007 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+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, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
+#else
+#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"
+
+#ifdef DECLARE_LIBRARY_RENAMES
+ DECLARE_LIBRARY_RENAMES
+#endif
+
+#if defined (L_negdi2)
+DWtype
+__negdi2 (DWtype u)
+{
+ const DWunion uu = {.ll = u};
+ const DWunion w = { {.low = -uu.s.low,
+ .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_addvsi3
+Wtype
+__addvSI3 (Wtype a, Wtype b)
+{
+ const Wtype w = a + b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
+
+ 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)
+{
+ const DWtype w = a + b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
+
+ return w;
+}
+#endif
+
+#ifdef L_subvsi3
+Wtype
+__subvSI3 (Wtype a, Wtype 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)
+{
+ const DWtype w = a - b;
+
+ if (b >= 0 ? w > a : w < a)
+ abort ();
+
+ return w;
+}
+#endif
+
+#ifdef L_mulvsi3
+Wtype
+__mulvSI3 (Wtype a, Wtype b)
+{
+ const DWtype w = (DWtype) a * (DWtype) b;
+
+ 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)
+{
+ const Wtype w = -a;
+
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ 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)
+{
+ const DWtype w = -a;
+
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ return w;
+}
+#endif
+
+#ifdef L_absvsi2
+Wtype
+__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;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+#endif
+
+#ifdef L_absvdi2
+DWtype
+__absvDI2 (DWtype a)
+{
+ DWtype w = a;
+
+ if (a < 0)
+#ifdef L_negvdi2
+ w = __negvDI2 (a);
+#else
+ w = -a;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#endif
+
+#ifdef L_mulvdi3
+DWtype
+__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 >> (W_TYPE_SIZE - 1), 1))
+ {
+ /* u fits in a single Wtype. */
+ 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. */
+ return (DWtype) uu.s.low * (DWtype) vv.s.low;
+ }
+ else
+ {
+ /* Two multiplications. */
+ DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+ DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.high};
+
+ if (vv.s.high < 0)
+ w1.s.high -= uu.s.low;
+ if (uu.s.low < 0)
+ w1.ll -= vv.ll;
+ w1.ll += (UWtype) w0.s.high;
+ if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ w0.s.high = w1.s.low;
+ return w0.ll;
+ }
+ }
+ }
+ else
+ {
+ if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ /* v fits into a single Wtype. */
+ /* Two multiplications. */
+ DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+ DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high
+ * (UDWtype) (UWtype) vv.s.low};
+
+ if (uu.s.high < 0)
+ w1.s.high -= vv.s.low;
+ if (vv.s.low < 0)
+ w1.ll -= uu.ll;
+ w1.ll += (UWtype) w0.s.high;
+ if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ w0.s.high = w1.s.low;
+ return w0.ll;
+ }
+ }
+ else
+ {
+ /* A few sign checks and a single multiplication. */
+ if (uu.s.high >= 0)
+ {
+ if (vv.s.high >= 0)
+ {
+ if (uu.s.high == 0 && vv.s.high == 0)
+ {
+ const DWtype w = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low;
+ if (__builtin_expect (w >= 0, 1))
+ return w;
+ }
+ }
+ else
+ {
+ if (uu.s.high == 0 && vv.s.high == (Wtype) -1)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= uu.s.low;
+ if (__builtin_expect (ww.s.high < 0, 1))
+ return ww.ll;
+ }
+ }
+ }
+ else
+ {
+ if (vv.s.high >= 0)
+ {
+ if (uu.s.high == (Wtype) -1 && vv.s.high == 0)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= vv.s.low;
+ if (__builtin_expect (ww.s.high < 0, 1))
+ return ww.ll;
+ }
+ }
+ else
+ {
+ if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= uu.s.low;
+ ww.s.high -= vv.s.low;
+ if (__builtin_expect (ww.s.high >= 0, 1))
+ return ww.ll;
+ }
+ }
+ }
+ }
+ }
+
+ /* Overflow. */
+ abort ();
+}
+#endif
+
+
+/* Unless shift functions are defined with full ANSI prototypes,
+ parameter b will be promoted to int if shift_count_type is smaller than an int. */
+#ifdef L_lshrdi3
+DWtype
+__lshrdi3 (DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ DWunion w;
+
+ if (bm <= 0)
+ {
+ w.s.high = 0;
+ w.s.low = (UWtype) uu.s.high >> -bm;
+ }
+ else
+ {
+ const UWtype carries = (UWtype) uu.s.high << bm;
+
+ w.s.high = (UWtype) uu.s.high >> b;
+ w.s.low = ((UWtype) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_ashldi3
+DWtype
+__ashldi3 (DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ DWunion w;
+
+ if (bm <= 0)
+ {
+ w.s.low = 0;
+ w.s.high = (UWtype) uu.s.low << -bm;
+ }
+ else
+ {
+ const UWtype carries = (UWtype) uu.s.low >> bm;
+
+ w.s.low = (UWtype) uu.s.low << b;
+ w.s.high = ((UWtype) uu.s.high << b) | carries;
+ }
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_ashrdi3
+DWtype
+__ashrdi3 (DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ DWunion w;
+
+ if (bm <= 0)
+ {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
+ w.s.low = uu.s.high >> -bm;
+ }
+ else
+ {
+ const UWtype carries = (UWtype) uu.s.high << bm;
+
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((UWtype) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+#endif
+
+#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
+__ffsSI2 (UWtype u)
+{
+ UWtype count;
+
+ if (u == 0)
+ return 0;
+
+ count_trailing_zeros (count, u);
+ return count + 1;
+}
+#endif
+
+#ifdef L_ffsdi2
+#undef int
+int
+__ffsDI2 (DWtype u)
+{
+ const DWunion uu = {.ll = u};
+ UWtype word, count, add;
+
+ if (uu.s.low != 0)
+ word = uu.s.low, add = 0;
+ else if (uu.s.high != 0)
+ word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype);
+ else
+ return 0;
+
+ count_trailing_zeros (count, word);
+ return count + add + 1;
+}
+#endif
+
+#ifdef L_muldi3
+DWtype
+__muldi3 (DWtype u, DWtype v)
+{
+ const DWunion uu = {.ll = u};
+ const DWunion vv = {.ll = v};
+ DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
+
+ w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
+ + (UWtype) uu.s.high * (UWtype) vv.s.low);
+
+ return w.ll;
+}
+#endif
+
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+#if defined (sdiv_qrnnd)
+#define L_udiv_w_sdiv
+#endif
+#endif
+
+#ifdef L_udiv_w_sdiv
+#if defined (sdiv_qrnnd)
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
+UWtype
+__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
+{
+ UWtype q, r;
+ UWtype c0, c1, b1;
+
+ if ((Wtype) d >= 0)
+ {
+ if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
+ {
+ /* 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. */
+ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
+ /* Divide (c1*2^32 + c0) by d. */
+ sdiv_qrnnd (q, r, c1, c0, d);
+ /* Add 2^31 to quotient. */
+ q += (UWtype) 1 << (W_TYPE_SIZE - 1);
+ }
+ }
+ else
+ {
+ b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
+ c1 = a1 >> 1; /* A/2 */
+ c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
+
+ if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
+ {
+ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+ r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
+ if ((d & 1) != 0)
+ {
+ if (r >= q)
+ r = r - q;
+ else if (q - r <= d)
+ {
+ r = r - q + d;
+ q--;
+ }
+ else
+ {
+ r = r - q + 2*d;
+ q -= 2;
+ }
+ }
+ }
+ else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
+ {
+ c1 = (b1 - 1) - c1;
+ c0 = ~c0; /* logical NOT */
+
+ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+ q = ~q; /* (A/2)/b1 */
+ r = (b1 - 1) - r;
+
+ r = 2*r + (a0 & 1); /* A/(2*b1) */
+
+ if ((d & 1) != 0)
+ {
+ if (r >= q)
+ r = r - q;
+ else if (q - r <= d)
+ {
+ r = r - q + d;
+ q--;
+ }
+ else
+ {
+ r = r - q + 2*d;
+ q -= 2;
+ }
+ }
+ }
+ else /* Implies c1 = b1 */
+ { /* Hence a1 = d - 1 = 2*b1 - 1 */
+ if (a0 >= -d)
+ {
+ q = -1;
+ r = a0 + d;
+ }
+ else
+ {
+ q = -2;
+ r = a0 + 2*d;
+ }
+ }
+ }
+
+ *rp = r;
+ return q;
+}
+#else
+/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
+UWtype
+__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
+ UWtype a1 __attribute__ ((__unused__)),
+ UWtype a0 __attribute__ ((__unused__)),
+ UWtype d __attribute__ ((__unused__)))
+{
+ return 0;
+}
+#endif
+#endif
+
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+#define L_udivmoddi4
+#endif
+
+#ifdef L_clz
+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,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,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
+int
+__clzSI2 (UWtype x)
+{
+ Wtype ret;
+
+ count_leading_zeros (ret, x);
+
+ return ret;
+}
+#endif
+
+#ifdef L_clzdi2
+#undef int
+int
+__clzDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.high)
+ word = uu.s.high, add = 0;
+ else
+ word = uu.s.low, add = W_TYPE_SIZE;
+
+ count_leading_zeros (ret, word);
+ return ret + add;
+}
+#endif
+
+#ifdef L_ctzsi2
+#undef int
+int
+__ctzSI2 (UWtype x)
+{
+ Wtype ret;
+
+ count_trailing_zeros (ret, x);
+
+ return ret;
+}
+#endif
+
+#ifdef L_ctzdi2
+#undef int
+int
+__ctzDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.low)
+ word = uu.s.low, add = 0;
+ else
+ word = uu.s.high, add = W_TYPE_SIZE;
+
+ count_trailing_zeros (ret, word);
+ return ret + add;
+}
+#endif
+
+#ifdef L_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,
+ 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
+};
+#endif
+
+#ifdef L_popcountsi2
+#undef int
+int
+__popcountSI2 (UWtype x)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < W_TYPE_SIZE; i += 8)
+ ret += __popcount_tab[(x >> i) & 0xff];
+
+ return ret;
+}
+#endif
+
+#ifdef L_popcountdi2
+#undef int
+int
+__popcountDI2 (UDWtype x)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
+ ret += __popcount_tab[(x >> i) & 0xff];
+
+ return ret;
+}
+#endif
+
+#ifdef L_paritysi2
+#undef int
+int
+__paritySI2 (UWtype x)
+{
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+ x ^= x >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+ x ^= x >> 16;
+#endif
+ x ^= x >> 8;
+ x ^= x >> 4;
+ x &= 0xf;
+ return (0x6996 >> x) & 1;
+}
+#endif
+
+#ifdef L_paritydi2
+#undef int
+int
+__parityDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype nx = uu.s.low ^ uu.s.high;
+
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+ nx ^= nx >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+ nx ^= nx >> 16;
+#endif
+ nx ^= nx >> 8;
+ nx ^= nx >> 4;
+ nx &= 0xf;
+ return (0x6996 >> nx) & 1;
+}
+#endif
+
+#ifdef L_udivmoddi4
+
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
+UDWtype
+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
+{
+ const DWunion nn = {.ll = n};
+ const DWunion dd = {.ll = d};
+ DWunion rr;
+ UWtype d0, d1, n0, n1, n2;
+ UWtype q0, q1;
+ UWtype b, bm;
+
+ d0 = dd.s.low;
+ d1 = dd.s.high;
+ n0 = nn.s.low;
+ n1 = nn.s.high;
+
+#if !UDIV_NEEDS_NORMALIZATION
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ udiv_qrnnd (q1, n1, 0, n1, d0);
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm != 0)
+ {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm == 0)
+ {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of W_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ }
+ else
+ {
+ /* Normalize. */
+
+ b = W_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0 >> bm;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+#endif /* UDIV_NEEDS_NORMALIZATION */
+
+ else
+ {
+ if (d1 > n1)
+ {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ /* 0q = NN / dd */
+
+ count_leading_zeros (bm, d1);
+ if (bm == 0)
+ {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0)
+ {
+ q0 = 1;
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ }
+ else
+ q0 = 0;
+
+ q1 = 0;
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ UWtype m1, m0;
+ /* Normalize. */
+
+ b = W_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q0, n1, n2, n1, d1);
+ umul_ppmm (m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0))
+ {
+ q0--;
+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ if (rp != 0)
+ {
+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ rr.s.low = (n1 << b) | (n0 >> bm);
+ rr.s.high = n1 >> bm;
+ *rp = rr.ll;
+ }
+ }
+ }
+ }
+
+ const DWunion ww = {{.low = q0, .high = q1}};
+ return ww.ll;
+}
+#endif
+
+#ifdef L_divdi3
+DWtype
+__divdi3 (DWtype u, DWtype v)
+{
+ Wtype c = 0;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
+ DWtype w;
+
+ if (uu.s.high < 0)
+ c = ~c,
+ uu.ll = -uu.ll;
+ if (vv.s.high < 0)
+ c = ~c,
+ vv.ll = -vv.ll;
+
+ w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
+ if (c)
+ w = -w;
+
+ return w;
+}
+#endif
+
+#ifdef L_moddi3
+DWtype
+__moddi3 (DWtype u, DWtype v)
+{
+ Wtype c = 0;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
+ DWtype w;
+
+ if (uu.s.high < 0)
+ c = ~c,
+ uu.ll = -uu.ll;
+ if (vv.s.high < 0)
+ vv.ll = -vv.ll;
+
+ (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
+ if (c)
+ w = -w;
+
+ return w;
+}
+#endif
+
+#ifdef L_umoddi3
+UDWtype
+__umoddi3 (UDWtype u, UDWtype v)
+{
+ UDWtype w;
+
+ (void) __udivmoddi4 (u, v, &w);
+
+ return w;
+}
+#endif
+
+#ifdef L_udivdi3
+UDWtype
+__udivdi3 (UDWtype n, UDWtype d)
+{
+ return __udivmoddi4 (n, d, (UDWtype *) 0);
+}
+#endif
+
+#ifdef L_cmpdi2
+cmp_return_type
+__cmpdi2 (DWtype a, DWtype b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if (au.s.high < bu.s.high)
+ return 0;
+ else if (au.s.high > bu.s.high)
+ return 2;
+ if ((UWtype) au.s.low < (UWtype) bu.s.low)
+ return 0;
+ else if ((UWtype) au.s.low > (UWtype) bu.s.low)
+ return 2;
+ return 1;
+}
+#endif
+
+#ifdef L_ucmpdi2
+cmp_return_type
+__ucmpdi2 (DWtype a, DWtype b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if ((UWtype) au.s.high < (UWtype) bu.s.high)
+ return 0;
+ else if ((UWtype) au.s.high > (UWtype) bu.s.high)
+ return 2;
+ if ((UWtype) au.s.low < (UWtype) bu.s.low)
+ return 0;
+ else if ((UWtype) au.s.low > (UWtype) bu.s.low)
+ return 2;
+ return 1;
+}
+#endif
+
+#if defined(L_fixunstfdi) && LIBGCC2_HAS_TF_MODE
+UDWtype
+__fixunstfDI (TFtype a)
+{
+ if (a < 0)
+ return 0;
+
+ /* Compute high word of result, as a flonum. */
+ 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 <<= 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.
+ Sometimes A comes out negative. This is significant, since
+ A has more bits than a long int does. */
+ if (a < 0)
+ v -= (UWtype) (- a);
+ else
+ v += (UWtype) a;
+ return v;
+}
+#endif
+
+#if defined(L_fixtfdi) && LIBGCC2_HAS_TF_MODE
+DWtype
+__fixtfdi (TFtype a)
+{
+ if (a < 0)
+ return - __fixunstfDI (-a);
+ return __fixunstfDI (a);
+}
+#endif
+
+#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE
+UDWtype
+__fixunsxfDI (XFtype a)
+{
+ if (a < 0)
+ return 0;
+
+ /* Compute high word of result, as a flonum. */
+ 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 <<= 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.
+ Sometimes A comes out negative. This is significant, since
+ A has more bits than a long int does. */
+ if (a < 0)
+ v -= (UWtype) (- a);
+ else
+ v += (UWtype) a;
+ return v;
+}
+#endif
+
+#if defined(L_fixxfdi) && LIBGCC2_HAS_XF_MODE
+DWtype
+__fixxfdi (XFtype a)
+{
+ if (a < 0)
+ return - __fixunsxfDI (-a);
+ return __fixunsxfDI (a);
+}
+#endif
+
+#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
+UDWtype
+__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 / 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 * Wtype_MAXp1_F;
+
+ /* Assemble result from the two parts. */
+ return ((UDWtype) hi << W_TYPE_SIZE) | lo;
+}
+#endif
+
+#if defined(L_fixdfdi) && LIBGCC2_HAS_DF_MODE
+DWtype
+__fixdfdi (DFtype a)
+{
+ if (a < 0)
+ return - __fixunsdfDI (-a);
+ return __fixunsdfDI (a);
+}
+#endif
+
+#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE
+UDWtype
+__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 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 = 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 = dfa - (DFtype) hi * Wtype_MAXp1_F;
+
+ /* Assemble result from the two parts. */
+ 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
+
+#if defined(L_fixsfdi) && LIBGCC2_HAS_SF_MODE
+DWtype
+__fixsfdi (SFtype a)
+{
+ if (a < 0)
+ return - __fixunssfDI (-a);
+ return __fixunssfDI (a);
+}
+#endif
+
+#if defined(L_floatdixf) && LIBGCC2_HAS_XF_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;
+ return d;
+}
+#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;
+ 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
+
+#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) \
+ && !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
+
+FSTYPE
+FUNC (DWtype u)
+{
+#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
+
+#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;
+
+ /* 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
+
+#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
+
+#if defined(L_fixunsxfsi) && LIBGCC2_HAS_XF_MODE
+/* Reenable the normal types, in case limits.h needs them. */
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+#undef MIN
+#undef MAX
+#include <limits.h>
+
+UWtype
+__fixunsxfSI (XFtype a)
+{
+ if (a >= - (DFtype) Wtype_MIN)
+ return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+ return (Wtype) a;
+}
+#endif
+
+#if defined(L_fixunsdfsi) && LIBGCC2_HAS_DF_MODE
+/* Reenable the normal types, in case limits.h needs them. */
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+#undef MIN
+#undef MAX
+#include <limits.h>
+
+UWtype
+__fixunsdfSI (DFtype a)
+{
+ if (a >= - (DFtype) Wtype_MIN)
+ return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+ return (Wtype) a;
+}
+#endif
+
+#if defined(L_fixunssfsi) && LIBGCC2_HAS_SF_MODE
+/* Reenable the normal types, in case limits.h needs them. */
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+#undef MIN
+#undef MAX
+#include <limits.h>
+
+UWtype
+__fixunssfSI (SFtype a)
+{
+ if (a >= - (SFtype) Wtype_MIN)
+ return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+ return (Wtype) 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
+# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
+# define CEXT l
+# else
+# define CEXT LIBGCC2_TF_CEXT
+# endif
+# 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
+#define USItype bogus_type
+#define DItype bogus_type
+#define UDItype bogus_type
+#define SFtype bogus_type
+#define DFtype bogus_type
+#undef Wtype
+#undef UWtype
+#undef HWtype
+#undef UHWtype
+#undef DWtype
+#undef UDWtype
+
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+
+#ifdef L__gcc_bcmp
+
+/* Like bcmp except the sign is meaningful.
+ Result is negative if S1 is less than S2,
+ positive if S1 is greater, 0 if S1 and S2 are equal. */
+
+int
+__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
+{
+ while (size > 0)
+ {
+ const unsigned char c1 = *s1++, c2 = *s2++;
+ if (c1 != c2)
+ return c1 - c2;
+ size--;
+ }
+ return 0;
+}
+
+#endif
+
+/* __eprintf used to be used by GCC's private version of <assert.h>.
+ We no longer provide that header, but this routine remains in libgcc.a
+ for binary backward compatibility. Note that it is not included in
+ the shared version of libgcc. */
+#ifdef L_eprintf
+#ifndef inhibit_libc
+
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
+#include <stdio.h>
+
+void
+__eprintf (const char *string, const char *expression,
+ unsigned int line, const char *filename)
+{
+ fprintf (stderr, string, expression, line, filename);
+ fflush (stderr);
+ abort ();
+}
+
+#endif
+#endif
+
+
+#ifdef L_clear_cache
+/* Clear part of an instruction cache. */
+
+void
+__clear_cache (char *beg __attribute__((__unused__)),
+ char *end __attribute__((__unused__)))
+{
+#ifdef CLEAR_INSN_CACHE
+ CLEAR_INSN_CACHE (beg, end);
+#endif /* CLEAR_INSN_CACHE */
+}
+
+#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)
+
+int
+getpagesize (void)
+{
+#ifdef _ALPHA_
+ return 8192;
+#else
+ return 4096;
+#endif
+}
+
+#ifdef __i386__
+extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
+#endif
+
+int
+mprotect (char *addr, int len, int prot)
+{
+ int np, op;
+
+ if (prot == 7)
+ np = 0x40;
+ else if (prot == 5)
+ np = 0x20;
+ else if (prot == 4)
+ np = 0x10;
+ else if (prot == 3)
+ np = 0x04;
+ else if (prot == 1)
+ np = 0x02;
+ else if (prot == 0)
+ np = 0x01;
+
+ if (VirtualProtect (addr, len, np, &op))
+ return 0;
+ else
+ return -1;
+}
+
+#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
+
+#ifdef TRANSFER_FROM_TRAMPOLINE
+TRANSFER_FROM_TRAMPOLINE
+#endif
+#endif /* L_trampoline */
+
+#ifndef __CYGWIN__
+#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
+ must define both, or neither. */
+#ifndef NAME__MAIN
+#define NAME__MAIN "__main"
+#define SYMBOL__MAIN __main
+#endif
+
+#if defined (INIT_SECTION_ASM_OP) || defined (INIT_ARRAY_SECTION_ASM_OP)
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+#endif
+
+#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
+
+/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
+ code to run constructors. In that case, we need to handle EH here, too. */
+
+#ifdef EH_FRAME_SECTION_NAME
+#include "unwind-dw2-fde.h"
+extern unsigned char __EH_FRAME_BEGIN__[];
+#endif
+
+/* Run all the global destructors on exit from the program. */
+
+void
+__do_global_dtors (void)
+{
+#ifdef DO_GLOBAL_DTORS_BODY
+ DO_GLOBAL_DTORS_BODY;
+#else
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ while (*p)
+ {
+ p++;
+ (*(p-1)) ();
+ }
+#endif
+#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
+ {
+ static int completed = 0;
+ if (! completed)
+ {
+ completed = 1;
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+ }
+ }
+#endif
+}
+#endif
+
+#ifndef HAS_INIT_SECTION
+/* Run all the global constructors on entry to the program. */
+
+void
+__do_global_ctors (void)
+{
+#ifdef EH_FRAME_SECTION_NAME
+ {
+ static struct object object;
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+ }
+#endif
+ DO_GLOBAL_CTORS_BODY;
+ atexit (__do_global_dtors);
+}
+#endif /* no HAS_INIT_SECTION */
+
+#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
+/* Subroutine called automatically by `main'.
+ Compiling a global function named `main'
+ produces an automatic call to this function at the beginning.
+
+ For many systems, this routine calls __do_global_ctors.
+ For systems which support a .init section we use the .init section
+ to run __do_global_ctors, so we need not do anything here. */
+
+extern void SYMBOL__MAIN (void);
+void
+SYMBOL__MAIN (void)
+{
+ /* Support recursive calls to `main': run initializers just once. */
+ static int initialized;
+ if (! initialized)
+ {
+ initialized = 1;
+ __do_global_ctors ();
+ }
+}
+#endif /* no HAS_INIT_SECTION or INVOKE__main */
+
+#endif /* L__main */
+#endif /* __CYGWIN__ */
+
+#ifdef L_ctors
+
+#include "gbl-ctors.h"
+
+/* Provide default definitions for the lists of constructors and
+ destructors, so that we don't get linker errors. These symbols are
+ intentionally bss symbols, so that gld and/or collect will provide
+ the right values. */
+
+/* We declare the lists here with two elements each,
+ so that they are valid empty lists if no other definition is loaded.
+
+ If we are using the old "set" extensions to have the gnu linker
+ collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
+ must be in the bss/common section.
+
+ Long term no port should use those extensions. But many still do. */
+#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
+#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
+func_ptr __CTOR_LIST__[2] = {0, 0};
+func_ptr __DTOR_LIST__[2] = {0, 0};
+#else
+func_ptr __CTOR_LIST__[2];
+func_ptr __DTOR_LIST__[2];
+#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 */
diff --git a/lib/libgcc/libgcc2.h b/lib/libgcc/libgcc2.h
new file mode 100644
index 0000000..9f2ca39
--- /dev/null
+++ b/lib/libgcc/libgcc2.h
@@ -0,0 +1,466 @@
+/* Header file for libgcc2.c. */
+/* Copyright (C) 2000, 2001, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+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, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+
+#ifndef GCC_LIBGCC2_H
+#define GCC_LIBGCC2_H
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility push(default)
+#endif
+
+extern int __gcc_bcmp (const unsigned char *, const unsigned char *, size_t);
+extern void __clear_cache (char *, char *);
+extern void __eprintf (const char *, const char *, unsigned int, const char *)
+ __attribute__ ((__noreturn__));
+
+/* Permit the tm.h file to select the endianness to use just for this
+ file. This is used when the endianness is determined when the
+ compiler is run. */
+
+#ifndef LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+#ifndef LIBGCC2_DOUBLE_TYPE_SIZE
+#define LIBGCC2_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
+#endif
+#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
+#endif
+
+#ifndef LIBGCC2_HAS_SF_MODE
+#define LIBGCC2_HAS_SF_MODE (BITS_PER_UNIT == 8)
+#endif
+
+#ifndef LIBGCC2_HAS_DF_MODE
+#define LIBGCC2_HAS_DF_MODE \
+ (BITS_PER_UNIT == 8 \
+ && (LIBGCC2_DOUBLE_TYPE_SIZE == 64 \
+ || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64))
+#endif
+
+#ifndef LIBGCC2_HAS_XF_MODE
+#define LIBGCC2_HAS_XF_MODE \
+ (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+#endif
+
+#ifndef LIBGCC2_HAS_TF_MODE
+#define LIBGCC2_HAS_TF_MODE \
+ (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+#endif
+
+#ifndef SF_SIZE
+#if LIBGCC2_HAS_SF_MODE
+#define SF_SIZE FLT_MANT_DIG
+#else
+#define SF_SIZE 0
+#endif
+#endif
+
+#ifndef DF_SIZE
+#if 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
+#else
+#define DF_SIZE 0
+#endif
+#else
+#define DF_SIZE 0
+#endif
+#endif
+
+#ifndef XF_SIZE
+#if LIBGCC2_HAS_XF_MODE
+#define XF_SIZE LDBL_MANT_DIG
+#else
+#define XF_SIZE 0
+#endif
+#endif
+
+#ifndef TF_SIZE
+#if LIBGCC2_HAS_TF_MODE
+#define TF_SIZE LDBL_MANT_DIG
+#else
+#define TF_SIZE 0
+#endif
+#endif
+
+/* FIXME: This #ifdef probably should be removed, ie. enable the test
+ for mips too. */
+/* Don't use IBM Extended Double TFmode for TI->SF calculations.
+ The conversion from long double to float suffers from double
+ rounding, because we convert via double. In other cases, going
+ through the software fp routines is much slower than the fallback. */
+#ifdef __powerpc__
+#define AVOID_FP_TYPE_CONVERSION(SIZE) (SIZE == 106)
+#elif defined(WIDEST_HARDWARE_FP_SIZE)
+#define AVOID_FP_TYPE_CONVERSION(SIZE) (SIZE > WIDEST_HARDWARE_FP_SIZE)
+#else
+#define AVOID_FP_TYPE_CONVERSION(SIZE) 0
+#endif
+
+/* In the first part of this file, we are interfacing to calls generated
+ by the compiler itself. These calls pass values into these routines
+ which have very specific modes (rather than very specific types), and
+ these compiler-generated calls also expect any return values to have
+ very specific modes (rather than very specific types). Thus, we need
+ to avoid using regular C language type names in this part of the file
+ because the sizes for those types can be configured to be anything.
+ Instead we use the following special type names. */
+
+typedef int QItype __attribute__ ((mode (QI)));
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int HItype __attribute__ ((mode (HI)));
+typedef unsigned int UHItype __attribute__ ((mode (HI)));
+#if MIN_UNITS_PER_WORD > 1
+/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1. */
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+#if LONG_LONG_TYPE_SIZE > 32
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2. */
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+#if MIN_UNITS_PER_WORD > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4. */
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#endif
+#endif
+#endif
+
+#if LIBGCC2_HAS_SF_MODE
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef _Complex float SCtype __attribute__ ((mode (SC)));
+#endif
+#if LIBGCC2_HAS_DF_MODE
+typedef float DFtype __attribute__ ((mode (DF)));
+typedef _Complex float DCtype __attribute__ ((mode (DC)));
+#endif
+#if LIBGCC2_HAS_XF_MODE
+typedef float XFtype __attribute__ ((mode (XF)));
+typedef _Complex float XCtype __attribute__ ((mode (XC)));
+#endif
+#if LIBGCC2_HAS_TF_MODE
+typedef float TFtype __attribute__ ((mode (TF)));
+typedef _Complex float TCtype __attribute__ ((mode (TC)));
+#endif
+
+typedef int cmp_return_type __attribute__((mode (__libgcc_cmp_return__)));
+typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
+
+/* Make sure that we don't accidentally use any normal C language built-in
+ type names in the first part of this file. Instead we want to use *only*
+ the type names defined above. The following macro definitions insure
+ that if we *do* accidentally use some normal C language built-in type name,
+ we will get a syntax error. */
+
+#define char bogus_type
+#define short bogus_type
+#define int bogus_type
+#define long bogus_type
+#define unsigned bogus_type
+#define float bogus_type
+#define double bogus_type
+
+/* Versions prior to 3.4.4 were not taking into account the word size for
+ the 5 trapping arithmetic functions absv, addv, subv, mulv and negv. As
+ a consequence, the si and di variants were always and the only ones emitted.
+ To maintain backward compatibility, COMPAT_SIMODE_TRAPPING_ARITHMETIC is
+ defined on platforms where it makes sense to still have the si variants
+ emitted. As a bonus, their implementation is now correct. Note that the
+ same mechanism should have been implemented for the di variants, but it
+ turns out that no platform would define COMPAT_DIMODE_TRAPPING_ARITHMETIC
+ if it existed. */
+
+#if LIBGCC2_UNITS_PER_WORD == 8
+#define W_TYPE_SIZE (8 * BITS_PER_UNIT)
+#define Wtype DItype
+#define UWtype UDItype
+#define HWtype DItype
+#define UHWtype UDItype
+#define DWtype TItype
+#define UDWtype UTItype
+#define __NW(a,b) __ ## a ## di ## b
+#define __NDW(a,b) __ ## a ## ti ## b
+#define COMPAT_SIMODE_TRAPPING_ARITHMETIC
+#elif LIBGCC2_UNITS_PER_WORD == 4
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+#define Wtype SItype
+#define UWtype USItype
+#define HWtype SItype
+#define UHWtype USItype
+#define DWtype DItype
+#define UDWtype UDItype
+#define __NW(a,b) __ ## a ## si ## b
+#define __NDW(a,b) __ ## a ## di ## b
+#elif LIBGCC2_UNITS_PER_WORD == 2
+#define W_TYPE_SIZE (2 * BITS_PER_UNIT)
+#define Wtype HItype
+#define UWtype UHItype
+#define HWtype HItype
+#define UHWtype UHItype
+#define DWtype SItype
+#define UDWtype USItype
+#define __NW(a,b) __ ## a ## hi ## b
+#define __NDW(a,b) __ ## a ## si ## b
+#else
+#define W_TYPE_SIZE BITS_PER_UNIT
+#define Wtype QItype
+#define UWtype UQItype
+#define HWtype QItype
+#define UHWtype UQItype
+#define DWtype HItype
+#define UDWtype UHItype
+#define __NW(a,b) __ ## a ## qi ## b
+#define __NDW(a,b) __ ## a ## hi ## b
+#endif
+
+#define Wtype_MAX ((Wtype)(((UWtype)1 << (W_TYPE_SIZE - 1)) - 1))
+#define Wtype_MIN (- Wtype_MAX - 1)
+
+#if W_TYPE_SIZE == 8
+# define Wtype_MAXp1_F 0x1p8f
+#elif W_TYPE_SIZE == 16
+# define Wtype_MAXp1_F 0x1p16f
+#elif W_TYPE_SIZE == 32
+# define Wtype_MAXp1_F 0x1p32f
+#elif W_TYPE_SIZE == 64
+# define Wtype_MAXp1_F 0x1p64f
+#else
+# error "expand the table"
+#endif
+
+#define __muldi3 __NDW(mul,3)
+#define __divdi3 __NDW(div,3)
+#define __udivdi3 __NDW(udiv,3)
+#define __moddi3 __NDW(mod,3)
+#define __umoddi3 __NDW(umod,3)
+#define __negdi2 __NDW(neg,2)
+#define __lshrdi3 __NDW(lshr,3)
+#define __ashldi3 __NDW(ashl,3)
+#define __ashrdi3 __NDW(ashr,3)
+#define __cmpdi2 __NDW(cmp,2)
+#define __ucmpdi2 __NDW(ucmp,2)
+#define __udivmoddi4 __NDW(udivmod,4)
+#define __fixunstfDI __NDW(fixunstf,)
+#define __fixtfdi __NDW(fixtf,)
+#define __fixunsxfDI __NDW(fixunsxf,)
+#define __fixxfdi __NDW(fixxf,)
+#define __fixunsdfDI __NDW(fixunsdf,)
+#define __fixdfdi __NDW(fixdf,)
+#define __fixunssfDI __NDW(fixunssf,)
+#define __fixsfdi __NDW(fixsf,)
+#define __floatdixf __NDW(float,xf)
+#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,)
+#define __fixunssfSI __NW(fixunssf,)
+
+#define __absvSI2 __NW(absv,2)
+#define __addvSI3 __NW(addv,3)
+#define __subvSI3 __NW(subv,3)
+#define __mulvSI3 __NW(mulv,3)
+#define __negvSI2 __NW(negv,2)
+#define __absvDI2 __NDW(absv,2)
+#define __addvDI3 __NDW(addv,3)
+#define __subvDI3 __NDW(subv,3)
+#define __mulvDI3 __NDW(mulv,3)
+#define __negvDI2 __NDW(negv,2)
+
+#define __ffsSI2 __NW(ffs,2)
+#define __clzSI2 __NW(clz,2)
+#define __ctzSI2 __NW(ctz,2)
+#define __popcountSI2 __NW(popcount,2)
+#define __paritySI2 __NW(parity,2)
+#define __ffsDI2 __NDW(ffs,2)
+#define __clzDI2 __NDW(clz,2)
+#define __ctzDI2 __NDW(ctz,2)
+#define __popcountDI2 __NDW(popcount,2)
+#define __parityDI2 __NDW(parity,2)
+
+extern DWtype __muldi3 (DWtype, DWtype);
+extern DWtype __divdi3 (DWtype, DWtype);
+extern UDWtype __udivdi3 (UDWtype, UDWtype);
+extern UDWtype __umoddi3 (UDWtype, UDWtype);
+extern DWtype __moddi3 (DWtype, DWtype);
+
+/* __udivmoddi4 is static inline when building other libgcc2 portions. */
+#if (!defined (L_udivdi3) && !defined (L_divdi3) && \
+ !defined (L_umoddi3) && !defined (L_moddi3))
+extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *);
+#endif
+
+/* __negdi2 is static inline when building other libgcc2 portions. */
+#if !defined(L_divdi3) && !defined(L_moddi3)
+extern DWtype __negdi2 (DWtype);
+#endif
+
+extern DWtype __lshrdi3 (DWtype, shift_count_type);
+extern DWtype __ashldi3 (DWtype, shift_count_type);
+extern DWtype __ashrdi3 (DWtype, shift_count_type);
+
+/* __udiv_w_sdiv is static inline when building other libgcc2 portions. */
+#if (!defined(L_udivdi3) && !defined(L_divdi3) && \
+ !defined(L_umoddi3) && !defined(L_moddi3))
+extern UWtype __udiv_w_sdiv (UWtype *, UWtype, UWtype, UWtype);
+#endif
+
+extern cmp_return_type __cmpdi2 (DWtype, DWtype);
+extern cmp_return_type __ucmpdi2 (DWtype, DWtype);
+
+#if MIN_UNITS_PER_WORD > 1
+extern SItype __bswapsi2 (SItype);
+#endif
+#if LONG_LONG_TYPE_SIZE > 32
+extern DItype __bswapdi2 (DItype);
+#endif
+
+extern Wtype __absvSI2 (Wtype);
+extern Wtype __addvSI3 (Wtype, Wtype);
+extern Wtype __subvSI3 (Wtype, Wtype);
+extern Wtype __mulvSI3 (Wtype, Wtype);
+extern Wtype __negvSI2 (Wtype);
+extern DWtype __absvDI2 (DWtype);
+extern DWtype __addvDI3 (DWtype, DWtype);
+extern DWtype __subvDI3 (DWtype, DWtype);
+extern DWtype __mulvDI3 (DWtype, DWtype);
+extern DWtype __negvDI2 (DWtype);
+
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+extern SItype __absvsi2 (SItype);
+extern SItype __addvsi3 (SItype, SItype);
+extern SItype __subvsi3 (SItype, SItype);
+extern SItype __mulvsi3 (SItype, SItype);
+extern SItype __negvsi2 (SItype);
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+
+#undef int
+#if LIBGCC2_HAS_SF_MODE
+extern DWtype __fixsfdi (SFtype);
+extern SFtype __floatdisf (DWtype);
+extern SFtype __floatundisf (UDWtype);
+extern UWtype __fixunssfSI (SFtype);
+extern UDWtype __fixunssfDI (SFtype);
+extern SFtype __powisf2 (SFtype, int);
+extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype);
+extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype);
+#endif
+#if LIBGCC2_HAS_DF_MODE
+extern DWtype __fixdfdi (DFtype);
+extern DFtype __floatdidf (DWtype);
+extern DFtype __floatundidf (UDWtype);
+extern UWtype __fixunsdfSI (DFtype);
+extern UDWtype __fixunsdfDI (DFtype);
+extern DFtype __powidf2 (DFtype, int);
+extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype);
+extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype);
+#endif
+
+#if LIBGCC2_HAS_XF_MODE
+extern DWtype __fixxfdi (XFtype);
+extern UDWtype __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_HAS_TF_MODE
+extern UDWtype __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
+
+/* DWstructs are pairs of Wtype values in the order determined by
+ LIBGCC2_WORDS_BIG_ENDIAN. */
+
+#if LIBGCC2_WORDS_BIG_ENDIAN
+ struct DWstruct {Wtype high, low;};
+#else
+ struct DWstruct {Wtype low, high;};
+#endif
+
+/* We need this union to unpack/pack DImode values, since we don't have
+ any arithmetic yet. Incoming DImode parameters are stored into the
+ `ll' field, and the unpacked result is read from the struct `s'. */
+
+typedef union
+{
+ struct DWstruct s;
+ DWtype ll;
+} DWunion;
+
+/* Defined for L_popcount_tab. Exported here because some targets may
+ want to use it for their own versions of the __popcount builtins. */
+extern const UQItype __popcount_tab[256];
+
+/* Defined for L_clz. Exported here because some targets may want to use
+ it for their own versions of the __clz builtins. It contains the bit
+ position of the first set bit for the numbers 0 - 255. This avoids the
+ need for a separate table for the __ctz builtins. */
+extern const UQItype __clz_tab[256];
+
+#include "longlong.h"
+
+#undef int
+extern int __clzDI2 (UDWtype);
+extern int __clzSI2 (UWtype);
+extern int __ctzSI2 (UWtype);
+extern int __ffsSI2 (UWtype);
+extern int __ffsDI2 (DWtype);
+extern int __ctzDI2 (UDWtype);
+extern int __popcountSI2 (UWtype);
+extern int __popcountDI2 (UDWtype);
+extern int __paritySI2 (UWtype);
+extern int __parityDI2 (UDWtype);
+#define int bogus_type
+
+extern void __enable_execute_stack (void *);
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility pop
+#endif
+
+#endif /* ! GCC_LIBGCC2_H */
--
1.6.2.1

2009-04-03 15:46:40

by Bastian Blank

[permalink] [raw]
Subject: [PATCH 3/5] libgcc: Add Makefile

It only supports the static linkage of the whole lib into vmlinux for
now. Exports are generated.

Signed-off-by: Bastian Blank <[email protected]>
---
lib/Makefile | 2 ++
lib/libgcc/Makefile | 29 +++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
create mode 100644 lib/libgcc/Makefile

diff --git a/lib/Makefile b/lib/Makefile
index d6edd67..521f2d5 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -92,6 +92,8 @@ obj-$(CONFIG_NLATTR) += nlattr.o

obj-$(CONFIG_DMA_API_DEBUG) += dma-debug.o

+obj-$(CONFIG_LIBGCC_SUPPORT) += libgcc/
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h

diff --git a/lib/libgcc/Makefile b/lib/libgcc/Makefile
new file mode 100644
index 0000000..50dff0b
--- /dev/null
+++ b/lib/libgcc/Makefile
@@ -0,0 +1,29 @@
+libfuncs = \
+ _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4 \
+ _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2 _absvsi2 \
+ _absvdi2 _addvsi3 _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 \
+ _negvdi2 _ffssi2 _ffsdi2 _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 \
+ _popcountsi2 _popcountdi2 _paritysi2 _paritydi2 \
+ _bswapsi2 _bswapdi2
+
+libsyms = $(libfuncs) _clz _popcount_tab
+
+quiet_cmd_libgcc_cc_o_c = CC [L] $@
+ cmd_libgcc_cc_o_c = $(CC) $(c_flags) -c -o $@ $< -std=gnu99 -Wno-declaration-after-statement -DL$*
+
+quiet_cmd_libgcc_exports = GEN $@
+ cmd_libgcc_exports = ( \
+ echo '\#include <linux/module.h>'; \
+ echo '\#include "libgcc2.c"'; \
+ $(patsubst %,echo 'EXPORT_SYMBOL(_%);';,$(libfuncs)) \
+ )
+
+$(patsubst %,$(obj)/%.o,$(libsyms)): $(obj)/%.o: $(src)/libgcc2.c FORCE
+ $(call if_changed_dep,libgcc_cc_o_c)
+
+$(obj)/_exports.c: FORCE
+ $(call cmd,libgcc_exports) > $@
+
+obj-y := $(patsubst %,%.o,$(libsyms)) _exports.o
+
+clean-files := _exports.c
--
1.6.2.1


--
... The prejudices people feel about each other disappear when they get
to know each other.
-- Kirk, "Elaan of Troyius", stardate 4372.5

2009-04-03 15:47:01

by Bastian Blank

[permalink] [raw]
Subject: [PATCH 4/5] libgcc: Disable usage of special do_div version

gcc takes care of large div and mod operations and redirects them into
the libgcc. There is no need to do it by hand in this case.

Signed-off-by: Bastian Blank <[email protected]>
---
include/asm-generic/div64.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h
index 8f4e319..45f618d 100644
--- a/include/asm-generic/div64.h
+++ b/include/asm-generic/div64.h
@@ -20,7 +20,7 @@
#include <linux/types.h>
#include <linux/compiler.h>

-#if BITS_PER_LONG == 64
+#if BITS_PER_LONG == 64 || CONFIG_LIBGCC_SUPPORT

# define do_div(n,base) ({ \
uint32_t __base = (base); \
--
1.6.2.1

2009-04-03 15:47:28

by Bastian Blank

[permalink] [raw]
Subject: [PATCH 5/5] s390: Use libgcc

Build our version of the libgcc. Remove conflicting __negdi2
implementation.

Signed-off-by: Bastian Blank <[email protected]>
---
arch/s390/Kconfig | 3 ++
arch/s390/include/asm/libgcc/config.h | 4 +++
arch/s390/include/asm/libgcc/longlong.h | 42 +++++++++++++++++++++++++++++++
arch/s390/math-emu/math.c | 20 --------------
4 files changed, 49 insertions(+), 20 deletions(-)
create mode 100644 arch/s390/include/asm/libgcc/config.h
create mode 100644 arch/s390/include/asm/libgcc/longlong.h

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index dcb667c..87128ef 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -75,6 +75,9 @@ config VIRT_CPU_ACCOUNTING
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y

+config LIBGCC_SUPPORT
+ def_bool y
+
mainmenu "Linux Kernel Configuration"

config S390
diff --git a/arch/s390/include/asm/libgcc/config.h b/arch/s390/include/asm/libgcc/config.h
new file mode 100644
index 0000000..1688497
--- /dev/null
+++ b/arch/s390/include/asm/libgcc/config.h
@@ -0,0 +1,4 @@
+#define MIN_UNITS_PER_WORD 4
+#define BITS_PER_UNIT 8
+#define WORDS_BIG_ENDIAN 1
+#define LONG_LONG_TYPE_SIZE 64
diff --git a/arch/s390/include/asm/libgcc/longlong.h b/arch/s390/include/asm/libgcc/longlong.h
new file mode 100644
index 0000000..742445d
--- /dev/null
+++ b/arch/s390/include/asm/libgcc/longlong.h
@@ -0,0 +1,42 @@
+/*
+ * Definitions for mixed size 32/64 bit arithmetic, s390 specific parts.
+ *
+ * Copyright (C) 1991-2009 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if W_TYPE_SIZE == 32
+#define smul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x; \
+ __asm__ ("lr %N0,%1\n\tmr %0,%2" \
+ : "=&r" (__x.__ll) \
+ : "r" (m0), "r" (m1)); \
+ (xh) = __x.__i.__h; (xl) = __x.__i.__l; \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x; \
+ __x.__i.__h = n1; __x.__i.__l = n0; \
+ __asm__ ("dr %0,%2" \
+ : "=r" (__x.__ll) \
+ : "0" (__x.__ll), "r" (d)); \
+ (q) = __x.__i.__l; (r) = __x.__i.__h; \
+ } while (0)
+#endif
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
index 3ee78cc..9f6869f 100644
--- a/arch/s390/math-emu/math.c
+++ b/arch/s390/math-emu/math.c
@@ -2233,23 +2233,3 @@ int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) {
current->thread.fp_regs.fpc |= (temp & 3);
return 0;
}
-
-/* broken compiler ... */
-long long
-__negdi2 (long long u)
-{
-
- union lll {
- long long ll;
- long s[2];
- };
-
- union lll w,uu;
-
- uu.ll = u;
-
- w.s[1] = -uu.s[1];
- w.s[0] = -uu.s[0] - ((int) w.s[1] != 0);
-
- return w.ll;
-}
--
1.6.2.1

2009-04-03 15:47:48

by Bastian Blank

[permalink] [raw]
Subject: [PATCH 2/5] libgcc: Add config and support headers

Disable all floating point functions and add support for generic
longlong divisions.

Signed-off-by: Bastian Blank <[email protected]>
---
include/asm-generic/libgcc/longlong.h | 183 +++++++++++++++++++++++++++++++++
lib/libgcc/coretypes.h | 1 +
lib/libgcc/longlong.h | 1 +
lib/libgcc/tconfig.h | 8 ++
lib/libgcc/tm.h | 3 +
lib/libgcc/tsystem.h | 1 +
6 files changed, 197 insertions(+), 0 deletions(-)
create mode 100644 include/asm-generic/libgcc/longlong.h
create mode 100644 lib/libgcc/coretypes.h
create mode 100644 lib/libgcc/longlong.h
create mode 100644 lib/libgcc/tconfig.h
create mode 100644 lib/libgcc/tm.h
create mode 100644 lib/libgcc/tsystem.h

diff --git a/include/asm-generic/libgcc/longlong.h b/include/asm-generic/libgcc/longlong.h
new file mode 100644
index 0000000..b5b9158
--- /dev/null
+++ b/include/asm-generic/libgcc/longlong.h
@@ -0,0 +1,183 @@
+/*
+ * Definitions for mixed size 32/64 bit arithmetic, generic parts.
+ *
+ * Copyright (C) 1991-2009 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+extern const UQItype __clz_tab[256];
+
+#include <asm/libgcc/longlong.h>
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - (__x > (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of
+ smul_ppmm. */
+#if !defined (umul_ppmm) && defined (smul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __w1; \
+ UWtype __xm0 = (u), __xm1 = (v); \
+ smul_ppmm (__w1, w0, __xm0, __xm1); \
+ (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \
+ + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \
+ } while (0)
+#endif
+
+/* If we still don't have umul_ppmm, define it using plain C. */
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __x0, __x1, __x2, __x3; \
+ UHWtype __ul, __vl, __uh, __vh; \
+ \
+ __ul = __ll_lowpart (u); \
+ __uh = __ll_highpart (u); \
+ __vl = __ll_lowpart (v); \
+ __vh = __ll_highpart (v); \
+ \
+ __x0 = (UWtype) __ul * __vl; \
+ __x1 = (UWtype) __ul * __vh; \
+ __x2 = (UWtype) __uh * __vl; \
+ __x3 = (UWtype) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
+ } while (0)
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+ ({DWunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+#endif
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+ __udiv_w_sdiv (defined in libgcc or elsewhere). */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ USItype __r; \
+ (q) = __udiv_w_sdiv (&__r, nh, nl, d); \
+ (r) = __r; \
+ } while (0)
+#endif
+
+#if !defined (udiv_qrnnd)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0; \
+ UWtype __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+#define UDIV_NEEDS_NORMALIZATION 1
+#endif
+
+#if !defined (count_leading_zeros)
+#define count_leading_zeros(count, x) \
+ do { \
+ UWtype __xr = (x); \
+ UWtype __a; \
+ \
+ if (W_TYPE_SIZE <= 32) \
+ { \
+ __a = __xr < ((UWtype)1<<2*__BITS4) \
+ ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \
+ : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
+ } \
+ else \
+ { \
+ for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
+ if (((__xr >> __a) & 0xff) != 0) \
+ break; \
+ } \
+ \
+ (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+#define count_trailing_zeros(count, x) \
+ do { \
+ UWtype __ctz_x = (x); \
+ UWtype __ctz_c; \
+ count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \
+ (count) = W_TYPE_SIZE - 1 - __ctz_c; \
+ } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
diff --git a/lib/libgcc/coretypes.h b/lib/libgcc/coretypes.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/lib/libgcc/coretypes.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/lib/libgcc/longlong.h b/lib/libgcc/longlong.h
new file mode 100644
index 0000000..5127ca8
--- /dev/null
+++ b/lib/libgcc/longlong.h
@@ -0,0 +1 @@
+#include <asm-generic/libgcc/longlong.h>
diff --git a/lib/libgcc/tconfig.h b/lib/libgcc/tconfig.h
new file mode 100644
index 0000000..16df0dc
--- /dev/null
+++ b/lib/libgcc/tconfig.h
@@ -0,0 +1,8 @@
+#include <asm/libgcc/config.h>
+
+#define LIBGCC2_DOUBLE_TYPE_SIZE 0
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 0
+#define LIBGCC2_HAS_SF_MODE 0
+#define LIBGCC2_HAS_DF_MODE 0
+#define LIBGCC2_HAS_XF_MODE 0
+#define LIBGCC2_HAS_FF_MODE 0
diff --git a/lib/libgcc/tm.h b/lib/libgcc/tm.h
new file mode 100644
index 0000000..59f75d6
--- /dev/null
+++ b/lib/libgcc/tm.h
@@ -0,0 +1,3 @@
+#include <asm/bug.h>
+
+#define abort() do { BUG(); return 0; } while (0)
diff --git a/lib/libgcc/tsystem.h b/lib/libgcc/tsystem.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/lib/libgcc/tsystem.h
@@ -0,0 +1 @@
+/* empty */
--
1.6.2.1