summaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorraksit <raksit@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-07 21:26:02 +0000
committerraksit <raksit@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-07 21:26:02 +0000
commite43928e066705a15454212156afff431afc7f5b3 (patch)
treeec2ee16bcc8a782df00eabb25aebf409356b9993 /libgcc
parent7d712a63969bf729ff518abe9bccec3319f07204 (diff)
downloadgcc-e43928e066705a15454212156afff431afc7f5b3.tar.gz
Merge lw-ipo branch from trunk 163718:170935
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/lw-ipo@172131 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog153
-rw-r--r--libgcc/Makefile.in31
-rw-r--r--libgcc/config.host14
-rw-r--r--libgcc/config/arm/bpabi-lib.h80
-rw-r--r--libgcc/config/frv/frv-abi.h183
-rw-r--r--libgcc/config/i386/libgcc-sol2.ver12
-rw-r--r--libgcc/config/i386/morestack.S593
-rw-r--r--libgcc/config/i386/t-stack-i3862
-rw-r--r--libgcc/config/libbid/bid_conf.h4
-rw-r--r--libgcc/config/libbid/bid_gcc_intrinsics.h10
-rw-r--r--libgcc/config/microblaze/divsi3.asm96
-rw-r--r--libgcc/config/microblaze/divsi3_table.c62
-rw-r--r--libgcc/config/microblaze/moddi3.asm115
-rw-r--r--libgcc/config/microblaze/modsi3.asm93
-rw-r--r--libgcc/config/microblaze/muldi3_hard.asm144
-rw-r--r--libgcc/config/microblaze/mulsi3.asm69
-rw-r--r--libgcc/config/microblaze/stack_overflow_exit.asm61
-rw-r--r--libgcc/config/microblaze/t-microblaze12
-rw-r--r--libgcc/config/microblaze/udivsi3.asm103
-rw-r--r--libgcc/config/microblaze/umodsi3.asm106
-rw-r--r--libgcc/config/t-stack4
-rw-r--r--libgcc/configure100
-rw-r--r--libgcc/configure.ac81
-rw-r--r--libgcc/generic-morestack-thread.c162
-rw-r--r--libgcc/generic-morestack.c880
-rw-r--r--libgcc/generic-morestack.h53
26 files changed, 3157 insertions, 66 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index d3bad75239a..c6e2567b1da 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,156 @@
+2011-03-14 Andreas Tobler <andreast@fgznet.ch>
+
+ * config.host (cpu_type): Add FreeBSD PowerPC specific parts.
+ Adjust copyright year.
+
+2011-03-07 Ian Lance Taylor <iant@google.com>
+
+ * generic-morestack.c (__splitstack_find): Adjust returned stack
+ pointer to include all registers pushed by __morestack.
+
+2011-01-26 Dave Korn <dave.korn.cygwin@gmail.com>
+
+ PR target/40125
+ * configure.ac: Call ACX_NONCANONICAL_TARGET.
+ (toolexecdir): Calculate and AC_SUBST.
+ (toolexeclibdir): Likewise.
+ * Makefile.in (target_noncanonical): Import.
+ (toolexecdir): Likewise.
+ (toolexeclibdir): Likewise.
+ * configure: Regenerate.
+
+2010-12-13 Nathan Froyd <froydnj@codesourcery.com>
+
+ PR target/46040
+ * config/arm/bpabi.h: Rename to...
+ * config/arm/bpabi-lib.h: ...this.
+
+2010-12-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac: Use i386/t-crtstuff on i?86-*-solaris2* if
+ appropriate.
+ * configure: Regenerate.
+
+2010-11-24 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/libbid/bid_conf.h (BID_BIG_ENDIAN): Define in terms of
+ __FLOAT_WORD_ORDER__.
+ * config/libbid/bid_gcc_intrinsics.h (LIBGCC2_FLOAT_WORDS_BIG_ENDIAN):
+ Delete.
+
+2010-11-20 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
+
+ PR other/46202
+ * Makefile.in (install-strip): New phony target.
+
+2010-11-07 Ian Lance Taylor <iant@google.com>
+
+ PR target/46089
+ * config/i386/morestack.S (__morestack_large_model): New
+ function.
+
+2010-10-23 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/libbid/bid_gcc_intrinsics.h (LIBGCC2_WORDS_BIG_ENDIAN):
+ Delete.
+ (LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__.
+
+2010-10-14 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/arm/bpabi.h: New file.
+ * config/frv/frv-abi.h: New file.
+
+2010-10-01 Ian Lance Taylor <iant@google.com>
+
+ * config/t-stack(LIB2ADD_ST): Set instead of LIB2ADD.
+ * config/i386/t-stack-i386 (LIB2ADD_ST): Likewise.
+
+2010-10-01 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/45858
+ * config.host: Add the missing `$'.
+
+2010-09-30 Michael Eager <eager@eagercon.com>
+
+ * config.host: Add microblaze*-*-*.
+ * config/microblaze/{divsi3.asm,divsi3_table.c,moddi3.asm,modsi3.asm,
+ muldi3_hard.asm,mulsi3.asm,stack_overflow_exit.asm,t-microblaze,
+ udivsi3.asm,umodsi3.asm}: New.
+
+2010-09-28 Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Adjust CFI test to test assembler directly rather
+ than checking gcc preprocessor macro.
+ * configure: Rebuild.
+
+2010-09-27 Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Test whether assembler supports CFI directives.
+ * config.host: Only add t-stack and i386/t-stack-i386 to
+ tmake_file if libgcc_cv_cfi is "yes".
+ * configure: Rebuild.
+
+2010-09-27 Ian Lance Taylor <iant@google.com>
+
+ * generic-morestack.h: New file.
+ * generic-morestack.c: New file.
+ * generic-morestack-thread.c: New file.
+ * config/i386/morestack.S: New file.
+ * config/t-stack: New file.
+ * config/i386/t-stack-i386: New file.
+ * config.host (i[34567]86-*-linux* and friends): Add t-stack and
+ i386/t-stack-i386 to tmake_file.
+
+2010-09-21 Iain Sandoe <iains@gcc.gnu.org>
+
+ * Makefile.in (libgcc-extra-parts): Check for static archives and
+ invoke ranlib after installing them.
+ (gcc-extra-parts): Likewise.
+ (install-leaf): Likewise.
+
+2010-09-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure: Regenerated.
+
+2010-09-10 Kai Tietz <kai.tietz@onevision.com>
+
+ * configure: Regenerated.
+
+2010-09-09 Gerald Pfeifer <gerald@pfeifer.com>
+ Andrew Pinski <pinskia@gmail.com>
+
+ PR target/40959
+ * config.host (ia64*-*-freebsd*): Set extra_parts. Set tmake_file.
+
+2010-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/45524
+ * configure: Regenerated.
+
+2010-09-06 Andreas Schwab <schwab@redhat.com>
+
+ * configure: Regenerate.
+
+2010-09-03 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/t-sol2 (__copysigntf3, __fabstf3): Disable for
+ 64bit targets.
+ (__fixtfti, __fixunstfti, __floattitf, __floatuntitf): Enable only
+ for 64bit targets.
+
+2010-09-03 Uros Bizjak <ubizjak@gmail.com>
+ Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/45476
+ * Makefile.in (sifuncs, difuncs, tifuncs): Filter out
+ LIB2FUNCS_EXCLUDE functions.
+
+2010-09-03 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * configure.ac: Use the GCC_AC_ENABLE_DECIMAL_FLOAT macro.
+ Include dfp.m4.
+ * configure: Regenerate.
+
2010-09-01 Uros Bizjak <ubizjak@gmail.com>
* config.host (i[34567]86-*-freebsd*, x86_64-*-freebsd*): Add
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index a7d1572d595..42fac9e1463 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -1,6 +1,6 @@
# Makefile.in
-# Copyright (C) 2005, 2006, 2009 Free Software Foundation
+# Copyright (C) 2005, 2006, 2009, 2010 Free Software Foundation
#
# This file is part of GCC.
#
@@ -41,6 +41,7 @@ enable_decimal_float = @enable_decimal_float@
fixed_point = @fixed_point@
host_noncanonical = @host_noncanonical@
+target_noncanonical = @target_noncanonical@
# List of extra object files that should be compiled for this target machine.
# The rules for compiling them should be in the t-* file for the machine.
@@ -147,6 +148,7 @@ configure_deps = \
$(srcdir)/../config/acx.m4 \
$(srcdir)/../config/no-executables.m4 \
$(srcdir)/../config/override.m4 \
+ $(srcdir)/../config/dfp.m4 \
$(srcdir)/configure: @MAINT@ $(srcdir)/configure.ac $(configure_deps)
cd $(srcdir) && $(AUTOCONF)
@@ -174,6 +176,9 @@ STRIP_FOR_TARGET = $(STRIP)
libsubdir = $(libdir)/gcc/$(host_noncanonical)/$(version)
# Used to install the shared libgcc.
slibdir = @slibdir@
+# Maybe used for DLLs on Windows targets.
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
export AR_FOR_TARGET
export AR_CREATE_FOR_TARGET
@@ -193,6 +198,8 @@ export STRIP_FOR_TARGET
export RANLIB_FOR_TARGET
export libsubdir
export slibdir
+export toolexecdir
+export toolexeclibdir
version := $(shell $(CC) -dumpversion)
@@ -384,9 +391,9 @@ ifneq ($(LIB2_SIDITI_CONV_FUNCS),)
# functions are built with a wordsize of 4; the TImode functions are
# built with the same labels, but a wordsize of 8.
-sifuncs = $(subst XX,si,$(swfloatfuncs))
-difuncs = $(subst XX,di,$(dwfloatfuncs))
-tifuncs = $(subst XX,ti,$(dwfloatfuncs))
+sifuncs := $(filter-out $(LIB2FUNCS_EXCLUDE),$(subst XX,si,$(swfloatfuncs)))
+difuncs := $(filter-out $(LIB2FUNCS_EXCLUDE),$(subst XX,di,$(dwfloatfuncs)))
+tifuncs := $(filter-out $(LIB2FUNCS_EXCLUDE),$(subst XX,ti,$(dwfloatfuncs)))
iter-items := $(sifuncs) $(difuncs) $(tifuncs)
iter-labels := $(sifuncs) $(difuncs) $(difuncs)
@@ -872,6 +879,10 @@ endif
for file in $$parts; do \
rm -f $(gcc_objdir)$(MULTISUBDIR)/$$file; \
$(INSTALL_DATA) $$file $(gcc_objdir)$(MULTISUBDIR)/; \
+ case $$file in \
+ *.a) \
+ $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \
+ esac; \
done
# Build extra startfiles in the gcc directory, for unconverted
@@ -905,6 +916,10 @@ gcc-extra-parts:
for file in $$parts; do \
rm -f $(gcc_objdir)$(MULTISUBDIR)/$$file; \
$(INSTALL_DATA) $$file $(gcc_objdir)$(MULTISUBDIR)/; \
+ case $$file in \
+ *.a) \
+ $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \
+ esac; \
done
all: $(extra-parts)
@@ -960,12 +975,18 @@ install-leaf: $(install-shared) $(install-libunwind)
for file in $$parts; do \
rm -f $(DESTDIR)$(inst_libdir)/$$file; \
$(INSTALL_DATA) $$file $(DESTDIR)$(inst_libdir)/; \
+ case $$file in \
+ *.a) \
+ $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \
+ esac; \
done
install: install-leaf
@: $(MAKE) ; $(MULTIDO) $(FLAGS_TO_PASS) multi-do DO=install
-.PHONY: install install-shared install-libunwind
+install-strip: install
+
+.PHONY: install install-shared install-libunwind install-strip
# Don't export variables to the environment, in order to not confuse
# configure.
diff --git a/libgcc/config.host b/libgcc/config.host
index d2205c74674..114a2e64317 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -107,6 +107,9 @@ m68k-*-*)
;;
mep*-*-*)
;;
+microblaze*-*-*)
+ cpu_type=microblaze
+ ;;
mips*-*-*)
cpu_type=mips
;;
@@ -345,6 +348,8 @@ ia64*-*-elf*)
tmake_file="ia64/t-ia64"
;;
ia64*-*-freebsd*)
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
+ tmake_file="ia64/t-ia64"
;;
ia64*-*-linux*)
extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
@@ -392,6 +397,9 @@ mcore-*-elf)
;;
mcore-*-pe*)
;;
+microblaze*-*-*)
+ tmake_file="microblaze/t-microblaze"
+ ;;
mips-sgi-irix[56]*)
;;
mips*-*-netbsd*) # NetBSD/mips, either endian.
@@ -450,7 +458,8 @@ powerpc-*-darwin*)
;;
powerpc64-*-darwin*)
;;
-powerpc*-*-freebsd*)
+powerpc-*-freebsd*)
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-freebsd t-softfp"
;;
powerpc-*-netbsd*)
;;
@@ -596,6 +605,9 @@ i[34567]86-*-linux* | x86_64-*-linux* | \
i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | \
i[34567]86-*-gnu*)
tmake_file="${tmake_file} t-tls"
+ if test "$libgcc_cv_cfi" = "yes"; then
+ tmake_file="${tmake_file} t-stack i386/t-stack-i386"
+ fi
;;
esac
diff --git a/libgcc/config/arm/bpabi-lib.h b/libgcc/config/arm/bpabi-lib.h
new file mode 100644
index 00000000000..49a28c3c202
--- /dev/null
+++ b/libgcc/config/arm/bpabi-lib.h
@@ -0,0 +1,80 @@
+/* Configuration file for ARM BPABI targets, library renames.
+ Copyright (C) 2010
+ Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC
+
+ 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 3, 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 and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if defined (__thumb__)
+#define RENAME_LIBRARY_SET ".thumb_set"
+#else
+#define RENAME_LIBRARY_SET ".set"
+#endif
+
+/* Make __aeabi_AEABI_NAME an alias for __GCC_NAME. */
+#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) \
+ __asm__ (".globl\t__aeabi_" #AEABI_NAME "\n" \
+ RENAME_LIBRARY_SET "\t__aeabi_" #AEABI_NAME \
+ ", __" #GCC_NAME "\n");
+
+/* Give some libgcc functions an additional __aeabi name. */
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+#endif
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+#endif
+#ifdef L_fixdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz) \
+ extern DWtype __fixdfdi (DFtype) __attribute__((pcs("aapcs"))); \
+ extern UDWtype __fixunsdfdi (DFtype) __asm__("__aeabi_d2ulz") __attribute__((pcs("aapcs")));
+#endif
+#ifdef L_fixunsdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz) \
+ extern UDWtype __fixunsdfdi (DFtype) __attribute__((pcs("aapcs")));
+#endif
+#ifdef L_fixsfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz) \
+ extern DWtype __fixsfdi (SFtype) __attribute__((pcs("aapcs"))); \
+ extern UDWtype __fixunssfdi (SFtype) __asm__("__aeabi_f2ulz") __attribute__((pcs("aapcs")));
+#endif
+#ifdef L_fixunssfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz) \
+ extern UDWtype __fixunssfdi (SFtype) __attribute__((pcs("aapcs")));
+#endif
+#ifdef L_floatdidf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d)
+#endif
+#ifdef L_floatdisf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, l2f)
+#endif
+
+/* These renames are needed on ARMv6M. Other targets get them from
+ assembly routines. */
+#ifdef L_fixunsdfsi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfsi, d2uiz)
+#endif
+#ifdef L_fixunssfsi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfsi, f2uiz)
+#endif
+#ifdef L_floatundidf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatundidf, ul2d)
+#endif
+#ifdef L_floatundisf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatundisf, ul2f)
+#endif
diff --git a/libgcc/config/frv/frv-abi.h b/libgcc/config/frv/frv-abi.h
new file mode 100644
index 00000000000..99a0cd87855
--- /dev/null
+++ b/libgcc/config/frv/frv-abi.h
@@ -0,0 +1,183 @@
+/* Frv map GCC names to FR-V ABI.
+ Copyright (C) 2000, 2003, 2004, 2007, 2010
+ Free Software Foundation, Inc.
+ Contributed by Red Hat, 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 3, 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 and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* For each of the functions in the library that has a corresponding name in
+ the ABI, add an equivalence between the GCC name and the ABI name. This is
+ in a separate file from frv.h so that fp-bit.c can be made to include it. */
+
+#ifdef __GNUC__
+#ifdef __FRV_UNDERSCORE__
+#define RENAME_LIBRARY(OLD,NEW) \
+__asm__ (".globl\t_" #NEW "\n" \
+ "_" #NEW "=_" #OLD "\n" \
+ "\t.type\t_" #NEW ",@function\n");
+
+#else
+#define RENAME_LIBRARY(OLD,NEW) \
+__asm__ (".globl\t" #NEW "\n" \
+ #NEW "=" #OLD "\n" \
+ "\t.type\t" #NEW ",@function\n");
+#endif
+
+#define CREATE_DOUBLE_SHIFT(OLD,NEW) \
+__asm__ (".text\n" \
+ "\t.globl\t" #NEW "\n" \
+ "\t.type\t" #NEW ",@function\n" \
+ #NEW ":\n" \
+ "\tor\tgr11, gr0, gr10\n" \
+ ".L" #OLD " = " #OLD "\n" \
+ "\tbra\t.L" #OLD "\n");
+
+#ifdef L_sf_to_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__extendsfdf2,__ftod)
+#endif
+
+#ifdef L_sf_to_si
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixsfsi,__ftoi)
+#endif
+
+#ifdef L_sf_to_usi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfsi,__ftoui)
+#endif
+
+#ifdef L_df_to_si
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixdfsi,__dtoi)
+#endif
+
+#ifdef L_fixunssfsi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfsi,__ftoui)
+#endif
+
+#ifdef L_fixunsdfsi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunsdfsi,__dtoui)
+#endif
+
+#ifdef L_fixsfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixsfdi,__ftoll)
+#endif
+
+#ifdef L_fixdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixdfdi,__dtoll)
+#endif
+
+#ifdef L_fixunssfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfdi,__ftoull)
+#endif
+
+#ifdef L_fixunsdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunsdfdi,__dtoull)
+#endif
+
+#ifdef L_si_to_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatsisf,__itof)
+#endif
+
+#ifdef L_di_to_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdisf,__lltof)
+#endif
+
+#ifdef L_df_to_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__truncdfsf2,__dtof)
+#endif
+
+#ifdef L_si_to_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatsidf,__itod)
+#endif
+
+#ifdef L_floatdisf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdisf,__lltof)
+#endif
+
+#ifdef L_floatdidf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdidf,__lltod)
+#endif
+
+#ifdef L_addsub_df
+#define DECLARE_LIBRARY_RENAMES \
+ RENAME_LIBRARY(__adddf3,__addd)
+ RENAME_LIBRARY(__subdf3,__subd)
+#endif
+
+#ifdef L_mul_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__muldf3,__muld)
+#endif
+
+#ifdef L_div_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divdf3,__divd)
+#endif
+
+#ifdef L_addsub_sf
+#define DECLARE_LIBRARY_RENAMES \
+ RENAME_LIBRARY(__addsf3,__addf) \
+ RENAME_LIBRARY(__subsf3,__subf)
+#endif
+
+#ifdef L_mul_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__mulsf3,__mulf)
+#endif
+
+#ifdef L_div_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divsf3,__divf)
+#endif
+
+#ifdef L_ashldi3
+#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__ashldi3,__sllll)
+#endif
+
+#ifdef L_lshrdi3
+#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__lshrdi3,__srlll)
+#endif
+
+#ifdef L_ashrdi3
+#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__ashrdi3,__srall)
+#endif
+
+#ifdef L_adddi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__adddi3,__addll)
+#endif
+
+#ifdef L_subdi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__subdi3,__subll)
+#endif
+
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES \
+ RENAME_LIBRARY(__muldi3,__mulll)
+ RENAME_LIBRARY(__muldi3,__umulll)
+#endif
+
+#ifdef L_divdi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divdi3,__divll)
+#endif
+
+#ifdef L_udivdi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__udivdi3,__udivll)
+#endif
+
+#ifdef L_moddi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__moddi3,__modll)
+#endif
+
+#ifdef L_umoddi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__umoddi3,__umodll)
+#endif
+#endif /* __GNUC__ */
diff --git a/libgcc/config/i386/libgcc-sol2.ver b/libgcc/config/i386/libgcc-sol2.ver
index 8d94d3c6178..26a0abfb541 100644
--- a/libgcc/config/i386/libgcc-sol2.ver
+++ b/libgcc/config/i386/libgcc-sol2.ver
@@ -59,26 +59,38 @@
GCC_4.5.0 {
__addtf3
+%ifndef __x86_64__
__copysigntf3
+%endif
__divtc3
__divtf3
__eqtf2
__extenddftf2
__extendsftf2
__extendxftf2
+%ifndef __x86_64__
__fabstf2
+%endif
__fixtfdi
__fixtfsi
+%ifdef __x86_64__
__fixtfti
+%endif
__fixunstfdi
__fixunstfsi
+%ifdef __x86_64__
__fixunstfti
+%endif
__floatditf
__floatsitf
+%ifdef __x86_64__
__floattitf
+%endif
__floatunditf
__floatunsitf
+%ifdef __x86_64__
__floatuntitf
+%endif
__getf2
__gttf2
__letf2
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
new file mode 100644
index 00000000000..10fa1fdf73a
--- /dev/null
+++ b/libgcc/config/i386/morestack.S
@@ -0,0 +1,593 @@
+# x86/x86_64 support for -fsplit-stack.
+# Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+# Contributed by Ian Lance Taylor <iant@google.com>.
+
+# 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 3, 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.
+
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+# Support for allocating more stack space when using -fsplit-stack.
+# When a function discovers that it needs more stack space, it will
+# call __morestack with the size of the stack frame and the size of
+# the parameters to copy from the old stack frame to the new one.
+# The __morestack function preserves the parameter registers and
+# calls __generic_morestack to actually allocate the stack space.
+
+# When this is called stack space is very low, but we ensure that
+# there is enough space to push the parameter registers and to call
+# __generic_morestack.
+
+# When calling __generic_morestack, FRAME_SIZE points to the size of
+# the desired frame when the function is called, and the function
+# sets it to the size of the allocated stack. OLD_STACK points to
+# the parameters on the old stack and PARAM_SIZE is the number of
+# bytes of parameters to copy to the new stack. These are the
+# parameters of the function that called __morestack. The
+# __generic_morestack function returns the new stack pointer,
+# pointing to the address of the first copied parameter. The return
+# value minus the returned *FRAME_SIZE will be the first address on
+# the stack which we should not use.
+
+# void *__generic_morestack (size_t *frame_size, void *old_stack,
+# size_t param_size);
+
+# The __morestack routine has to arrange for the caller to return to a
+# stub on the new stack. The stub is responsible for restoring the
+# old stack pointer and returning to the caller's caller. This calls
+# __generic_releasestack to retrieve the old stack pointer and release
+# the newly allocated stack.
+
+# void *__generic_releasestack (size_t *available);
+
+# We do a little dance so that the processor's call/return return
+# address prediction works out. The compiler arranges for the caller
+# to look like this:
+# call __generic_morestack
+# ret
+# L:
+# // carry on with function
+# After we allocate more stack, we call L, which is in our caller.
+# When that returns (to the predicted instruction), we release the
+# stack segment and reset the stack pointer. We then return to the
+# predicted instruction, namely the ret instruction immediately after
+# the call to __generic_morestack. That then returns to the caller of
+# the original caller.
+
+
+# The amount of extra space we ask for. In general this has to be
+# enough for the dynamic loader to find a symbol and for a signal
+# handler to run.
+
+#ifndef __x86_64__
+#define BACKOFF (1024)
+#else
+#define BACKOFF (1536)
+#endif
+
+
+# This entry point is for split-stack code which calls non-split-stack
+# code. When the linker sees this case, it converts the call to
+# __morestack to call __morestack_non_split instead. We just bump the
+# requested stack space by 16K.
+
+ .global __morestack_non_split
+ .hidden __morestack_non_split
+
+#ifdef __ELF__
+ .type __morestack_non_split,@function
+#endif
+
+__morestack_non_split:
+
+#ifndef __x86_64__
+ addl $0x4000,4(%esp)
+#else
+ addq $0x4000,%r10
+#endif
+
+#ifdef __ELF__
+ .size __morestack_non_split, . - __morestack_non_split
+#endif
+
+# __morestack_non_split falls through into __morestack.
+
+
+# The __morestack function.
+
+ .global __morestack
+ .hidden __morestack
+
+#ifdef __ELF__
+ .type __morestack,@function
+#endif
+
+__morestack:
+.LFB1:
+ .cfi_startproc
+
+
+#ifndef __x86_64__
+
+
+# The 32-bit __morestack function.
+
+ # We use a cleanup to restore the stack guard if an exception
+ # is thrown through this code.
+#ifndef __PIC__
+ .cfi_personality 0,__gcc_personality_v0
+ .cfi_lsda 0,.LLSDA1
+#else
+ .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
+ .cfi_lsda 0x1b,.LLSDA1
+#endif
+
+ # Set up a normal backtrace.
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset %ebp, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register %ebp
+
+ # We return below with a ret $8. We will return to a single
+ # return instruction, which will return to the caller of our
+ # caller. We let the unwinder skip that single return
+ # instruction, and just return to the real caller.
+ .cfi_offset 8, 8
+ .cfi_escape 0x15, 4, 0x7d # DW_CFA_val_offset_sf, %esp, 12/-4
+
+ # In 32-bit mode the parameters are pushed on the stack. The
+ # argument size is pushed then the new stack frame size is
+ # pushed.
+
+ # In 32-bit mode the registers %eax, %edx, and %ecx may be
+ # used for parameters, depending on the regparm and fastcall
+ # attributes.
+
+ pushl %eax
+ pushl %edx
+ pushl %ecx
+
+ call __morestack_block_signals
+
+ pushl 12(%ebp) # The size of the parameters.
+ leal 20(%ebp),%eax # Address of caller's parameters.
+ pushl %eax
+ addl $BACKOFF,8(%ebp) # Ask for backoff bytes.
+ leal 8(%ebp),%eax # The address of the new frame size.
+ pushl %eax
+
+ # Note that %esp is exactly 32 bytes below the CFA -- perfect for
+ # a 16-byte aligned stack. That said, we still ought to compile
+ # generic-morestack.c with -mpreferred-stack-boundary=2. FIXME.
+ call __generic_morestack
+
+ movl %eax,%esp # Switch to the new stack.
+ subl 8(%ebp),%eax # The end of the stack space.
+ addl $BACKOFF,%eax # Back off 512 bytes.
+
+.LEHB0:
+ # FIXME: The offset must match
+ # TARGET_THREAD_SPLIT_STACK_OFFSET in
+ # gcc/config/i386/linux.h.
+ movl %eax,%gs:0x30 # Save the new stack boundary.
+
+ call __morestack_unblock_signals
+
+ movl -8(%ebp),%edx # Restore registers.
+ movl -12(%ebp),%ecx
+
+ movl 4(%ebp),%eax # Increment the return address
+ cmpb $0xc3,(%eax) # to skip the ret instruction;
+ je 1f # see above.
+ addl $2,%eax
+1: inc %eax
+
+ movl %eax,-8(%ebp) # Store return address in an
+ # unused slot.
+
+ movl -4(%ebp),%eax # Restore the last register.
+
+ call *-8(%ebp) # Call our caller!
+
+ # The caller will return here, as predicted.
+
+ # Save the registers which may hold a return value. We
+ # assume that __generic_releasestack does not touch any
+ # floating point or vector registers.
+ pushl %eax
+ pushl %edx
+
+ # Push the arguments to __generic_releasestack now so that the
+ # stack is at a 16-byte boundary for
+ # __morestack_block_signals.
+ pushl $0 # Where the available space is returned.
+ leal 0(%esp),%eax # Push its address.
+ push %eax
+
+ call __morestack_block_signals
+
+ call __generic_releasestack
+
+ subl 4(%esp),%eax # Subtract available space.
+ addl $BACKOFF,%eax # Back off 512 bytes.
+.LEHE0:
+ movl %eax,%gs:0x30 # Save the new stack boundary.
+
+ addl $8,%esp # Remove values from stack.
+
+ # We need to restore the old stack pointer, which is in %rbp,
+ # before we unblock signals. We also need to restore %eax and
+ # %edx after we unblock signals but before we return. Do this
+ # by moving %eax and %edx from the current stack to the old
+ # stack.
+
+ popl %edx # Pop return value from current stack.
+ popl %eax
+
+ movl %ebp,%esp # Restore stack pointer.
+
+ pushl %eax # Push return value on old stack.
+ pushl %edx
+ subl $8,%esp # Align stack to 16-byte boundary.
+
+ call __morestack_unblock_signals
+
+ addl $8,%esp
+ popl %edx # Restore return value.
+ popl %eax
+
+ .cfi_remember_state
+ popl %ebp
+ .cfi_restore %ebp
+ .cfi_def_cfa %esp, 12
+ ret $8 # Return to caller, which will
+ # immediately return. Pop
+ # arguments as we go.
+
+# This is the cleanup code called by the stack unwinder when unwinding
+# through the code between .LEHB0 and .LEHE0 above.
+
+.L1:
+ .cfi_restore_state
+ subl $16,%esp # Maintain 16 byte alignment.
+ movl %eax,4(%esp) # Save exception header.
+ movl %ebp,(%esp) # Stack pointer after resume.
+ call __generic_findstack
+ movl %ebp,%ecx # Get the stack pointer.
+ subl %eax,%ecx # Subtract available space.
+ addl $BACKOFF,%ecx # Back off 512 bytes.
+ movl %ecx,%gs:0x30 # Save new stack boundary.
+ movl 4(%esp),%eax # Function argument.
+ movl %eax,(%esp)
+#ifdef __PIC__
+#undef __i686
+ call __i686.get_pc_thunk.bx # %ebx may not be set up for us.
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ call _Unwind_Resume@PLT # Resume unwinding.
+#else
+ call _Unwind_Resume
+#endif
+
+#else /* defined(__x86_64__) */
+
+
+# The 64-bit __morestack function.
+
+ # We use a cleanup to restore the stack guard if an exception
+ # is thrown through this code.
+#ifndef __PIC__
+ .cfi_personality 0x3,__gcc_personality_v0
+ .cfi_lsda 0x3,.LLSDA1
+#else
+ .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
+ .cfi_lsda 0x1b,.LLSDA1
+#endif
+
+ # Set up a normal backtrace.
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+
+ # We will return a single return instruction, which will
+ # return to the caller of our caller. Let the unwinder skip
+ # that single return instruction, and just return to the real
+ # caller.
+ .cfi_offset 16, 0
+ .cfi_escape 0x15, 7, 0x7f # DW_CFA_val_offset_sf, %esp, 8/-8
+
+ # In 64-bit mode the new stack frame size is passed in r10
+ # and the argument size is passed in r11.
+
+ addq $BACKOFF,%r10 # Ask for backoff bytes.
+ pushq %r10 # Save new frame size.
+
+ # In 64-bit mode the registers %rdi, %rsi, %rdx, %rcx, %r8,
+ # and %r9 may be used for parameters. We also preserve %rax
+ # which the caller may use to hold %r10.
+
+ pushq %rax
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ pushq %r9
+
+ pushq %r11
+ pushq $0 # For alignment.
+
+ call __morestack_block_signals
+
+ leaq -8(%rbp),%rdi # Address of new frame size.
+ leaq 24(%rbp),%rsi # The caller's parameters.
+ addq $8,%rsp
+ popq %rdx # The size of the parameters.
+
+ call __generic_morestack
+
+ movq -8(%rbp),%r10 # Reload modified frame size
+ movq %rax,%rsp # Switch to the new stack.
+ subq %r10,%rax # The end of the stack space.
+ addq $BACKOFF,%rax # Back off 1024 bytes.
+
+.LEHB0:
+ # FIXME: The offset must match
+ # TARGET_THREAD_SPLIT_STACK_OFFSET in
+ # gcc/config/i386/linux64.h.
+ movq %rax,%fs:0x70 # Save the new stack boundary.
+
+ call __morestack_unblock_signals
+
+ movq -24(%rbp),%rdi # Restore registers.
+ movq -32(%rbp),%rsi
+ movq -40(%rbp),%rdx
+ movq -48(%rbp),%rcx
+ movq -56(%rbp),%r8
+ movq -64(%rbp),%r9
+
+ movq 8(%rbp),%r10 # Increment the return address
+ incq %r10 # to skip the ret instruction;
+ # see above.
+
+ movq -16(%rbp),%rax # Restore caller's %rax.
+
+ call *%r10 # Call our caller!
+
+ # The caller will return here, as predicted.
+
+ # Save the registers which may hold a return value. We
+ # assume that __generic_releasestack does not touch any
+ # floating point or vector registers.
+ pushq %rax
+ pushq %rdx
+
+ call __morestack_block_signals
+
+ pushq $0 # For alignment.
+ pushq $0 # Where the available space is returned.
+ leaq 0(%rsp),%rdi # Pass its address.
+
+ call __generic_releasestack
+
+ subq 0(%rsp),%rax # Subtract available space.
+ addq $BACKOFF,%rax # Back off 1024 bytes.
+.LEHE0:
+ movq %rax,%fs:0x70 # Save the new stack boundary.
+
+ addq $16,%rsp # Remove values from stack.
+
+ # We need to restore the old stack pointer, which is in %rbp,
+ # before we unblock signals. We also need to restore %rax and
+ # %rdx after we unblock signals but before we return. Do this
+ # by moving %rax and %rdx from the current stack to the old
+ # stack.
+
+ popq %rdx # Pop return value from current stack.
+ popq %rax
+
+ movq %rbp,%rsp # Restore stack pointer.
+
+ pushq %rax # Push return value on old stack.
+ pushq %rdx
+
+ call __morestack_unblock_signals
+
+ popq %rdx # Restore return value.
+ popq %rax
+
+ .cfi_remember_state
+ popq %rbp
+ .cfi_restore %rbp
+ .cfi_def_cfa %rsp, 8
+ ret # Return to caller, which will
+ # immediately return.
+
+# This is the cleanup code called by the stack unwinder when unwinding
+# through the code between .LEHB0 and .LEHE0 above.
+
+.L1:
+ .cfi_restore_state
+ subq $16,%rsp # Maintain 16 byte alignment.
+ movq %rax,(%rsp) # Save exception header.
+ movq %rbp,%rdi # Stack pointer after resume.
+ call __generic_findstack
+ movq %rbp,%rcx # Get the stack pointer.
+ subq %rax,%rcx # Subtract available space.
+ addq $BACKOFF,%rcx # Back off 1024 bytes.
+ movq %rcx,%fs:0x70 # Save new stack boundary.
+ movq (%rsp),%rdi # Restore exception data for call.
+#ifdef __PIC__
+ call _Unwind_Resume@PLT # Resume unwinding.
+#else
+ call _Unwind_Resume # Resume unwinding.
+#endif
+
+#endif /* defined(__x86_64__) */
+
+ .cfi_endproc
+#ifdef __ELF__
+ .size __morestack, . - __morestack
+#endif
+
+
+# The exception table. This tells the personality routine to execute
+# the exception handler.
+
+ .section .gcc_except_table,"a",@progbits
+ .align 4
+.LLSDA1:
+ .byte 0xff # @LPStart format (omit)
+ .byte 0xff # @TType format (omit)
+ .byte 0x1 # call-site format (uleb128)
+ .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length
+.LLSDACSB1:
+ .uleb128 .LEHB0-.LFB1 # region 0 start
+ .uleb128 .LEHE0-.LEHB0 # length
+ .uleb128 .L1-.LFB1 # landing pad
+ .uleb128 0 # action
+.LLSDACSE1:
+
+
+ .global __gcc_personality_v0
+#ifdef __PIC__
+ # Build a position independent reference to the basic
+ # personality function.
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
+ .type DW.ref.__gcc_personality_v0, @object
+DW.ref.__gcc_personality_v0:
+#ifndef __x86_64
+ .align 4
+ .size DW.ref.__gcc_personality_v0, 4
+ .long __gcc_personality_v0
+#else
+ .align 8
+ .size DW.ref.__gcc_personality_v0, 8
+ .quad __gcc_personality_v0
+#endif
+#endif
+
+#ifdef __x86_64__
+
+# This entry point is used for the large model. With this entry point
+# the upper 32 bits of %r10 hold the argument size and the lower 32
+# bits hold the new stack frame size. There doesn't seem to be a way
+# to know in the assembler code that we are assembling for the large
+# model, and there doesn't seem to be a large model multilib anyhow.
+# If one is developed, then the non-PIC code is probably OK since we
+# will probably be close to the morestack code, but the PIC code
+# almost certainly needs to be changed. FIXME.
+
+ .text
+ .global __morestack_large_model
+ .hidden __morestack_large_model
+
+#ifdef __ELF__
+ .type __morestack_large_model,@function
+#endif
+
+__morestack_large_model:
+
+ .cfi_startproc
+
+ movq %r10, %r11
+ andl $0xffffffff, %r10d
+ sarq $32, %r11
+ jmp __morestack
+
+ .cfi_endproc
+#ifdef __ELF__
+ .size __morestack_large_model, . - __morestack_large_model
+#endif
+
+#endif /* __x86_64__ */
+
+# Initialize the stack test value when the program starts or when a
+# new thread starts. We don't know how large the main stack is, so we
+# guess conservatively. We might be able to use getrlimit here.
+
+ .text
+ .global __stack_split_initialize
+ .hidden __stack_split_initialize
+
+#ifdef __ELF__
+ .type __stack_split_initialize, @function
+#endif
+
+__stack_split_initialize:
+
+#ifndef __x86_64__
+
+ leal -16000(%esp),%eax # We should have at least 16K.
+ movl %eax,%gs:0x30
+ pushl $16000
+ pushl %esp
+#ifdef __PIC__
+ call __generic_morestack_set_initial_sp@PLT
+#else
+ call __generic_morestack_set_initial_sp
+#endif
+ addl $8,%esp
+ ret
+
+#else /* defined(__x86_64__) */
+
+ leaq -16000(%rsp),%rax # We should have at least 16K.
+ movq %rax,%fs:0x70
+ movq %rsp,%rdi
+ movq $16000,%rsi
+#ifdef __PIC__
+ call __generic_morestack_set_initial_sp@PLT
+#else
+ call __generic_morestack_set_initial_sp
+#endif
+ ret
+
+#endif /* defined(__x86_64__) */
+
+#ifdef __ELF__
+ .size __stack_split_initialize, . - __stack_split_initialize
+#endif
+
+
+# Make __stack_split_initialize a high priority constructor. FIXME:
+# This is ELF specific.
+
+ .section .ctors.65535,"aw",@progbits
+
+#ifndef __x86_64__
+ .align 4
+ .long __stack_split_initialize
+ .long __morestack_load_mmap
+#else
+ .align 8
+ .quad __stack_split_initialize
+ .quad __morestack_load_mmap
+#endif
+
+#ifdef __ELF__
+ .section .note.GNU-stack,"",@progbits
+ .section .note.GNU-split-stack,"",@progbits
+ .section .note.GNU-no-split-stack,"",@progbits
+#endif
diff --git a/libgcc/config/i386/t-stack-i386 b/libgcc/config/i386/t-stack-i386
new file mode 100644
index 00000000000..9965f9402cc
--- /dev/null
+++ b/libgcc/config/i386/t-stack-i386
@@ -0,0 +1,2 @@
+# Makefile fragment to support -fsplit-stack for x86.
+LIB2ADD_ST += $(srcdir)/config/i386/morestack.S
diff --git a/libgcc/config/libbid/bid_conf.h b/libgcc/config/libbid/bid_conf.h
index d22980d9d2a..72de5019daa 100644
--- a/libgcc/config/libbid/bid_conf.h
+++ b/libgcc/config/libbid/bid_conf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
@@ -516,7 +516,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
#ifndef BID_BIG_ENDIAN
-#define BID_BIG_ENDIAN LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+#define BID_BIG_ENDIAN __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
#endif
#ifndef BID_THREAD
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index f5bd8d04a96..3f3e1ef1706 100644
--- a/libgcc/config/libbid/bid_gcc_intrinsics.h
+++ b/libgcc/config/libbid/bid_gcc_intrinsics.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
@@ -30,14 +30,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "coretypes.h"
#include "tm.h"
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
-#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
-#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
-#endif
-
#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
#endif
diff --git a/libgcc/config/microblaze/divsi3.asm b/libgcc/config/microblaze/divsi3.asm
new file mode 100644
index 00000000000..7d888b32e8d
--- /dev/null
+++ b/libgcc/config/microblaze/divsi3.asm
@@ -0,0 +1,96 @@
+###################################-
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# divsi3.asm
+#
+# Divide operation for 32 bit integers.
+# Input : Dividend in Reg r5
+# Divisor in Reg r6
+# Output: Result in Reg r3
+#
+#######################################
+
+ .globl __divsi3
+ .ent __divsi3
+ .type __divsi3,@function
+__divsi3:
+ .frame r1,0,r15
+
+ ADDIK r1,r1,-16
+ SWI r28,r1,0
+ SWI r29,r1,4
+ SWI r30,r1,8
+ SWI r31,r1,12
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQI r5,$LaResult_Is_Zero # Result is Zero
+ BGEID r5,$LaR5_Pos
+ XOR r28,r5,r6 # Get the sign of the result
+ RSUBI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BGEI r6,$LaR6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDIK r30,r0,0 # Clear mod
+ ADDIK r3,r0,0 # clear div
+ ADDIK r29,r0,32 # Initialize the loop count
+
+ # First part try to find the first '1' in the r5
+$LaDIV0:
+ BLTI r5,$LaDIV2 # This traps r5 == 0x80000000
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGTID r5,$LaDIV1
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r30,r30,r30 # Move that bit into the Mod register
+ RSUB r31,r6,r30 # Try to subtract (r30 a r6)
+ BLTI r31,$LaMOD_TOO_SMALL
+ OR r30,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r3,r3,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r3,r3,r3 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r28,$LaRETURN_HERE
+ BRID $LaRETURN_HERE
+ RSUBI r3,r3,0 # Negate the result
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ OR r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ LWI r28,r1,0
+ LWI r29,r1,4
+ LWI r30,r1,8
+ LWI r31,r1,12
+ RTSD r15,8
+ ADDIK r1,r1,16
+.end __divsi3
+ .size __divsi3, . - __divsi3
+
diff --git a/libgcc/config/microblaze/divsi3_table.c b/libgcc/config/microblaze/divsi3_table.c
new file mode 100644
index 00000000000..d37f2aee57c
--- /dev/null
+++ b/libgcc/config/microblaze/divsi3_table.c
@@ -0,0 +1,62 @@
+/* Table for software lookup divide for Xilinx MicroBlaze.
+
+ Copyright 2009, 2010 Free Software Foundation, Inc.
+
+ Contributed by Michael Eager <eager@eagercon.com>.
+
+ This file 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 3, 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+unsigned char _divsi3_table[] =
+{
+ 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7,
+ 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
+ 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7,
+ 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
+ 0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7,
+ 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
+ 0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7,
+ 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
+ 0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7,
+ 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
+ 0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7,
+ 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
+ 0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7,
+ 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
+ 0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7,
+ 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
+ 0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7,
+ 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
+ 0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7,
+ 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
+ 0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7,
+ 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
+ 0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7,
+ 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
+ 0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7,
+ 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
+ 0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7,
+ 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
+ 0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7,
+ 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
+ 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7,
+ 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
+};
+
diff --git a/libgcc/config/microblaze/moddi3.asm b/libgcc/config/microblaze/moddi3.asm
new file mode 100644
index 00000000000..4923b45ffeb
--- /dev/null
+++ b/libgcc/config/microblaze/moddi3.asm
@@ -0,0 +1,115 @@
+###################################
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# modsi3.asm
+#
+# modulo operation for 64 bit integers.
+#
+#######################################
+
+
+ .globl __moddi3
+ .ent __moddi3
+__moddi3:
+ .frame r1,0,r15
+
+#Change the stack pointer value and Save callee saved regs
+ addik r1,r1,-24
+ swi r25,r1,0
+ swi r26,r1,4
+ swi r27,r1,8 # used for sign
+ swi r28,r1,12 # used for loop count
+ swi r29,r1,16 # Used for div value High
+ swi r30,r1,20 # Used for div value Low
+
+#Check for Zero Value in the divisor/dividend
+ OR r9,r5,r6 # Check for the op1 being zero
+ BEQID r9,$LaResult_Is_Zero # Result is zero
+ OR r9,r7,r8 # Check for the dividend being zero
+ BEQI r9,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BGEId r5,$La1_Pos
+ XOR r27,r5,r7 # Get the sign of the result
+ RSUBI r6,r6,0 # Make dividend positive
+ RSUBIC r5,r5,0 # Make dividend positive
+$La1_Pos:
+ BGEI r7,$La2_Pos
+ RSUBI r8,r8,0 # Make Divisor Positive
+ RSUBIC r9,r9,0 # Make Divisor Positive
+$La2_Pos:
+ ADDIK r4,r0,0 # Clear mod low
+ ADDIK r3,r0,0 # Clear mod high
+ ADDIK r29,r0,0 # clear div high
+ ADDIK r30,r0,0 # clear div low
+ ADDIK r28,r0,64 # Initialize the loop count
+ # First part try to find the first '1' in the r5/r6
+$LaDIV1:
+ ADD r6,r6,r6
+ ADDC r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1
+ ADDIK r28,r28,-1
+$LaDIV2:
+ ADD r6,r6,r6
+ ADDC r5,r5,r5 # left shift logical r5/r6 get the '1' into the Carry
+ ADDC r4,r4,r4 # Move that bit into the Mod register
+ ADDC r3,r3,r3 # Move carry into high mod register
+ rsub r18,r7,r3 # Compare the High Parts of Mod and Divisor
+ bnei r18,$L_High_EQ
+ rsub r18,r6,r4 # Compare Low Parts only if Mod[h] == Divisor[h]
+$L_High_EQ:
+ rSUB r26,r8,r4 # Subtract divisor[L] from Mod[L]
+ rsubc r25,r7,r3 # Subtract divisor[H] from Mod[H]
+ BLTi r25,$LaMOD_TOO_SMALL
+ OR r3,r0,r25 # move r25 to mod [h]
+ OR r4,r0,r26 # move r26 to mod [l]
+ ADDI r30,r30,1
+ ADDC r29,r29,r0
+$LaMOD_TOO_SMALL:
+ ADDIK r28,r28,-1
+ BEQi r28,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div [low]
+ ADDC r29,r29,r29 # Move the carry generated into high
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r27,$LaRETURN_HERE
+ rsubi r30,r30,0
+ rsubc r29,r29,r0
+ BRI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r29,r0,r0 # set result to 0 [High]
+ or r30,r0,r0 # set result to 0 [Low]
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r29 and the divisor and the dividend
+
+ lwi r25,r1,0
+ lwi r26,r1,4
+ lwi r27,r1,8
+ lwi r28,r1,12
+ lwi r29,r1,16
+ lwi r30,r1,20
+ rtsd r15,8
+ addik r1,r1,24
+ .end __moddi3
+
diff --git a/libgcc/config/microblaze/modsi3.asm b/libgcc/config/microblaze/modsi3.asm
new file mode 100644
index 00000000000..cae95c8bc63
--- /dev/null
+++ b/libgcc/config/microblaze/modsi3.asm
@@ -0,0 +1,93 @@
+###################################
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# modsi3.asm
+#
+# modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+ .globl __modsi3
+ .ent __modsi3
+ .type __modsi3,@function
+__modsi3:
+ .frame r1,0,r15
+
+ addik r1,r1,-16
+ swi r28,r1,0
+ swi r29,r1,4
+ swi r30,r1,8
+ swi r31,r1,12
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQI r5,$LaResult_Is_Zero # Result is Zero
+ BGEId r5,$LaR5_Pos
+ ADD r28,r5,r0 # Get the sign of the result [ Depends only on the first arg]
+ RSUBI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BGEI r6,$LaR6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDIK r3,r0,0 # Clear mod
+ ADDIK r30,r0,0 # clear div
+ ADDIK r29,r0,32 # Initialize the loop count
+ # First part try to find the first '1' in the r5
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1 #
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r3,r3,r3 # Move that bit into the Mod register
+ rSUB r31,r6,r3 # Try to subtract (r30 a r6)
+ BLTi r31,$LaMOD_TOO_SMALL
+ OR r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r28,$LaRETURN_HERE
+ BRId $LaRETURN_HERE
+ rsubi r3,r3,0 # Negate the result
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r3,r0,r0 # set result to 0 [Both mod as well as div are 0]
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lwi r28,r1,0
+ lwi r29,r1,4
+ lwi r30,r1,8
+ lwi r31,r1,12
+ rtsd r15,8
+ addik r1,r1,16
+ .end __modsi3
+ .size __modsi3, . - __modsi3
+
diff --git a/libgcc/config/microblaze/muldi3_hard.asm b/libgcc/config/microblaze/muldi3_hard.asm
new file mode 100644
index 00000000000..0499e2a550b
--- /dev/null
+++ b/libgcc/config/microblaze/muldi3_hard.asm
@@ -0,0 +1,144 @@
+###################################-
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# muldi3_hard.asm
+#
+# Multiply operation for 64 bit integers, for devices with hard multiply
+# Input : Operand1[H] in Reg r5
+# Operand1[L] in Reg r6
+# Operand2[H] in Reg r7
+# Operand2[L] in Reg r8
+# Output: Result[H] in Reg r3
+# Result[L] in Reg r4
+#
+# Explaination:
+#
+# Both the input numbers are divided into 16 bit number as follows
+# op1 = A B C D
+# op2 = E F G H
+# result = D * H
+# + (C * H + D * G) << 16
+# + (B * H + C * G + D * F) << 32
+# + (A * H + B * G + C * F + D * E) << 48
+#
+# Only 64 bits of the output are considered
+#
+#######################################
+
+ .globl muldi3_hardproc
+ .ent muldi3_hardproc
+muldi3_hardproc:
+ addi r1,r1,-40
+
+# Save the input operands on the caller's stack
+ swi r5,r1,44
+ swi r6,r1,48
+ swi r7,r1,52
+ swi r8,r1,56
+
+# Store all the callee saved registers
+ sw r20,r1,r0
+ swi r21,r1,4
+ swi r22,r1,8
+ swi r23,r1,12
+ swi r24,r1,16
+ swi r25,r1,20
+ swi r26,r1,24
+ swi r27,r1,28
+
+# Load all the 16 bit values for A thru H
+ lhui r20,r1,44 # A
+ lhui r21,r1,46 # B
+ lhui r22,r1,48 # C
+ lhui r23,r1,50 # D
+ lhui r24,r1,52 # E
+ lhui r25,r1,54 # F
+ lhui r26,r1,56 # G
+ lhui r27,r1,58 # H
+
+# D * H ==> LSB of the result on stack ==> Store1
+ mul r9,r23,r27
+ swi r9,r1,36 # Pos2 and Pos3
+
+# Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2
+# Store the carry generated in position 2 for Pos 3
+ lhui r11,r1,36 # Pos2
+ mul r9,r22,r27 # C * H
+ mul r10,r23,r26 # D * G
+ add r9,r9,r10
+ addc r12,r0,r0
+ add r9,r9,r11
+ addc r12,r12,r0 # Store the Carry
+ shi r9,r1,36 # Store Pos2
+ swi r9,r1,32
+ lhui r11,r1,32
+ shi r11,r1,34 # Store Pos1
+
+# Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1
+ mul r9,r21,r27 # B * H
+ mul r10,r22,r26 # C * G
+ mul r7,r23,r25 # D * F
+ add r9,r9,r11
+ add r9,r9,r10
+ add r9,r9,r7
+ swi r9,r1,32 # Pos0 and Pos1
+
+# Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0
+ lhui r11,r1,32 # Pos0
+ mul r9,r20,r27 # A * H
+ mul r10,r21,r26 # B * G
+ mul r7,r22,r25 # C * F
+ mul r8,r23,r24 # D * E
+ add r9,r9,r11
+ add r9,r9,r10
+ add r9,r9,r7
+ add r9,r9,r8
+ sext16 r9,r9 # Sign extend the MSB
+ shi r9,r1,32
+
+# Move results to r3 and r4
+ lhui r3,r1,32
+ add r3,r3,r12
+ shi r3,r1,32
+ lwi r3,r1,32 # Hi Part
+ lwi r4,r1,36 # Lo Part
+
+# Restore Callee saved registers
+ lw r20,r1,r0
+ lwi r21,r1,4
+ lwi r22,r1,8
+ lwi r23,r1,12
+ lwi r24,r1,16
+ lwi r25,r1,20
+ lwi r26,r1,24
+ lwi r27,r1,28
+
+# Restore Frame and return
+ rtsd r15,8
+ addi r1,r1,40
+
+.end muldi3_hardproc
+
+
diff --git a/libgcc/config/microblaze/mulsi3.asm b/libgcc/config/microblaze/mulsi3.asm
new file mode 100644
index 00000000000..03fe0288df8
--- /dev/null
+++ b/libgcc/config/microblaze/mulsi3.asm
@@ -0,0 +1,69 @@
+###################################-*-asm*-
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# mulsi3.asm
+#
+# Multiply operation for 32 bit integers.
+# Input : Operand1 in Reg r5
+# Operand2 in Reg r6
+# Output: Result [op1 * op2] in Reg r3
+#
+#######################################
+
+ .globl __mulsi3
+ .ent __mulsi3
+ .type __mulsi3,@function
+__mulsi3:
+ .frame r1,0,r15
+ add r3,r0,r0
+ BEQI r5,$L_Result_Is_Zero # Multiply by Zero
+ BEQI r6,$L_Result_Is_Zero # Multiply by Zero
+ BGEId r5,$L_R5_Pos
+ XOR r4,r5,r6 # Get the sign of the result
+ RSUBI r5,r5,0 # Make r5 positive
+$L_R5_Pos:
+ BGEI r6,$L_R6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$L_R6_Pos:
+ bri $L1
+$L2:
+ add r5,r5,r5
+$L1:
+ srl r6,r6
+ addc r7,r0,r0
+ beqi r7,$L2
+ bneid r6,$L2
+ add r3,r3,r5
+ blti r4,$L_NegateResult
+ rtsd r15,8
+ nop
+$L_NegateResult:
+ rtsd r15,8
+ rsub r3,r3,r0
+$L_Result_Is_Zero:
+ rtsd r15,8
+ addi r3,r0,0
+ .end __mulsi3
+ .size __mulsi3, . - __mulsi3
diff --git a/libgcc/config/microblaze/stack_overflow_exit.asm b/libgcc/config/microblaze/stack_overflow_exit.asm
new file mode 100644
index 00000000000..30b31f0a5ba
--- /dev/null
+++ b/libgcc/config/microblaze/stack_overflow_exit.asm
@@ -0,0 +1,61 @@
+###################################-*-asm*-
+#
+# Copyright 2009 Free Software Foundation, Inc.
+#
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# stack_overflow_exit.asm
+#
+# Checks for stack overflows and sets the global variable
+# stack_overflow_error with the value of current stack pointer
+#
+# This routine exits from the program
+#
+#######################################
+
+ .globl _stack_overflow_error
+ .data
+ .align 2
+ .type _stack_overflow_error,@object
+ .size _stack_overflow_error,4
+_stack_overflow_error:
+ .data32 0
+
+ .text
+ .globl _stack_overflow_exit
+ .ent _stack_overflow_exit
+ .type _stack_overflow_exit,@function
+
+_stack_overflow_exit:
+#ifdef __PIC__
+ mfs r20,rpc
+ addik r20,r20,_GLOBAL_OFFSET_TABLE_+8
+ swi r1,r20,_stack_overflow_error@GOTOFF
+ bri exit@PLT
+#else
+ swi r1,r0,_stack_overflow_error
+ bri exit
+#endif
+
+ .end _stack_overflow_exit
+ .size _stack_overflow_exit,. - _stack_overflow_exit
diff --git a/libgcc/config/microblaze/t-microblaze b/libgcc/config/microblaze/t-microblaze
new file mode 100644
index 00000000000..85fc8d39d8a
--- /dev/null
+++ b/libgcc/config/microblaze/t-microblaze
@@ -0,0 +1,12 @@
+LIB2ADD += \
+ $(srcdir)/config/microblaze/divsi3.asm \
+ $(srcdir)/config/microblaze/moddi3.asm \
+ $(srcdir)/config/microblaze/modsi3.asm \
+ $(srcdir)/config/microblaze/muldi3_hard.asm \
+ $(srcdir)/config/microblaze/mulsi3.asm \
+ $(srcdir)/config/microblaze/stack_overflow_exit.asm \
+ $(srcdir)/config/microblaze/udivsi3.asm \
+ $(srcdir)/config/microblaze/umodsi3.asm \
+ $(srcdir)/config/microblaze/divsi3_table.c
+
+MULTILIB_OPTIONS = mxl-barrel-shift mno-xl-soft-mul mxl-multiply-high
diff --git a/libgcc/config/microblaze/udivsi3.asm b/libgcc/config/microblaze/udivsi3.asm
new file mode 100644
index 00000000000..879cd349ca7
--- /dev/null
+++ b/libgcc/config/microblaze/udivsi3.asm
@@ -0,0 +1,103 @@
+###################################-
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# udivsi3.asm
+#
+# Unsigned divide operation.
+# Input : Divisor in Reg r5
+# Dividend in Reg r6
+# Output: Result in Reg r3
+#
+#######################################
+
+ .globl __udivsi3
+ .ent __udivsi3
+ .type __udivsi3,@function
+__udivsi3:
+ .frame r1,0,r15
+
+ ADDIK r1,r1,-12
+ SWI r29,r1,0
+ SWI r30,r1,4
+ SWI r31,r1,8
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQID r5,$LaResult_Is_Zero # Result is Zero
+ ADDIK r30,r0,0 # Clear mod
+ ADDIK r29,r0,32 # Initialize the loop count
+
+ # Check if r6 and r5 are equal # if yes, return 1
+ RSUB r18,r5,r6
+ BEQID r18,$LaRETURN_HERE
+ ADDIK r3,r0,1
+
+ # Check if (uns)r6 is greater than (uns)r5. In that case, just return 0
+ XOR r18,r5,r6
+ BGEID r18,16
+ ADD r3,r0,r0 # We would anyways clear r3
+ BLTI r6,$LaRETURN_HERE # r6[bit 31 = 1] hence is greater
+ BRI $LCheckr6
+ RSUB r18,r6,r5 # MICROBLAZEcmp
+ BLTI r18,$LaRETURN_HERE
+
+ # If r6 [bit 31] is set, then return result as 1
+$LCheckr6:
+ BGTI r6,$LaDIV0
+ BRID $LaRETURN_HERE
+ ADDIK r3,r0,1
+
+ # First part try to find the first '1' in the r5
+$LaDIV0:
+ BLTI r5,$LaDIV2
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGTID r5,$LaDIV1
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r30,r30,r30 # Move that bit into the Mod register
+ RSUB r31,r6,r30 # Try to subtract (r30 a r6)
+ BLTI r31,$LaMOD_TOO_SMALL
+ OR r30,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r3,r3,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r3,r3,r3 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BRI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ OR r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+ # Restore values of CSRs and that of r3 and the divisor and the dividend
+ LWI r29,r1,0
+ LWI r30,r1,4
+ LWI r31,r1,8
+ RTSD r15,8
+ ADDIK r1,r1,12
+ .end __udivsi3
+ .size __udivsi3, . - __udivsi3
diff --git a/libgcc/config/microblaze/umodsi3.asm b/libgcc/config/microblaze/umodsi3.asm
new file mode 100644
index 00000000000..f7fd0087965
--- /dev/null
+++ b/libgcc/config/microblaze/umodsi3.asm
@@ -0,0 +1,106 @@
+###################################
+#
+# Copyright 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file 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 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# umodsi3.asm
+#
+# Unsigned modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+ .globl __umodsi3
+ .ent __umodsi3
+ .type __umodsi3,@function
+__umodsi3:
+ .frame r1,0,r15
+
+ addik r1,r1,-12
+ swi r29,r1,0
+ swi r30,r1,4
+ swi r31,r1,8
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQId r5,$LaResult_Is_Zero # Result is Zero
+ ADDIK r3,r0,0 # Clear div
+ ADDIK r30,r0,0 # clear mod
+ ADDIK r29,r0,32 # Initialize the loop count
+
+# Check if r6 and r5 are equal # if yes, return 0
+ rsub r18,r5,r6
+ beqi r18,$LaRETURN_HERE
+
+# Check if (uns)r6 is greater than (uns)r5. In that case, just return r5
+ xor r18,r5,r6
+ bgeid r18,16
+ addik r3,r5,0
+ blti r6,$LaRETURN_HERE
+ bri $LCheckr6
+ rsub r18,r5,r6 # MICROBLAZEcmp
+ bgti r18,$LaRETURN_HERE
+
+# If r6 [bit 31] is set, then return result as r5-r6
+$LCheckr6:
+ bgtid r6,$LaDIV0
+ addik r3,r0,0
+ addik r18,r0,0x7fffffff
+ and r5,r5,r18
+ and r6,r6,r18
+ brid $LaRETURN_HERE
+ rsub r3,r6,r5
+# First part: try to find the first '1' in the r5
+$LaDIV0:
+ BLTI r5,$LaDIV2
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1 #
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r3,r3,r3 # Move that bit into the Mod register
+ rSUB r31,r6,r3 # Try to subtract (r3 a r6)
+ BLTi r31,$LaMOD_TOO_SMALL
+ OR r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BRI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lwi r29,r1,0
+ lwi r30,r1,4
+ lwi r31,r1,8
+ rtsd r15,8
+ addik r1,r1,12
+.end __umodsi3
+ .size __umodsi3, . - __umodsi3
diff --git a/libgcc/config/t-stack b/libgcc/config/t-stack
new file mode 100644
index 00000000000..cc0366b4cd8
--- /dev/null
+++ b/libgcc/config/t-stack
@@ -0,0 +1,4 @@
+# Makefile fragment to provide generic support for -fsplit-stack.
+# This should be used in config.host for any host which supports
+# -fsplit-stack.
+LIB2ADD_ST += $(srcdir)/generic-morestack.c $(srcdir)/generic-morestack-thread.c
diff --git a/libgcc/configure b/libgcc/configure
index f5224276693..8a27aab1886 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -576,10 +576,13 @@ RANLIB
NM
LIPO
AR
+toolexeclibdir
+toolexecdir
target_subdir
host_subdir
build_subdir
build_libsubdir
+target_noncanonical
host_noncanonical
host_os
host_vendor
@@ -2174,6 +2177,8 @@ esac
esac
+
+
# post-stage1 host modules use a different CC_FOR_BUILD so, in order to
# have matching libraries, they should use host libraries: Makefile.tpl
# arranges to pass --with-build-libsubdir=$(HOST_SUBDIR).
@@ -2204,6 +2209,36 @@ fi
target_subdir=${target_noncanonical}
+# Calculate toolexeclibdir
+# Also toolexecdir, though it's only used in toolexeclibdir
+case ${version_specific_libs} in
+ yes)
+ # Need the gcc compiler version to know where to install libraries
+ # and header files if --enable-version-specific-runtime-libs option
+ # is selected.
+ toolexecdir='$(libdir)/gcc/$(target_noncanonical)'
+ toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
+ ;;
+ no)
+ if test -n "$with_cross_host" &&
+ test x"$with_cross_host" != x"no"; then
+ # Install a library built with a cross compiler in tooldir, not libdir.
+ toolexecdir='$(exec_prefix)/$(target_noncanonical)'
+ toolexeclibdir='$(toolexecdir)/lib'
+ else
+ toolexecdir='$(libdir)/gcc-lib/$(target_noncanonical)'
+ toolexeclibdir='$(libdir)'
+ fi
+ multi_os_directory=`$CC -print-multi-os-directory`
+ case $multi_os_directory in
+ .) ;; # Avoid trailing /.
+ *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+ esac
+ ;;
+esac
+
+
+
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
@@ -3634,11 +3669,12 @@ $as_echo "$libgcc_cv_dfp" >&6; }
decimal_float=$libgcc_cv_dfp
+
# Check whether --enable-decimal-float was given.
if test "${enable_decimal_float+set}" = set; then :
enableval=$enable_decimal_float;
case $enable_decimal_float in
- yes | no | bid | dpd) ;;
+ yes | no | bid | dpd) default_decimal_float=$enable_decimal_float ;;
*) as_fn_error "'$enable_decimal_float' is an invalid value for --enable-decimal-float.
Valid choices are 'yes', 'bid', 'dpd', and 'no'." "$LINENO" 5 ;;
esac
@@ -3646,10 +3682,14 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'." "$LINENO" 5 ;;
else
case $host in
- powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux*)
+ powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
+ i?86*-*-mingw* | x86_64*-*-mingw* | \
+ i?86*-*-cygwin*)
enable_decimal_float=yes
;;
*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: decimal float is not supported for this target, ignored" >&5
+$as_echo "$as_me: WARNING: decimal float is not supported for this target, ignored" >&2;}
enable_decimal_float=no
;;
esac
@@ -3658,16 +3698,26 @@ fi
# x86's use BID format instead of DPD
-if test x$enable_decimal_float = xyes; then
- case $host in
- i?86*-*-linux* | x86_64*-*-linux*)
- enable_decimal_float=bid
- ;;
- *)
- enable_decimal_float=dpd
- ;;
- esac
-fi
+case x$enable_decimal_float in
+ xyes)
+ case $host in
+ i?86*-*-* | x86_64*-*-*)
+ enable_decimal_float=bid
+ ;;
+ *)
+ enable_decimal_float=dpd
+ ;;
+ esac
+ default_decimal_float=$enable_decimal_float
+ ;;
+ xno)
+ # ENABLE_DECIMAL_FLOAT is set to 0. But we have to have proper
+ # dependency on libdecnumber.
+ default_decimal_float=dpd
+ ;;
+esac
+
+
# Check for fixed-point support.
@@ -3692,6 +3742,30 @@ $as_echo "$libgcc_cv_fixed_point" >&6; }
fixed_point=$libgcc_cv_fixed_point
+# Check for assembler CFI support.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether assembler supports CFI directives" >&5
+$as_echo_n "checking whether assembler supports CFI directives... " >&6; }
+if test "${libgcc_cv_cfi+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+asm("\n\
+ .text\n\
+ .cfi_startproc\n\
+ .cfi_personality 0, symbol\n\
+ .cfi_endproc");
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libgcc_cv_cfi=yes
+else
+ libgcc_cv_cfi=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_cfi" >&5
+$as_echo "$libgcc_cv_cfi" >&6; }
+
# Check 32bit or 64bit for x86.
case ${host} in
i?86*-*-* | x86_64*-*-*)
@@ -3715,7 +3789,7 @@ esac
# Link with -nostartfiles -nodefaultlibs since neither are present while
# building libgcc.
case ${host} in
-i?86-*-solaris2.1[0-9]*)
+i?86-*-solaris2*)
cat > conftest.s <<EOF
.section .eh_frame,"a",@unwind
.zero 4
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index ce467dda598..7dbe114e394 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -5,6 +5,7 @@ sinclude(../config/tls.m4)
sinclude(../config/acx.m4)
sinclude(../config/no-executables.m4)
sinclude(../config/override.m4)
+sinclude(../config/dfp.m4)
AC_PREREQ(2.64)
AC_INIT([GNU C Runtime Library], 1.0,,[libgcc])
@@ -103,8 +104,39 @@ esac
AC_CANONICAL_HOST
ACX_NONCANONICAL_HOST
+ACX_NONCANONICAL_TARGET
GCC_TOPLEV_SUBDIRS
+# Calculate toolexeclibdir
+# Also toolexecdir, though it's only used in toolexeclibdir
+case ${version_specific_libs} in
+ yes)
+ # Need the gcc compiler version to know where to install libraries
+ # and header files if --enable-version-specific-runtime-libs option
+ # is selected.
+ toolexecdir='$(libdir)/gcc/$(target_noncanonical)'
+ toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
+ ;;
+ no)
+ if test -n "$with_cross_host" &&
+ test x"$with_cross_host" != x"no"; then
+ # Install a library built with a cross compiler in tooldir, not libdir.
+ toolexecdir='$(exec_prefix)/$(target_noncanonical)'
+ toolexeclibdir='$(toolexecdir)/lib'
+ else
+ toolexecdir='$(libdir)/gcc-lib/$(target_noncanonical)'
+ toolexeclibdir='$(libdir)'
+ fi
+ multi_os_directory=`$CC -print-multi-os-directory`
+ case $multi_os_directory in
+ .) ;; # Avoid trailing /.
+ *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+ esac
+ ;;
+esac
+AC_SUBST(toolexecdir)
+AC_SUBST(toolexeclibdir)
+
dnl These must be called before AM_PROG_LIBTOOL, because it may want
dnl to call AC_CHECK_PROG.
AC_CHECK_TOOL(AR, ar)
@@ -125,41 +157,7 @@ AC_CACHE_CHECK([whether decimal floating point is supported], [libgcc_cv_dfp],
decimal_float=$libgcc_cv_dfp
AC_SUBST(decimal_float)
-AC_ARG_ENABLE(decimal-float,
-[ --enable-decimal-float={no,yes,bid,dpd}
- enable decimal float extension to C. Selecting 'bid'
- or 'dpd' choses which decimal floating point format
- to use],
-[
- case $enable_decimal_float in
- yes | no | bid | dpd) ;;
- *) AC_MSG_ERROR(['$enable_decimal_float' is an invalid value for --enable-decimal-float.
-Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
- esac
-],
-[
- case $host in
- powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux*)
- enable_decimal_float=yes
- ;;
- *)
- enable_decimal_float=no
- ;;
- esac
-])
-
-# x86's use BID format instead of DPD
-if test x$enable_decimal_float = xyes; then
- case $host in
- i?86*-*-linux* | x86_64*-*-linux*)
- enable_decimal_float=bid
- ;;
- *)
- enable_decimal_float=dpd
- ;;
- esac
-fi
-AC_SUBST(enable_decimal_float)
+GCC_AC_ENABLE_DECIMAL_FLOAT([$host])
# Check for fixed-point support.
AC_CACHE_CHECK([whether fixed-point is supported], [libgcc_cv_fixed_point],
@@ -168,6 +166,17 @@ AC_CACHE_CHECK([whether fixed-point is supported], [libgcc_cv_fixed_point],
fixed_point=$libgcc_cv_fixed_point
AC_SUBST(fixed_point)
+# Check for assembler CFI support.
+AC_CACHE_CHECK([whether assembler supports CFI directives], [libgcc_cv_cfi],
+ [AC_COMPILE_IFELSE(
+[asm("\n\
+ .text\n\
+ .cfi_startproc\n\
+ .cfi_personality 0, symbol\n\
+ .cfi_endproc");],
+ [libgcc_cv_cfi=yes],
+ [libgcc_cv_cfi=no])])
+
# Check 32bit or 64bit for x86.
case ${host} in
i?86*-*-* | x86_64*-*-*)
@@ -191,7 +200,7 @@ esac
# Link with -nostartfiles -nodefaultlibs since neither are present while
# building libgcc.
case ${host} in
-i?86-*-solaris2.1[[0-9]]*)
+i?86-*-solaris2*)
cat > conftest.s <<EOF
.section .eh_frame,"a",@unwind
.zero 4
diff --git a/libgcc/generic-morestack-thread.c b/libgcc/generic-morestack-thread.c
new file mode 100644
index 00000000000..bc237957ef6
--- /dev/null
+++ b/libgcc/generic-morestack-thread.c
@@ -0,0 +1,162 @@
+/* Thread library support for -fsplit-stack. */
+/* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+ Contributed by Ian Lance Taylor <iant@google.com>.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+/* If inhibit_libc is defined, we can not compile this file. The
+ effect is that people will not be able to use -fsplit-stack. That
+ is much better than failing the build particularly since people
+ will want to define inhibit_libc while building a compiler which
+ can build glibc. */
+
+#ifndef inhibit_libc
+
+#include <pthread.h>
+
+#include "generic-morestack.h"
+
+/* We declare the pthread functions we need as weak, so that
+ libgcc_s.so does not need to be linked against -lpthread. */
+
+extern int pthread_once (pthread_once_t *, void (*) (void))
+ __attribute__ ((weak));
+
+extern int pthread_key_create (pthread_key_t *, void (*) (void *))
+ __attribute__ ((weak));
+
+extern int pthread_setspecific (pthread_key_t, const void *)
+ __attribute__ ((weak));
+
+/* The key for the list of stack segments to free when the thread
+ exits. This is created by pthread_key_create. */
+
+static pthread_key_t segment_list_key;
+
+/* Used to only run create_key once. */
+
+static pthread_once_t create_key_once = PTHREAD_ONCE_INIT;
+
+/* Release all the segments for a thread. This is the destructor
+ function used by pthread_key_create, and is called when a thread
+ exits. */
+
+static void
+free_segments (void* arg)
+{
+ __morestack_release_segments ((struct stack_segment **) arg, 1);
+}
+
+/* Set up the key for the list of segments. This is called via
+ pthread_once. */
+
+static void
+create_key (void)
+{
+ int err;
+
+ err = pthread_key_create (&segment_list_key, free_segments);
+ if (err != 0)
+ {
+ static const char msg[] = "pthread_key_create failed: errno ";
+ __morestack_fail (msg, sizeof msg - 1, err);
+ }
+}
+
+/* Pass information from the pthread_create wrapper to
+ stack_split_initialize_thread. */
+
+struct pthread_create_args
+{
+ void *(*start_routine) (void *);
+ void *arg;
+};
+
+/* Initialize a thread. This is called via pthread_create. It calls
+ a target dependent function to set up any required stack guard. */
+
+static void* stack_split_initialize_thread (void *)
+ __attribute__ ((no_split_stack));
+
+static void *
+stack_split_initialize_thread (void *varg)
+{
+ struct pthread_create_args *args = (struct pthread_create_args *) varg;
+ int err;
+ void *(*start_routine) (void *);
+ void *arg;
+
+ __stack_split_initialize ();
+
+ err = pthread_setspecific (segment_list_key, (void *) &__morestack_segments);
+ if (err != 0)
+ {
+ static const char msg[] = "pthread_setspecific failed: errno ";
+ __morestack_fail (msg, sizeof msg - 1, err);
+ }
+
+ start_routine = args->start_routine;
+ arg = args->arg;
+ free (args);
+ return (*start_routine) (arg);
+}
+
+/* This function wraps calls to pthread_create to make sure that the
+ stack guard is initialized for new threads. FIXME: This hack will
+ not be necessary if glibc supports -fsplit-stack directly. */
+
+int __wrap_pthread_create (pthread_t *, const pthread_attr_t *,
+ void *(*start_routine) (void *), void *)
+ __attribute__ ((visibility ("hidden")));
+
+extern int __real_pthread_create (pthread_t *, const pthread_attr_t *,
+ void *(*start_routine) (void *), void *)
+ __attribute__ ((weak));
+
+int
+__wrap_pthread_create (pthread_t *tid, const pthread_attr_t *attr,
+ void *(*start_routine) (void *), void *arg)
+{
+ int err;
+ struct pthread_create_args* args;
+
+ err = pthread_once (&create_key_once, create_key);
+ if (err != 0)
+ {
+ static const char msg[] = "pthread_once failed: errno ";
+ __morestack_fail (msg, sizeof msg - 1, err);
+ }
+
+ args = malloc (sizeof (struct pthread_create_args));
+ if (args == NULL)
+ return EAGAIN;
+ args->start_routine = start_routine;
+ args->arg = arg;
+ return __real_pthread_create (tid, attr, stack_split_initialize_thread, args);
+}
+
+#endif /* !defined (inhibit_libc) */
diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c
new file mode 100644
index 00000000000..7e29bbcf748
--- /dev/null
+++ b/libgcc/generic-morestack.c
@@ -0,0 +1,880 @@
+/* Library support for -fsplit-stack. */
+/* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+ Contributed by Ian Lance Taylor <iant@google.com>.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+/* If inhibit_libc is defined, we can not compile this file. The
+ effect is that people will not be able to use -fsplit-stack. That
+ is much better than failing the build particularly since people
+ will want to define inhibit_libc while building a compiler which
+ can build glibc. */
+
+#ifndef inhibit_libc
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+
+#include "generic-morestack.h"
+
+/* This file contains subroutines that are used by code compiled with
+ -fsplit-stack. */
+
+/* Declare functions to avoid warnings--there is no header file for
+ these internal functions. We give most of these functions the
+ flatten attribute in order to minimize their stack usage--here we
+ must minimize stack usage even at the cost of code size, and in
+ general inlining everything will do that. */
+
+extern void
+__generic_morestack_set_initial_sp (void *sp, size_t len)
+ __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
+
+extern void *
+__generic_morestack (size_t *frame_size, void *old_stack, size_t param_size)
+ __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
+
+extern void *
+__generic_releasestack (size_t *pavailable)
+ __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
+
+extern void
+__morestack_block_signals (void)
+ __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
+
+extern void
+__morestack_unblock_signals (void)
+ __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
+
+extern size_t
+__generic_findstack (void *stack)
+ __attribute__ ((no_split_stack, flatten, visibility ("hidden")));
+
+extern void
+__morestack_load_mmap (void)
+ __attribute__ ((no_split_stack, visibility ("hidden")));
+
+extern void *
+__morestack_allocate_stack_space (size_t size)
+ __attribute__ ((visibility ("hidden")));
+
+/* This is a function which -fsplit-stack code can call to get a list
+ of the stacks. Since it is not called only by the compiler, it is
+ not hidden. */
+
+extern void *
+__splitstack_find (void *, void *, size_t *, void **, void **, void **)
+ __attribute__ ((visibility ("default")));
+
+/* When we allocate a stack segment we put this header at the
+ start. */
+
+struct stack_segment
+{
+ /* The previous stack segment--when a function running on this stack
+ segment returns, it will run on the previous one. */
+ struct stack_segment *prev;
+ /* The next stack segment, if it has been allocated--when a function
+ is running on this stack segment, the next one is not being
+ used. */
+ struct stack_segment *next;
+ /* The total size of this stack segment. */
+ size_t size;
+ /* The stack address when this stack was created. This is used when
+ popping the stack. */
+ void *old_stack;
+ /* A list of memory blocks allocated by dynamic stack
+ allocation. */
+ struct dynamic_allocation_blocks *dynamic_allocation;
+ /* A list of dynamic memory blocks no longer needed. */
+ struct dynamic_allocation_blocks *free_dynamic_allocation;
+ /* An extra pointer in case we need some more information some
+ day. */
+ void *extra;
+};
+
+/* This structure holds the (approximate) initial stack pointer and
+ size for the system supplied stack for a thread. This is set when
+ the thread is created. We also store a sigset_t here to hold the
+ signal mask while splitting the stack, since we don't want to store
+ that on the stack. */
+
+struct initial_sp
+{
+ /* The initial stack pointer. */
+ void *sp;
+ /* The stack length. */
+ size_t len;
+ /* A signal mask, put here so that the thread can use it without
+ needing stack space. */
+ sigset_t mask;
+ /* Some extra space for later extensibility. */
+ void *extra[5];
+};
+
+/* A list of memory blocks allocated by dynamic stack allocation.
+ This is used for code that calls alloca or uses variably sized
+ arrays. */
+
+struct dynamic_allocation_blocks
+{
+ /* The next block in the list. */
+ struct dynamic_allocation_blocks *next;
+ /* The size of the allocated memory. */
+ size_t size;
+ /* The allocated memory. */
+ void *block;
+};
+
+/* These thread local global variables must be shared by all split
+ stack code across shared library boundaries. Therefore, they have
+ default visibility. They have extensibility fields if needed for
+ new versions. If more radical changes are needed, new code can be
+ written using new variable names, while still using the existing
+ variables in a backward compatible manner. Symbol versioning is
+ also used, although, since these variables are only referenced by
+ code in this file and generic-morestack-thread.c, it is likely that
+ simply using new names will suffice. */
+
+/* The first stack segment allocated for this thread. */
+
+__thread struct stack_segment *__morestack_segments
+ __attribute__ ((visibility ("default")));
+
+/* The stack segment that we think we are currently using. This will
+ be correct in normal usage, but will be incorrect if an exception
+ unwinds into a different stack segment or if longjmp jumps to a
+ different stack segment. */
+
+__thread struct stack_segment *__morestack_current_segment
+ __attribute__ ((visibility ("default")));
+
+/* The initial stack pointer and size for this thread. */
+
+__thread struct initial_sp __morestack_initial_sp
+ __attribute__ ((visibility ("default")));
+
+/* A static signal mask, to avoid taking up stack space. */
+
+static sigset_t __morestack_fullmask;
+
+/* Convert an integer to a decimal string without using much stack
+ space. Return a pointer to the part of the buffer to use. We this
+ instead of sprintf because sprintf will require too much stack
+ space. */
+
+static char *
+print_int (int val, char *buf, int buflen, size_t *print_len)
+{
+ int is_negative;
+ int i;
+ unsigned int uval;
+
+ uval = (unsigned int) val;
+ if (val >= 0)
+ is_negative = 0;
+ else
+ {
+ is_negative = 1;
+ uval = - uval;
+ }
+
+ i = buflen;
+ do
+ {
+ --i;
+ buf[i] = '0' + (uval % 10);
+ uval /= 10;
+ }
+ while (uval != 0 && i > 0);
+
+ if (is_negative)
+ {
+ if (i > 0)
+ --i;
+ buf[i] = '-';
+ }
+
+ *print_len = buflen - i;
+ return buf + i;
+}
+
+/* Print the string MSG/LEN, the errno number ERR, and a newline on
+ stderr. Then crash. */
+
+void
+__morestack_fail (const char *, size_t, int) __attribute__ ((noreturn));
+
+void
+__morestack_fail (const char *msg, size_t len, int err)
+{
+ char buf[24];
+ static const char nl[] = "\n";
+ struct iovec iov[3];
+ union { char *p; const char *cp; } const_cast;
+
+ const_cast.cp = msg;
+ iov[0].iov_base = const_cast.p;
+ iov[0].iov_len = len;
+ /* We can't call strerror, because it may try to translate the error
+ message, and that would use too much stack space. */
+ iov[1].iov_base = print_int (err, buf, sizeof buf, &iov[1].iov_len);
+ const_cast.cp = &nl[0];
+ iov[2].iov_base = const_cast.p;
+ iov[2].iov_len = sizeof nl - 1;
+ /* FIXME: On systems without writev we need to issue three write
+ calls, or punt on printing errno. For now this is irrelevant
+ since stack splitting only works on GNU/Linux anyhow. */
+ writev (2, iov, 3);
+ abort ();
+}
+
+/* Allocate a new stack segment. FRAME_SIZE is the required frame
+ size. */
+
+static struct stack_segment *
+allocate_segment (size_t frame_size)
+{
+ static unsigned int static_pagesize;
+ static int use_guard_page;
+ unsigned int pagesize;
+ unsigned int overhead;
+ unsigned int allocate;
+ void *space;
+ struct stack_segment *pss;
+
+ pagesize = static_pagesize;
+ if (pagesize == 0)
+ {
+ unsigned int p;
+
+ pagesize = getpagesize ();
+
+#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+ p = __sync_val_compare_and_swap (&static_pagesize, 0, pagesize);
+#else
+ /* Just hope this assignment is atomic. */
+ static_pagesize = pagesize;
+ p = 0;
+#endif
+
+ use_guard_page = getenv ("SPLIT_STACK_GUARD") != 0;
+
+ /* FIXME: I'm not sure this assert should be in the released
+ code. */
+ assert (p == 0 || p == pagesize);
+ }
+
+ overhead = sizeof (struct stack_segment);
+
+ allocate = pagesize;
+ if (allocate < MINSIGSTKSZ)
+ allocate = ((MINSIGSTKSZ + overhead + pagesize - 1)
+ & ~ (pagesize - 1));
+ if (allocate < frame_size)
+ allocate = ((frame_size + overhead + pagesize - 1)
+ & ~ (pagesize - 1));
+
+ if (use_guard_page)
+ allocate += pagesize;
+
+ /* FIXME: If this binary requires an executable stack, then we need
+ to set PROT_EXEC. Unfortunately figuring that out is complicated
+ and target dependent. We would need to use dl_iterate_phdr to
+ see if there is any object which does not have a PT_GNU_STACK
+ phdr, though only for architectures which use that mechanism. */
+ space = mmap (NULL, allocate, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (space == MAP_FAILED)
+ {
+ static const char msg[] =
+ "unable to allocate additional stack space: errno ";
+ __morestack_fail (msg, sizeof msg - 1, errno);
+ }
+
+ if (use_guard_page)
+ {
+ void *guard;
+
+#ifdef STACK_GROWS_DOWNWARD
+ guard = space;
+ space = (char *) space + pagesize;
+#else
+ guard = space + allocate - pagesize;
+#endif
+
+ mprotect (guard, pagesize, PROT_NONE);
+ allocate -= pagesize;
+ }
+
+ pss = (struct stack_segment *) space;
+
+ pss->prev = __morestack_current_segment;
+ pss->next = NULL;
+ pss->size = allocate - overhead;
+ pss->dynamic_allocation = NULL;
+ pss->free_dynamic_allocation = NULL;
+ pss->extra = NULL;
+
+ if (__morestack_current_segment != NULL)
+ __morestack_current_segment->next = pss;
+ else
+ __morestack_segments = pss;
+
+ return pss;
+}
+
+/* Free a list of dynamic blocks. */
+
+static void
+free_dynamic_blocks (struct dynamic_allocation_blocks *p)
+{
+ while (p != NULL)
+ {
+ struct dynamic_allocation_blocks *next;
+
+ next = p->next;
+ free (p->block);
+ free (p);
+ p = next;
+ }
+}
+
+/* Merge two lists of dynamic blocks. */
+
+static struct dynamic_allocation_blocks *
+merge_dynamic_blocks (struct dynamic_allocation_blocks *a,
+ struct dynamic_allocation_blocks *b)
+{
+ struct dynamic_allocation_blocks **pp;
+
+ if (a == NULL)
+ return b;
+ if (b == NULL)
+ return a;
+ for (pp = &a->next; *pp != NULL; pp = &(*pp)->next)
+ ;
+ *pp = b;
+ return a;
+}
+
+/* Release stack segments. If FREE_DYNAMIC is non-zero, we also free
+ any dynamic blocks. Otherwise we return them. */
+
+struct dynamic_allocation_blocks *
+__morestack_release_segments (struct stack_segment **pp, int free_dynamic)
+{
+ struct dynamic_allocation_blocks *ret;
+ struct stack_segment *pss;
+
+ ret = NULL;
+ pss = *pp;
+ while (pss != NULL)
+ {
+ struct stack_segment *next;
+ unsigned int allocate;
+
+ next = pss->next;
+
+ if (pss->dynamic_allocation != NULL
+ || pss->free_dynamic_allocation != NULL)
+ {
+ if (free_dynamic)
+ {
+ free_dynamic_blocks (pss->dynamic_allocation);
+ free_dynamic_blocks (pss->free_dynamic_allocation);
+ }
+ else
+ {
+ ret = merge_dynamic_blocks (pss->dynamic_allocation, ret);
+ ret = merge_dynamic_blocks (pss->free_dynamic_allocation, ret);
+ }
+ }
+
+ allocate = pss->size + sizeof (struct stack_segment);
+ if (munmap (pss, allocate) < 0)
+ {
+ static const char msg[] = "munmap of stack space failed: errno ";
+ __morestack_fail (msg, sizeof msg - 1, errno);
+ }
+
+ pss = next;
+ }
+ *pp = NULL;
+
+ return ret;
+}
+
+/* This function is called by a processor specific function to set the
+ initial stack pointer for a thread. The operating system will
+ always create a stack for a thread. Here we record a stack pointer
+ near the base of that stack. The size argument lets the processor
+ specific code estimate how much stack space is available on this
+ initial stack. */
+
+void
+__generic_morestack_set_initial_sp (void *sp, size_t len)
+{
+ /* The stack pointer most likely starts on a page boundary. Adjust
+ to the nearest 512 byte boundary. It's not essential that we be
+ precise here; getting it wrong will just leave some stack space
+ unused. */
+#ifdef STACK_GROWS_DOWNWARD
+ sp = (void *) ((((__UINTPTR_TYPE__) sp + 511U) / 512U) * 512U);
+#else
+ sp = (void *) ((((__UINTPTR_TYPE__) sp - 511U) / 512U) * 512U);
+#endif
+
+ __morestack_initial_sp.sp = sp;
+ __morestack_initial_sp.len = len;
+ sigemptyset (&__morestack_initial_sp.mask);
+
+ sigfillset (&__morestack_fullmask);
+#ifdef __linux__
+ /* On Linux, the first two real time signals are used by the NPTL
+ threading library. By taking them out of the set of signals, we
+ avoiding copying the signal mask in pthread_sigmask. More
+ importantly, pthread_sigmask uses less stack space on x86_64. */
+ sigdelset (&__morestack_fullmask, __SIGRTMIN);
+ sigdelset (&__morestack_fullmask, __SIGRTMIN + 1);
+#endif
+}
+
+/* This function is called by a processor specific function which is
+ run in the prologue when more stack is needed. The processor
+ specific function handles the details of saving registers and
+ frobbing the actual stack pointer. This function is responsible
+ for allocating a new stack segment and for copying a parameter
+ block from the old stack to the new one. On function entry
+ *PFRAME_SIZE is the size of the required stack frame--the returned
+ stack must be at least this large. On function exit *PFRAME_SIZE
+ is the amount of space remaining on the allocated stack. OLD_STACK
+ points at the parameters the old stack (really the current one
+ while this function is running). OLD_STACK is saved so that it can
+ be returned by a later call to __generic_releasestack. PARAM_SIZE
+ is the size in bytes of parameters to copy to the new stack. This
+ function returns a pointer to the new stack segment, pointing to
+ the memory after the parameters have been copied. The returned
+ value minus the returned *PFRAME_SIZE (or plus if the stack grows
+ upward) is the first address on the stack which should not be used.
+
+ This function is running on the old stack and has only a limited
+ amount of stack space available. */
+
+void *
+__generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size)
+{
+ size_t frame_size = *pframe_size;
+ struct stack_segment *current;
+ struct stack_segment **pp;
+ struct dynamic_allocation_blocks *dynamic;
+ char *from;
+ char *to;
+ void *ret;
+ size_t i;
+
+ current = __morestack_current_segment;
+
+ pp = current != NULL ? &current->next : &__morestack_segments;
+ if (*pp != NULL && (*pp)->size < frame_size)
+ dynamic = __morestack_release_segments (pp, 0);
+ else
+ dynamic = NULL;
+ current = *pp;
+
+ if (current == NULL)
+ current = allocate_segment (frame_size);
+
+ current->old_stack = old_stack;
+
+ __morestack_current_segment = current;
+
+ if (dynamic != NULL)
+ {
+ /* Move the free blocks onto our list. We don't want to call
+ free here, as we are short on stack space. */
+ current->free_dynamic_allocation =
+ merge_dynamic_blocks (dynamic, current->free_dynamic_allocation);
+ }
+
+ *pframe_size = current->size - param_size;
+
+#ifdef STACK_GROWS_DOWNWARD
+ {
+ char *bottom = (char *) (current + 1) + current->size;
+ to = bottom - param_size;
+ ret = bottom - param_size;
+ }
+#else
+ to = current + 1;
+ ret = (char *) (current + 1) + param_size;
+#endif
+
+ /* We don't call memcpy to avoid worrying about the dynamic linker
+ trying to resolve it. */
+ from = (char *) old_stack;
+ for (i = 0; i < param_size; i++)
+ *to++ = *from++;
+
+ return ret;
+}
+
+/* This function is called by a processor specific function when it is
+ ready to release a stack segment. We don't actually release the
+ stack segment, we just move back to the previous one. The current
+ stack segment will still be available if we need it in
+ __generic_morestack. This returns a pointer to the new stack
+ segment to use, which is the one saved by a previous call to
+ __generic_morestack. The processor specific function is then
+ responsible for actually updating the stack pointer. This sets
+ *PAVAILABLE to the amount of stack space now available. */
+
+void *
+__generic_releasestack (size_t *pavailable)
+{
+ struct stack_segment *current;
+ void *old_stack;
+
+ current = __morestack_current_segment;
+ old_stack = current->old_stack;
+ current = current->prev;
+ __morestack_current_segment = current;
+
+ if (current != NULL)
+ {
+#ifdef STACK_GROWS_DOWNWARD
+ *pavailable = (char *) old_stack - (char *) (current + 1);
+#else
+ *pavailable = (char *) (current + 1) + current->size - (char *) old_stack;
+#endif
+ }
+ else
+ {
+ size_t used;
+
+ /* We have popped back to the original stack. */
+#ifdef STACK_GROWS_DOWNWARD
+ if ((char *) old_stack >= (char *) __morestack_initial_sp.sp)
+ used = 0;
+ else
+ used = (char *) __morestack_initial_sp.sp - (char *) old_stack;
+#else
+ if ((char *) old_stack <= (char *) __morestack_initial_sp.sp)
+ used = 0;
+ else
+ used = (char *) old_stack - (char *) __morestack_initial_sp.sp;
+#endif
+
+ if (used > __morestack_initial_sp.len)
+ *pavailable = 0;
+ else
+ *pavailable = __morestack_initial_sp.len - used;
+ }
+
+ return old_stack;
+}
+
+/* Block signals while splitting the stack. This avoids trouble if we
+ try to invoke a signal handler which itself wants to split the
+ stack. */
+
+extern int pthread_sigmask (int, const sigset_t *, sigset_t *)
+ __attribute__ ((weak));
+
+void
+__morestack_block_signals (void)
+{
+ if (pthread_sigmask)
+ pthread_sigmask (SIG_BLOCK, &__morestack_fullmask,
+ &__morestack_initial_sp.mask);
+ else
+ sigprocmask (SIG_BLOCK, &__morestack_fullmask,
+ &__morestack_initial_sp.mask);
+}
+
+/* Unblock signals while splitting the stack. */
+
+void
+__morestack_unblock_signals (void)
+{
+ if (pthread_sigmask)
+ pthread_sigmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL);
+ else
+ sigprocmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL);
+}
+
+/* This function is called to allocate dynamic stack space, for alloca
+ or a variably sized array. This is a regular function with
+ sufficient stack space, so we just use malloc to allocate the
+ space. We attach the allocated blocks to the current stack
+ segment, so that they will eventually be reused or freed. */
+
+void *
+__morestack_allocate_stack_space (size_t size)
+{
+ struct stack_segment *seg, *current;
+ struct dynamic_allocation_blocks *p;
+
+ /* We have to block signals to avoid getting confused if we get
+ interrupted by a signal whose handler itself uses alloca or a
+ variably sized array. */
+ __morestack_block_signals ();
+
+ /* Since we don't want to call free while we are low on stack space,
+ we may have a list of already allocated blocks waiting to be
+ freed. Release them all, unless we find one that is large
+ enough. We don't look at every block to see if one is large
+ enough, just the first one, because we aren't trying to build a
+ memory allocator here, we're just trying to speed up common
+ cases. */
+
+ current = __morestack_current_segment;
+ p = NULL;
+ for (seg = __morestack_segments; seg != NULL; seg = seg->next)
+ {
+ p = seg->free_dynamic_allocation;
+ if (p != NULL)
+ {
+ if (p->size >= size)
+ {
+ seg->free_dynamic_allocation = p->next;
+ break;
+ }
+
+ free_dynamic_blocks (p);
+ seg->free_dynamic_allocation = NULL;
+ p = NULL;
+ }
+ }
+
+ if (p == NULL)
+ {
+ /* We need to allocate additional memory. */
+ p = malloc (sizeof (*p));
+ if (p == NULL)
+ abort ();
+ p->size = size;
+ p->block = malloc (size);
+ if (p->block == NULL)
+ abort ();
+ }
+
+ /* If we are still on the initial stack, then we have a space leak.
+ FIXME. */
+ if (current != NULL)
+ {
+ p->next = current->dynamic_allocation;
+ current->dynamic_allocation = p;
+ }
+
+ __morestack_unblock_signals ();
+
+ return p->block;
+}
+
+/* Find the stack segment for STACK and return the amount of space
+ available. This is used when unwinding the stack because of an
+ exception, in order to reset the stack guard correctly. */
+
+size_t
+__generic_findstack (void *stack)
+{
+ struct stack_segment *pss;
+ size_t used;
+
+ for (pss = __morestack_current_segment; pss != NULL; pss = pss->prev)
+ {
+ if ((char *) pss < (char *) stack
+ && (char *) pss + pss->size > (char *) stack)
+ {
+ __morestack_current_segment = pss;
+#ifdef STACK_GROWS_DOWNWARD
+ return (char *) stack - (char *) (pss + 1);
+#else
+ return (char *) (pss + 1) + pss->size - (char *) stack;
+#endif
+ }
+ }
+
+ /* We have popped back to the original stack. */
+#ifdef STACK_GROWS_DOWNWARD
+ if ((char *) stack >= (char *) __morestack_initial_sp.sp)
+ used = 0;
+ else
+ used = (char *) __morestack_initial_sp.sp - (char *) stack;
+#else
+ if ((char *) stack <= (char *) __morestack_initial_sp.sp)
+ used = 0;
+ else
+ used = (char *) stack - (char *) __morestack_initial_sp.sp;
+#endif
+
+ if (used > __morestack_initial_sp.len)
+ return 0;
+ else
+ return __morestack_initial_sp.len - used;
+}
+
+/* This function is called at program startup time to make sure that
+ mmap, munmap, and getpagesize are resolved if linking dynamically.
+ We want to resolve them while we have enough stack for them, rather
+ than calling into the dynamic linker while low on stack space. */
+
+void
+__morestack_load_mmap (void)
+{
+ /* Call with bogus values to run faster. We don't care if the call
+ fails. Pass __MORESTACK_CURRENT_SEGMENT to make sure that any
+ TLS accessor function is resolved. */
+ mmap (__morestack_current_segment, 0, PROT_READ, MAP_ANONYMOUS, -1, 0);
+ mprotect (NULL, 0, 0);
+ munmap (0, getpagesize ());
+}
+
+/* This function may be used to iterate over the stack segments.
+ This can be called like this.
+ void *next_segment = NULL;
+ void *next_sp = NULL;
+ void *initial_sp = NULL;
+ void *stack;
+ size_t stack_size;
+ while ((stack = __splitstack_find (next_segment, next_sp, &stack_size,
+ &next_segment, &next_sp,
+ &initial_sp)) != NULL)
+ {
+ // Stack segment starts at stack and is stack_size bytes long.
+ }
+
+ There is no way to iterate over the stack segments of a different
+ thread. However, what is permitted is for one thread to call this
+ with the first two values NULL, to pass next_segment, next_sp, and
+ initial_sp to a different thread, and then to suspend one way or
+ another. A different thread may run the subsequent
+ __morestack_find iterations. Of course, this will only work if the
+ first thread is suspended during the __morestack_find iterations.
+ If not, the second thread will be looking at the stack while it is
+ changing, and anything could happen.
+
+ FIXME: This should be declared in some header file, but where? */
+
+void *
+__splitstack_find (void *segment_arg, void *sp, size_t *len,
+ void **next_segment, void **next_sp,
+ void **initial_sp)
+{
+ struct stack_segment *segment;
+ void *ret;
+ char *nsp;
+
+ if (segment_arg == (void *) 1)
+ {
+ char *isp = (char *) *initial_sp;
+
+ *next_segment = (void *) 2;
+ *next_sp = NULL;
+#ifdef STACK_GROWS_DOWNWARD
+ if ((char *) sp >= isp)
+ return NULL;
+ *len = (char *) isp - (char *) sp;
+ return sp;
+#else
+ if ((char *) sp <= (char *) isp)
+ return NULL;
+ *len = (char *) sp - (char *) isp;
+ return (void *) isp;
+#endif
+ }
+ else if (segment_arg == (void *) 2)
+ return NULL;
+ else if (segment_arg != NULL)
+ segment = (struct stack_segment *) segment_arg;
+ else
+ {
+ *initial_sp = __morestack_initial_sp.sp;
+ segment = __morestack_current_segment;
+ sp = (void *) &segment;
+ while (1)
+ {
+ if (segment == NULL)
+ return __splitstack_find ((void *) 1, sp, len, next_segment,
+ next_sp, initial_sp);
+ if ((char *) sp >= (char *) (segment + 1)
+ && (char *) sp <= (char *) (segment + 1) + segment->size)
+ break;
+ segment = segment->prev;
+ }
+ }
+
+ if (segment->prev == NULL)
+ *next_segment = (void *) 1;
+ else
+ *next_segment = segment->prev;
+
+ /* The old_stack value is the address of the function parameters of
+ the function which called __morestack. So if f1 called f2 which
+ called __morestack, the stack looks like this:
+
+ parameters <- old_stack
+ return in f1
+ return in f2
+ registers pushed by __morestack
+
+ The registers pushed by __morestack may not be visible on any
+ other stack, if we are being called by a signal handler
+ immediately after the call to __morestack_unblock_signals. We
+ want to adjust our return value to include those registers. This
+ is target dependent. */
+
+ nsp = (char *) segment->old_stack;
+
+#if defined (__x86_64__)
+ nsp -= 12 * sizeof (void *);
+#elif defined (__i386__)
+ nsp -= 6 * sizeof (void *);
+#else
+#error "unrecognized target"
+#endif
+
+ *next_sp = (void *) nsp;
+
+#ifdef STACK_GROWS_DOWNWARD
+ *len = (char *) (segment + 1) + segment->size - (char *) sp;
+ ret = (void *) sp;
+#else
+ *len = (char *) sp - (char *) (segment + 1);
+ ret = (void *) (segment + 1);
+#endif
+
+ return ret;
+}
+
+#endif /* !defined (inhibit_libc) */
diff --git a/libgcc/generic-morestack.h b/libgcc/generic-morestack.h
new file mode 100644
index 00000000000..12da0acfee4
--- /dev/null
+++ b/libgcc/generic-morestack.h
@@ -0,0 +1,53 @@
+/* Library support for -fsplit-stack. */
+/* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+ Contributed by Ian Lance Taylor <iant@google.com>.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* This is a libgcc internal header file for functions shared between
+ generic-morestack.c and generic-morestack-thread.c. The latter
+ file is only used when linking with the pthread library. */
+
+/* The stack segment structure, defined in generic-morestack.c. */
+
+struct stack_segment;
+
+/* The list of stack segments for this thread. */
+
+extern __thread struct stack_segment *__morestack_segments;
+
+/* Print the string MSG/LEN, the errno number ERR, and a newline on
+ stderr, without using printf. Then crash. */
+
+extern void __morestack_fail (const char *msg, size_t len, int err)
+ __attribute__ ((noreturn, visibility ("hidden")));
+
+/* Release stack segments. */
+
+extern struct dynamic_allocation_blocks *
+ __morestack_release_segments (struct stack_segment **, int)
+ __attribute__ ((visibility ("hidden")));
+
+/* Store the stack information in a processor dependent manner. */
+
+extern void __stack_split_initialize (void)
+ __attribute__ ((visibility ("hidden")));