diff options
author | raksit <raksit@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-04-07 21:26:02 +0000 |
---|---|---|
committer | raksit <raksit@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-04-07 21:26:02 +0000 |
commit | e43928e066705a15454212156afff431afc7f5b3 (patch) | |
tree | ec2ee16bcc8a782df00eabb25aebf409356b9993 /libgcc | |
parent | 7d712a63969bf729ff518abe9bccec3319f07204 (diff) | |
download | gcc-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')
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 ? ¤t->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"))); |