summaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog124
-rw-r--r--libgcc/Makefile.in36
-rw-r--r--libgcc/config.host8
-rw-r--r--libgcc/config/arm/t-bpabi5
-rw-r--r--libgcc/config/avr/avr-lib.h76
-rw-r--r--libgcc/config/avr/lib1funcs-fixed.S874
-rw-r--r--libgcc/config/avr/lib1funcs.S423
-rw-r--r--libgcc/config/avr/t-avr65
-rw-r--r--libgcc/config/i386/libgcc-cygming.ver22
-rw-r--r--libgcc/config/i386/morestack.S13
-rw-r--r--libgcc/config/i386/t-linux2
-rw-r--r--libgcc/config/i386/t-seh-eh6
-rw-r--r--libgcc/config/i386/t-slibgcc-cygming2
-rw-r--r--libgcc/config/m32c/lib2funcs.c16
-rw-r--r--libgcc/config/m68k/linux-atomic.c4
-rw-r--r--libgcc/config/stormy16/clrsbhi2.c2
-rw-r--r--libgcc/config/stormy16/lib2funcs.c16
-rw-r--r--libgcc/config/stormy16/t-stormy161
-rw-r--r--libgcc/config/t-darwin4
-rw-r--r--libgcc/crtstuff.c16
-rw-r--r--libgcc/fixed-obj.mk2
-rw-r--r--libgcc/libgcov.c3
-rw-r--r--libgcc/longlong.h44
-rw-r--r--libgcc/static-object.mk10
-rw-r--r--libgcc/unwind-c.c15
-rw-r--r--libgcc/unwind-generic.h17
-rw-r--r--libgcc/unwind-seh.c483
27 files changed, 2073 insertions, 216 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index fbdd11ebf9c..0ea0ed3ad2a 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,127 @@
+2012-08-24 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/54222
+ * config/avr/t-avr (conv_X): Rename to func_X.
+
+2012-08-24 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/54222
+ * config/avr/lib1funcs-fixed.S: New file.
+ * config/avr/lib1funcs.S: Include it. Undefine some divmodsi
+ after they are used.
+ (neg2, neg4): New macros.
+ (__mulqihi3,__umulqihi3,__mulhi3): Rewrite non-MUL variants.
+ (__mulhisi3,__umulhisi3,__mulsi3): Rewrite non-MUL variants.
+ (__umulhisi3): Speed up MUL variant if there is enough flash.
+ * config/avr/avr-lib.h (TA, UTA): Adjust according to gcc's
+ avr-modes.def.
+ * config/avr/t-avr (LIB1ASMFUNCS): Add: _fractqqsf, _fractuqqsf,
+ _fracthqsf, _fractuhqsf, _fracthasf, _fractuhasf, _fractsasf,
+ _fractusasf, _fractsfqq, _fractsfuqq, _fractsfhq, _fractsfuhq,
+ _fractsfha, _fractsfsa, _mulqq3, _muluqq3, _mulhq3, _muluhq3,
+ _mulha3, _muluha3, _mulsa3, _mulusa3, _divqq3, _udivuqq3, _divhq3,
+ _udivuhq3, _divha3, _udivuha3, _divsa3, _udivusa3.
+ (LIB2FUNCS_EXCLUDE): Add supported functions.
+
+2012-08-22 Georg-Johann Lay <avr@gjlay.de>
+
+ * Makefile.in (fixed-funcs,fixed-conv-funcs): filter-out
+ LIB2FUNCS_EXCLUDE before adding them to libgcc-objects,
+ libgcc-s-objects.
+ * fixed-obj.mk: Only expand dependency if $o is not in
+ LIB2FUNCS_EXCLUDE.
+
+2012-08-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/t-linux (HOST_LIBGCC2_CFLAGS): New.
+
+2012-08-22 Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile.in (vis_hide, gen-hide-list): Do not make definitions
+ depend on --enable-shared.
+ ($(lib1asmfuncs-o)): Use %.vis files independent of
+ --enable-shared.
+ * static-object.mk ($(base)$(objext), $(base).vis)
+ ($(base)_s$(objext)): Use same rules for visibility handling as in
+ shared-object.mk.
+
+2012-08-21 Ian Lance Taylor <iant@google.com>
+
+ * config/i386/morestack.S (__morestack_non_split): Increase amount
+ of space allocated for non-split code stack.
+
+2012-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ * crtstuff.c (USE_PT_GNU_EH_FRAME): Define for systems using glibc
+ even if inhibit_libc.
+
+2012-08-17 Julian Brown <julian@codesourcery.com>
+
+ * Makefile.in (LIB2_DIVMOD_EXCEPTION_FLAGS): Default to
+ -fexceptions -fnon-call-exceptions if not defined.
+ ($(lib2-divmod-o), $(lib2-divmod-s-o)): Use above.
+ * config/arm/t-bpabi (LIB2_DIVMOD_EXCEPTION_FLAGS): Define.
+
+2012-08-17 Andreas Schwab <schwab@linux-m68k.org>
+
+ * config/m68k/linux-atomic.c (__sync_lock_test_and_set_1): Fix
+ type.
+
+2012-08-16 David Edelsohn <dje.gcc@gmail.com>
+
+ * config.host (*-*-aix*): Move rs6000/t-ibm-ldouble after
+ rs6000/t-slibgcc-aix.
+
+2012-08-15 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * longlong.h: (powerpc): Delete _ARCH_PWR and _ARCH_COM handling.
+
+2012-08-15 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * longlong.h: (whole file, powerpc): Adjust to single assembler syntax.
+
+2012-08-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR driver/54171
+ * Makefile.in (version): Replace top_srcdir with srcdir.
+
+2012-08-03 Jonathan Yong <jon_y@users.sourceforge.net>
+
+ * Makefile.in (version): set to BASE-VER file from gcc directory.
+
+2012-08-01 Nick Clifton <nickc@redhat.com>
+
+ * config/m32c/lib2funcs.c (__clrsbhi2): New function.
+ Implements __clrsb for an HImode argument.
+
+2012-07-31 Nick Clifton <nickc@redhat.com>
+
+ * config/stormy16/lib2funcs.c (__clrsbhi2): New function.
+ Implements __clrsb for an HImode argument.
+ * config/stormy16/clrsbhi2.c: New file:
+ * config/stormy16/t-stormy16 (LIB2ADD): Add clrsbhi2.c.
+
+2012-07-22 Steven Bosscher <steven@gcc.gnu.org>
+
+ * libgcov.c (__gcov_ior_profiler): Benign comment fix.
+
+2012-07-19 Tristan Gingold <gingold@adacore.com>
+ Richard Henderson <rth@redhat.com>
+
+ * unwind-seh.c: New file.
+ * unwind-generic.h: Include windows.h for SEH.
+ (_Unwind_Exception): Use 6 private fields for SEH.
+ (_GCC_specific_handler): Declare.
+ * unwind-c.c (__gcc_personality_seh0): New function.
+ Adjust for SEH.
+ * config/i386/libgcc-cygming.ver: New file.
+ * config/i386/t-seh-eh: New file.
+ * config.host (x86_64-*-mingw*): Default to seh.
+
+2012-07-14 Steven Bosscher <steven@gcc.gnu.org>
+
+ * config/t-darwin (crt3.0): Remove work-around for fixed PR26840.
+
2012-06-17 Uros Bizjak <ubizjak@gmail.com>
* config/i386/sfp-machine.h (FP_HANDLE_EXCEPTIONS): Use
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 22af1b40b7f..1de1b8e5a48 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -207,7 +207,7 @@ export slibdir
export toolexecdir
export toolexeclibdir
-version := $(shell $(CC) -dumpversion)
+version := $(shell cat $(srcdir)/../gcc/BASE-VER)
ifeq ($(decimal_float),yes)
ifeq ($(enable_decimal_float),bid)
@@ -363,6 +363,7 @@ ifeq ($(enable_shared),yes)
ifneq ($(LIBUNWIND),)
install-libunwind = install-libunwind
endif
+endif
# For -fvisibility=hidden. We need both a -fvisibility=hidden on
# the command line, and a #define to prevent libgcc2.h etc from
@@ -386,11 +387,8 @@ else
gen-hide-list = echo > $@
endif
-else
-# Not enable_shared.
+ifneq ($(enable_shared),yes)
iterator = $(srcdir)/empty.mk $(patsubst %,$(srcdir)/static-object.mk,$(iter-items))
-vis_hide =
-gen-hide-list = echo > \$@
endif
LIB2ADD += enable-execute-stack.c
@@ -439,7 +437,6 @@ LIB2_DIVMOD_FUNCS := $(filter-out $(LIB2FUNCS_EXCLUDE) $(LIB1ASMFUNCS), \
$(LIB2_DIVMOD_FUNCS))
# Build "libgcc1" (assembly) components.
-ifeq ($(enable_shared),yes)
lib1asmfuncs-o = $(patsubst %,%$(objext),$(LIB1ASMFUNCS))
$(lib1asmfuncs-o): %$(objext): $(srcdir)/config/$(LIB1ASMSRC) %.vis
@@ -451,14 +448,9 @@ libgcc-objects += $(lib1asmfuncs-o)
lib1asmfuncs-s-o = $(patsubst %,%_s$(objext),$(LIB1ASMFUNCS))
$(lib1asmfuncs-s-o): %_s$(objext): $(srcdir)/config/$(LIB1ASMSRC)
$(gcc_s_compile) -DL$* -xassembler-with-cpp -c $<
-libgcc-s-objects += $(lib1asmfuncs-s-o)
-
-else
+ifeq ($(enable_shared),yes)
-lib1asmfuncs-o = $(patsubst %,%$(objext),$(LIB1ASMFUNCS))
-$(lib1asmfuncs-o): %$(objext): $(srcdir)/config/$(LIB1ASMSRC)
- $(gcc_compile) -DL$* -xassembler-with-cpp -c $<
-libgcc-objects += $(lib1asmfuncs-o)
+libgcc-s-objects += $(lib1asmfuncs-s-o)
endif
@@ -497,18 +489,24 @@ libgcc-s-objects += $(patsubst %,%_s$(objext),$(sifuncs) $(difuncs) $(tifuncs))
endif
endif
+ifeq ($(LIB2_DIVMOD_EXCEPTION_FLAGS),)
+# Provide default flags for compiling divmod functions, if they haven't been
+# set already by a target-specific Makefile fragment.
+LIB2_DIVMOD_EXCEPTION_FLAGS := -fexceptions -fnon-call-exceptions
+endif
+
# Build LIB2_DIVMOD_FUNCS.
lib2-divmod-o = $(patsubst %,%$(objext),$(LIB2_DIVMOD_FUNCS))
$(lib2-divmod-o): %$(objext): $(srcdir)/libgcc2.c
$(gcc_compile) -DL$* -c $< \
- -fexceptions -fnon-call-exceptions $(vis_hide)
+ $(LIB2_DIVMOD_EXCEPTION_FLAGS) $(vis_hide)
libgcc-objects += $(lib2-divmod-o)
ifeq ($(enable_shared),yes)
lib2-divmod-s-o = $(patsubst %,%_s$(objext),$(LIB2_DIVMOD_FUNCS))
$(lib2-divmod-s-o): %_s$(objext): $(srcdir)/libgcc2.c
$(gcc_s_compile) -DL$* -c $< \
- -fexceptions -fnon-call-exceptions
+ $(LIB2_DIVMOD_EXCEPTION_FLAGS)
libgcc-s-objects += $(lib2-divmod-s-o)
endif
@@ -765,9 +763,9 @@ iter-to := $(fixed-modes)
include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items))
# Add arithmetic functions to list of objects to be built
-libgcc-objects += $(patsubst %,%$(objext),$(fixed-funcs))
+libgcc-objects += $(patsubst %,%$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-funcs)))
ifeq ($(enable_shared),yes)
-libgcc-s-objects += $(patsubst %,%_s$(objext),$(fixed-funcs))
+libgcc-s-objects += $(patsubst %,%_s$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-funcs)))
endif
# Convert from or to fractional
@@ -784,9 +782,9 @@ iter-to := $(fixed-conv-to)
include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items))
# Add conversion functions to list of objects to be built
-libgcc-objects += $(patsubst %,%$(objext),$(fixed-conv-funcs))
+libgcc-objects += $(patsubst %,%$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-conv-funcs)))
ifeq ($(enable_shared),yes)
-libgcc-s-objects += $(patsubst %,%_s$(objext),$(fixed-conv-funcs))
+libgcc-s-objects += $(patsubst %,%_s$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-conv-funcs)))
endif
endif
diff --git a/libgcc/config.host b/libgcc/config.host
index d8ad48c5e04..d7259a77484 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -618,7 +618,7 @@ x86_64-*-mingw*)
if test x$enable_sjlj_exceptions = xyes; then
tmake_eh_file="i386/t-sjlj-eh"
else
- tmake_eh_file="i386/t-dw2-eh"
+ tmake_eh_file="i386/t-seh-eh"
fi
# Shared libgcc DLL install dir depends on cross/native build.
if test x${build} = x${host} ; then
@@ -898,15 +898,15 @@ powerpcle-*-eabi*)
;;
rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
md_unwind_header=rs6000/aix-unwind.h
- tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble rs6000/t-slibgcc-aix"
+ tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble"
;;
rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
md_unwind_header=rs6000/aix-unwind.h
- tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble rs6000/t-slibgcc-aix"
+ tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble"
;;
rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
md_unwind_header=rs6000/aix-unwind.h
- tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble rs6000/t-slibgcc-aix"
+ tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble"
;;
rl78-*-elf)
tmake_file="$tm_file t-fdpbit rl78/t-rl78"
diff --git a/libgcc/config/arm/t-bpabi b/libgcc/config/arm/t-bpabi
index e79cbd7064e..dddddc7c444 100644
--- a/libgcc/config/arm/t-bpabi
+++ b/libgcc/config/arm/t-bpabi
@@ -13,3 +13,8 @@ LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
# Add the BPABI names.
SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
+
+# On ARM, specifying -fnon-call-exceptions will needlessly pull in
+# the unwinder in simple programs which use 64-bit division. Omitting
+# the option is safe.
+LIB2_DIVMOD_EXCEPTION_FLAGS := -fexceptions
diff --git a/libgcc/config/avr/avr-lib.h b/libgcc/config/avr/avr-lib.h
index daca4d81f9a..66082eb8a48 100644
--- a/libgcc/config/avr/avr-lib.h
+++ b/libgcc/config/avr/avr-lib.h
@@ -4,3 +4,79 @@
#define DI SI
typedef int QItype __attribute__ ((mode (QI)));
#endif
+
+/* fixed-bit.h does not define functions for TA and UTA because
+ that part is wrapped in #if MIN_UNITS_PER_WORD > 4.
+ This would lead to empty functions for TA and UTA.
+ Thus, supply appropriate defines as if HAVE_[U]TA == 1.
+ #define HAVE_[U]TA 1 won't work because avr-modes.def
+ uses ADJUST_BYTESIZE(TA,8) and fixed-bit.h is not generic enough
+ to arrange for such changes of the mode size. */
+
+typedef unsigned _Fract UTAtype __attribute__ ((mode (UTA)));
+
+#if defined (UTA_MODE)
+#define FIXED_SIZE 8 /* in bytes */
+#define INT_C_TYPE UDItype
+#define UINT_C_TYPE UDItype
+#define HINT_C_TYPE USItype
+#define HUINT_C_TYPE USItype
+#define MODE_NAME UTA
+#define MODE_NAME_S uta
+#define MODE_UNSIGNED 1
+#endif
+
+#if defined (FROM_UTA)
+#define FROM_TYPE 4 /* ID for fixed-point */
+#define FROM_MODE_NAME UTA
+#define FROM_MODE_NAME_S uta
+#define FROM_INT_C_TYPE UDItype
+#define FROM_SINT_C_TYPE DItype
+#define FROM_UINT_C_TYPE UDItype
+#define FROM_MODE_UNSIGNED 1
+#define FROM_FIXED_SIZE 8 /* in bytes */
+#elif defined (TO_UTA)
+#define TO_TYPE 4 /* ID for fixed-point */
+#define TO_MODE_NAME UTA
+#define TO_MODE_NAME_S uta
+#define TO_INT_C_TYPE UDItype
+#define TO_SINT_C_TYPE DItype
+#define TO_UINT_C_TYPE UDItype
+#define TO_MODE_UNSIGNED 1
+#define TO_FIXED_SIZE 8 /* in bytes */
+#endif
+
+/* Same for TAmode */
+
+typedef _Fract TAtype __attribute__ ((mode (TA)));
+
+#if defined (TA_MODE)
+#define FIXED_SIZE 8 /* in bytes */
+#define INT_C_TYPE DItype
+#define UINT_C_TYPE UDItype
+#define HINT_C_TYPE SItype
+#define HUINT_C_TYPE USItype
+#define MODE_NAME TA
+#define MODE_NAME_S ta
+#define MODE_UNSIGNED 0
+#endif
+
+#if defined (FROM_TA)
+#define FROM_TYPE 4 /* ID for fixed-point */
+#define FROM_MODE_NAME TA
+#define FROM_MODE_NAME_S ta
+#define FROM_INT_C_TYPE DItype
+#define FROM_SINT_C_TYPE DItype
+#define FROM_UINT_C_TYPE UDItype
+#define FROM_MODE_UNSIGNED 0
+#define FROM_FIXED_SIZE 8 /* in bytes */
+#elif defined (TO_TA)
+#define TO_TYPE 4 /* ID for fixed-point */
+#define TO_MODE_NAME TA
+#define TO_MODE_NAME_S ta
+#define TO_INT_C_TYPE DItype
+#define TO_SINT_C_TYPE DItype
+#define TO_UINT_C_TYPE UDItype
+#define TO_MODE_UNSIGNED 0
+#define TO_FIXED_SIZE 8 /* in bytes */
+#endif
diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S
new file mode 100644
index 00000000000..c1aff53d5fd
--- /dev/null
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -0,0 +1,874 @@
+/* -*- Mode: Asm -*- */
+;; Copyright (C) 2012
+;; Free Software Foundation, Inc.
+;; Contributed by Sean D'Epagnier (sean@depagnier.com)
+;; Georg-Johann Lay (avr@gjlay.de)
+
+;; 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.
+
+;; In addition to the permissions in the GNU General Public License, the
+;; Free Software Foundation gives you unlimited permission to link the
+;; compiled version of this file into combinations with other programs,
+;; and to distribute those combinations without any restriction coming
+;; from the use of this file. (The General Public License restrictions
+;; do apply in other respects; for example, they cover modification of
+;; the file, and distribution when not linked into a combine
+;; executable.)
+
+;; This file is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Fixed point library routines for AVR
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.section .text.libgcc.fixed, "ax", @progbits
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Conversions to float
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#if defined (L_fractqqsf)
+DEFUN __fractqqsf
+ ;; Move in place for SA -> SF conversion
+ clr r22
+ mov r23, r24
+ lsl r23
+ ;; Sign-extend
+ sbc r24, r24
+ mov r25, r24
+ XJMP __fractsasf
+ENDF __fractqqsf
+#endif /* L_fractqqsf */
+
+#if defined (L_fractuqqsf)
+DEFUN __fractuqqsf
+ ;; Move in place for USA -> SF conversion
+ clr r22
+ mov r23, r24
+ ;; Zero-extend
+ clr r24
+ clr r25
+ XJMP __fractusasf
+ENDF __fractuqqsf
+#endif /* L_fractuqqsf */
+
+#if defined (L_fracthqsf)
+DEFUN __fracthqsf
+ ;; Move in place for SA -> SF conversion
+ wmov 22, 24
+ lsl r22
+ rol r23
+ ;; Sign-extend
+ sbc r24, r24
+ mov r25, r24
+ XJMP __fractsasf
+ENDF __fracthqsf
+#endif /* L_fracthqsf */
+
+#if defined (L_fractuhqsf)
+DEFUN __fractuhqsf
+ ;; Move in place for USA -> SF conversion
+ wmov 22, 24
+ ;; Zero-extend
+ clr r24
+ clr r25
+ XJMP __fractusasf
+ENDF __fractuhqsf
+#endif /* L_fractuhqsf */
+
+#if defined (L_fracthasf)
+DEFUN __fracthasf
+ ;; Move in place for SA -> SF conversion
+ clr r22
+ mov r23, r24
+ mov r24, r25
+ ;; Sign-extend
+ lsl r25
+ sbc r25, r25
+ XJMP __fractsasf
+ENDF __fracthasf
+#endif /* L_fracthasf */
+
+#if defined (L_fractuhasf)
+DEFUN __fractuhasf
+ ;; Move in place for USA -> SF conversion
+ clr r22
+ mov r23, r24
+ mov r24, r25
+ ;; Zero-extend
+ clr r25
+ XJMP __fractusasf
+ENDF __fractuhasf
+#endif /* L_fractuhasf */
+
+
+#if defined (L_fractsqsf)
+DEFUN __fractsqsf
+ XCALL __floatsisf
+ ;; Divide non-zero results by 2^31 to move the
+ ;; decimal point into place
+ tst r25
+ breq 0f
+ subi r24, exp_lo (31)
+ sbci r25, exp_hi (31)
+0: ret
+ENDF __fractsqsf
+#endif /* L_fractsqsf */
+
+#if defined (L_fractusqsf)
+DEFUN __fractusqsf
+ XCALL __floatunsisf
+ ;; Divide non-zero results by 2^32 to move the
+ ;; decimal point into place
+ cpse r25, __zero_reg__
+ subi r25, exp_hi (32)
+ ret
+ENDF __fractusqsf
+#endif /* L_fractusqsf */
+
+#if defined (L_fractsasf)
+DEFUN __fractsasf
+ XCALL __floatsisf
+ ;; Divide non-zero results by 2^16 to move the
+ ;; decimal point into place
+ cpse r25, __zero_reg__
+ subi r25, exp_hi (16)
+ ret
+ENDF __fractsasf
+#endif /* L_fractsasf */
+
+#if defined (L_fractusasf)
+DEFUN __fractusasf
+ XCALL __floatunsisf
+ ;; Divide non-zero results by 2^16 to move the
+ ;; decimal point into place
+ cpse r25, __zero_reg__
+ subi r25, exp_hi (16)
+ ret
+ENDF __fractusasf
+#endif /* L_fractusasf */
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Conversions from float
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#if defined (L_fractsfqq)
+DEFUN __fractsfqq
+ ;; Multiply with 2^{24+7} to get a QQ result in r25
+ subi r24, exp_lo (-31)
+ sbci r25, exp_hi (-31)
+ XCALL __fixsfsi
+ mov r24, r25
+ ret
+ENDF __fractsfqq
+#endif /* L_fractsfqq */
+
+#if defined (L_fractsfuqq)
+DEFUN __fractsfuqq
+ ;; Multiply with 2^{24+8} to get a UQQ result in r25
+ subi r25, exp_hi (-32)
+ XCALL __fixunssfsi
+ mov r24, r25
+ ret
+ENDF __fractsfuqq
+#endif /* L_fractsfuqq */
+
+#if defined (L_fractsfha)
+DEFUN __fractsfha
+ ;; Multiply with 2^24 to get a HA result in r25:r24
+ subi r25, exp_hi (-24)
+ XJMP __fixsfsi
+ENDF __fractsfha
+#endif /* L_fractsfha */
+
+#if defined (L_fractsfuha)
+DEFUN __fractsfuha
+ ;; Multiply with 2^24 to get a UHA result in r25:r24
+ subi r25, exp_hi (-24)
+ XJMP __fixunssfsi
+ENDF __fractsfuha
+#endif /* L_fractsfuha */
+
+#if defined (L_fractsfhq)
+DEFUN __fractsfsq
+ENDF __fractsfsq
+
+DEFUN __fractsfhq
+ ;; Multiply with 2^{16+15} to get a HQ result in r25:r24
+ ;; resp. with 2^31 to get a SQ result in r25:r22
+ subi r24, exp_lo (-31)
+ sbci r25, exp_hi (-31)
+ XJMP __fixsfsi
+ENDF __fractsfhq
+#endif /* L_fractsfhq */
+
+#if defined (L_fractsfuhq)
+DEFUN __fractsfusq
+ENDF __fractsfusq
+
+DEFUN __fractsfuhq
+ ;; Multiply with 2^{16+16} to get a UHQ result in r25:r24
+ ;; resp. with 2^32 to get a USQ result in r25:r22
+ subi r25, exp_hi (-32)
+ XJMP __fixunssfsi
+ENDF __fractsfuhq
+#endif /* L_fractsfuhq */
+
+#if defined (L_fractsfsa)
+DEFUN __fractsfsa
+ ;; Multiply with 2^16 to get a SA result in r25:r22
+ subi r25, exp_hi (-16)
+ XJMP __fixsfsi
+ENDF __fractsfsa
+#endif /* L_fractsfsa */
+
+#if defined (L_fractsfusa)
+DEFUN __fractsfusa
+ ;; Multiply with 2^16 to get a USA result in r25:r22
+ subi r25, exp_hi (-16)
+ XJMP __fixunssfsi
+ENDF __fractsfusa
+#endif /* L_fractsfusa */
+
+
+;; For multiplication the functions here are called directly from
+;; avr-fixed.md instead of using the standard libcall mechanisms.
+;; This can make better code because GCC knows exactly which
+;; of the call-used registers (not all of them) are clobbered. */
+
+/*******************************************************
+ Fractional Multiplication 8 x 8 without MUL
+*******************************************************/
+
+#if defined (L_mulqq3) && !defined (__AVR_HAVE_MUL__)
+;;; R23 = R24 * R25
+;;; Clobbers: __tmp_reg__, R22, R24, R25
+;;; Rounding: ???
+DEFUN __mulqq3
+ XCALL __fmuls
+ ;; TR 18037 requires that (-1) * (-1) does not overflow
+ ;; The only input that can produce -1 is (-1)^2.
+ dec r23
+ brvs 0f
+ inc r23
+0: ret
+ENDF __mulqq3
+#endif /* L_mulqq3 && ! HAVE_MUL */
+
+/*******************************************************
+ Fractional Multiply .16 x .16 with and without MUL
+*******************************************************/
+
+#if defined (L_mulhq3)
+;;; Same code with and without MUL, but the interfaces differ:
+;;; no MUL: (R25:R24) = (R22:R23) * (R24:R25)
+;;; Clobbers: ABI, called by optabs
+;;; MUL: (R25:R24) = (R19:R18) * (R27:R26)
+;;; Clobbers: __tmp_reg__, R22, R23
+;;; Rounding: -0.5 LSB <= error <= 0.5 LSB
+DEFUN __mulhq3
+ XCALL __mulhisi3
+ ;; Shift result into place
+ lsl r23
+ rol r24
+ rol r25
+ brvs 1f
+ ;; Round
+ sbrc r23, 7
+ adiw r24, 1
+ ret
+1: ;; Overflow. TR 18037 requires (-1)^2 not to overflow
+ ldi r24, lo8 (0x7fff)
+ ldi r25, hi8 (0x7fff)
+ ret
+ENDF __mulhq3
+#endif /* defined (L_mulhq3) */
+
+#if defined (L_muluhq3)
+;;; Same code with and without MUL, but the interfaces differ:
+;;; no MUL: (R25:R24) *= (R23:R22)
+;;; Clobbers: ABI, called by optabs
+;;; MUL: (R25:R24) = (R19:R18) * (R27:R26)
+;;; Clobbers: __tmp_reg__, R22, R23
+;;; Rounding: -0.5 LSB < error <= 0.5 LSB
+DEFUN __muluhq3
+ XCALL __umulhisi3
+ ;; Round
+ sbrc r23, 7
+ adiw r24, 1
+ ret
+ENDF __muluhq3
+#endif /* L_muluhq3 */
+
+
+/*******************************************************
+ Fixed Multiply 8.8 x 8.8 with and without MUL
+*******************************************************/
+
+#if defined (L_mulha3)
+;;; Same code with and without MUL, but the interfaces differ:
+;;; no MUL: (R25:R24) = (R22:R23) * (R24:R25)
+;;; Clobbers: ABI, called by optabs
+;;; MUL: (R25:R24) = (R19:R18) * (R27:R26)
+;;; Clobbers: __tmp_reg__, R22, R23
+;;; Rounding: -0.5 LSB <= error <= 0.5 LSB
+DEFUN __mulha3
+ XCALL __mulhisi3
+ XJMP __muluha3_round
+ENDF __mulha3
+#endif /* L_mulha3 */
+
+#if defined (L_muluha3)
+;;; Same code with and without MUL, but the interfaces differ:
+;;; no MUL: (R25:R24) *= (R23:R22)
+;;; Clobbers: ABI, called by optabs
+;;; MUL: (R25:R24) = (R19:R18) * (R27:R26)
+;;; Clobbers: __tmp_reg__, R22, R23
+;;; Rounding: -0.5 LSB < error <= 0.5 LSB
+DEFUN __muluha3
+ XCALL __umulhisi3
+ XJMP __muluha3_round
+ENDF __muluha3
+#endif /* L_muluha3 */
+
+#if defined (L_muluha3_round)
+DEFUN __muluha3_round
+ ;; Shift result into place
+ mov r25, r24
+ mov r24, r23
+ ;; Round
+ sbrc r22, 7
+ adiw r24, 1
+ ret
+ENDF __muluha3_round
+#endif /* L_muluha3_round */
+
+
+/*******************************************************
+ Fixed Multiplication 16.16 x 16.16
+*******************************************************/
+
+#if defined (__AVR_HAVE_MUL__)
+
+;; Multiplier
+#define A0 16
+#define A1 A0+1
+#define A2 A1+1
+#define A3 A2+1
+
+;; Multiplicand
+#define B0 20
+#define B1 B0+1
+#define B2 B1+1
+#define B3 B2+1
+
+;; Result
+#define C0 24
+#define C1 C0+1
+#define C2 C1+1
+#define C3 C2+1
+
+#if defined (L_mulusa3)
+;;; (C3:C0) = (A3:A0) * (B3:B0)
+;;; Clobbers: __tmp_reg__
+;;; Rounding: -0.5 LSB < error <= 0.5 LSB
+DEFUN __mulusa3
+ ;; Some of the MUL instructions have LSBs outside the result.
+ ;; Don't ignore these LSBs in order to tame rounding error.
+ ;; Use C2/C3 for these LSBs.
+
+ clr C0
+ clr C1
+ mul A0, B0 $ movw C2, r0
+
+ mul A1, B0 $ add C3, r0 $ adc C0, r1
+ mul A0, B1 $ add C3, r0 $ adc C0, r1 $ rol C1
+
+ ;; Round
+ sbrc C3, 7
+ adiw C0, 1
+
+ ;; The following MULs don't have LSBs outside the result.
+ ;; C2/C3 is the high part.
+
+ mul A0, B2 $ add C0, r0 $ adc C1, r1 $ sbc C2, C2
+ mul A1, B1 $ add C0, r0 $ adc C1, r1 $ sbci C2, 0
+ mul A2, B0 $ add C0, r0 $ adc C1, r1 $ sbci C2, 0
+ neg C2
+
+ mul A0, B3 $ add C1, r0 $ adc C2, r1 $ sbc C3, C3
+ mul A1, B2 $ add C1, r0 $ adc C2, r1 $ sbci C3, 0
+ mul A2, B1 $ add C1, r0 $ adc C2, r1 $ sbci C3, 0
+ mul A3, B0 $ add C1, r0 $ adc C2, r1 $ sbci C3, 0
+ neg C3
+
+ mul A1, B3 $ add C2, r0 $ adc C3, r1
+ mul A2, B2 $ add C2, r0 $ adc C3, r1
+ mul A3, B1 $ add C2, r0 $ adc C3, r1
+
+ mul A2, B3 $ add C3, r0
+ mul A3, B2 $ add C3, r0
+
+ clr __zero_reg__
+ ret
+ENDF __mulusa3
+#endif /* L_mulusa3 */
+
+#if defined (L_mulsa3)
+;;; (C3:C0) = (A3:A0) * (B3:B0)
+;;; Clobbers: __tmp_reg__
+;;; Rounding: -0.5 LSB <= error <= 0.5 LSB
+DEFUN __mulsa3
+ XCALL __mulusa3
+ tst B3
+ brpl 1f
+ sub C2, A0
+ sbc C3, A1
+1: sbrs A3, 7
+ ret
+ sub C2, B0
+ sbc C3, B1
+ ret
+ENDF __mulsa3
+#endif /* L_mulsa3 */
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+
+#else /* __AVR_HAVE_MUL__ */
+
+#define A0 18
+#define A1 A0+1
+#define A2 A0+2
+#define A3 A0+3
+
+#define B0 22
+#define B1 B0+1
+#define B2 B0+2
+#define B3 B0+3
+
+#define C0 22
+#define C1 C0+1
+#define C2 C0+2
+#define C3 C0+3
+
+;; __tmp_reg__
+#define CC0 0
+;; __zero_reg__
+#define CC1 1
+#define CC2 16
+#define CC3 17
+
+#define AA0 26
+#define AA1 AA0+1
+#define AA2 30
+#define AA3 AA2+1
+
+#if defined (L_mulsa3)
+;;; (R25:R22) *= (R21:R18)
+;;; Clobbers: ABI, called by optabs
+;;; Rounding: -1 LSB <= error <= 1 LSB
+DEFUN __mulsa3
+ push B0
+ push B1
+ bst B3, 7
+ XCALL __mulusa3
+ ;; A survived in 31:30:27:26
+ rcall 1f
+ pop AA1
+ pop AA0
+ bst AA3, 7
+1: brtc 9f
+ ;; 1-extend A/B
+ sub C2, AA0
+ sbc C3, AA1
+9: ret
+ENDF __mulsa3
+#endif /* L_mulsa3 */
+
+#if defined (L_mulusa3)
+;;; (R25:R22) *= (R21:R18)
+;;; Clobbers: ABI, called by optabs and __mulsua
+;;; Rounding: -1 LSB <= error <= 1 LSB
+;;; Does not clobber T and A[] survives in 26, 27, 30, 31
+DEFUN __mulusa3
+ push CC2
+ push CC3
+ ; clear result
+ clr __tmp_reg__
+ wmov CC2, CC0
+ ; save multiplicand
+ wmov AA0, A0
+ wmov AA2, A2
+ rjmp 3f
+
+ ;; Loop the integral part
+
+1: ;; CC += A * 2^n; n >= 0
+ add CC0,A0 $ adc CC1,A1 $ adc CC2,A2 $ adc CC3,A3
+
+2: ;; A <<= 1
+ lsl A0 $ rol A1 $ rol A2 $ rol A3
+
+3: ;; IBIT(B) >>= 1
+ ;; Carry = n-th bit of B; n >= 0
+ lsr B3
+ ror B2
+ brcs 1b
+ sbci B3, 0
+ brne 2b
+
+ ;; Loop the fractional part
+ ;; B2/B3 is 0 now, use as guard bits for rounding
+ ;; Restore multiplicand
+ wmov A0, AA0
+ wmov A2, AA2
+ rjmp 5f
+
+4: ;; CC += A:Guard * 2^n; n < 0
+ add B3,B2 $ adc CC0,A0 $ adc CC1,A1 $ adc CC2,A2 $ adc CC3,A3
+5:
+ ;; A:Guard >>= 1
+ lsr A3 $ ror A2 $ ror A1 $ ror A0 $ ror B2
+
+ ;; FBIT(B) <<= 1
+ ;; Carry = n-th bit of B; n < 0
+ lsl B0
+ rol B1
+ brcs 4b
+ sbci B0, 0
+ brne 5b
+
+ ;; Move result into place and round
+ lsl B3
+ wmov C2, CC2
+ wmov C0, CC0
+ clr __zero_reg__
+ adc C0, __zero_reg__
+ adc C1, __zero_reg__
+ adc C2, __zero_reg__
+ adc C3, __zero_reg__
+
+ ;; Epilogue
+ pop CC3
+ pop CC2
+ ret
+ENDF __mulusa3
+#endif /* L_mulusa3 */
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef AA0
+#undef AA1
+#undef AA2
+#undef AA3
+#undef CC0
+#undef CC1
+#undef CC2
+#undef CC3
+
+#endif /* __AVR_HAVE_MUL__ */
+
+/*******************************************************
+ Fractional Division 8 / 8
+*******************************************************/
+
+#define r_divd r25 /* dividend */
+#define r_quo r24 /* quotient */
+#define r_div r22 /* divisor */
+
+#if defined (L_divqq3)
+DEFUN __divqq3
+ mov r0, r_divd
+ eor r0, r_div
+ sbrc r_div, 7
+ neg r_div
+ sbrc r_divd, 7
+ neg r_divd
+ cp r_divd, r_div
+ breq __divqq3_minus1 ; if equal return -1
+ XCALL __udivuqq3
+ lsr r_quo
+ sbrc r0, 7 ; negate result if needed
+ neg r_quo
+ ret
+__divqq3_minus1:
+ ldi r_quo, 0x80
+ ret
+ENDF __divqq3
+#endif /* defined (L_divqq3) */
+
+#if defined (L_udivuqq3)
+DEFUN __udivuqq3
+ clr r_quo ; clear quotient
+ inc __zero_reg__ ; init loop counter, used per shift
+__udivuqq3_loop:
+ lsl r_divd ; shift dividend
+ brcs 0f ; dividend overflow
+ cp r_divd,r_div ; compare dividend & divisor
+ brcc 0f ; dividend >= divisor
+ rol r_quo ; shift quotient (with CARRY)
+ rjmp __udivuqq3_cont
+0:
+ sub r_divd,r_div ; restore dividend
+ lsl r_quo ; shift quotient (without CARRY)
+__udivuqq3_cont:
+ lsl __zero_reg__ ; shift loop-counter bit
+ brne __udivuqq3_loop
+ com r_quo ; complement result
+ ; because C flag was complemented in loop
+ ret
+ENDF __udivuqq3
+#endif /* defined (L_udivuqq3) */
+
+#undef r_divd
+#undef r_quo
+#undef r_div
+
+
+/*******************************************************
+ Fractional Division 16 / 16
+*******************************************************/
+#define r_divdL 26 /* dividend Low */
+#define r_divdH 27 /* dividend Hig */
+#define r_quoL 24 /* quotient Low */
+#define r_quoH 25 /* quotient High */
+#define r_divL 22 /* divisor */
+#define r_divH 23 /* divisor */
+#define r_cnt 21
+
+#if defined (L_divhq3)
+DEFUN __divhq3
+ mov r0, r_divdH
+ eor r0, r_divH
+ sbrs r_divH, 7
+ rjmp 1f
+ NEG2 r_divL
+1:
+ sbrs r_divdH, 7
+ rjmp 2f
+ NEG2 r_divdL
+2:
+ cp r_divdL, r_divL
+ cpc r_divdH, r_divH
+ breq __divhq3_minus1 ; if equal return -1
+ XCALL __udivuhq3
+ lsr r_quoH
+ ror r_quoL
+ brpl 9f
+ ;; negate result if needed
+ NEG2 r_quoL
+9:
+ ret
+__divhq3_minus1:
+ ldi r_quoH, 0x80
+ clr r_quoL
+ ret
+ENDF __divhq3
+#endif /* defined (L_divhq3) */
+
+#if defined (L_udivuhq3)
+DEFUN __udivuhq3
+ sub r_quoH,r_quoH ; clear quotient and carry
+ ;; FALLTHRU
+ENDF __udivuhq3
+
+DEFUN __udivuha3_common
+ clr r_quoL ; clear quotient
+ ldi r_cnt,16 ; init loop counter
+__udivuhq3_loop:
+ rol r_divdL ; shift dividend (with CARRY)
+ rol r_divdH
+ brcs __udivuhq3_ep ; dividend overflow
+ cp r_divdL,r_divL ; compare dividend & divisor
+ cpc r_divdH,r_divH
+ brcc __udivuhq3_ep ; dividend >= divisor
+ rol r_quoL ; shift quotient (with CARRY)
+ rjmp __udivuhq3_cont
+__udivuhq3_ep:
+ sub r_divdL,r_divL ; restore dividend
+ sbc r_divdH,r_divH
+ lsl r_quoL ; shift quotient (without CARRY)
+__udivuhq3_cont:
+ rol r_quoH ; shift quotient
+ dec r_cnt ; decrement loop counter
+ brne __udivuhq3_loop
+ com r_quoL ; complement result
+ com r_quoH ; because C flag was complemented in loop
+ ret
+ENDF __udivuha3_common
+#endif /* defined (L_udivuhq3) */
+
+/*******************************************************
+ Fixed Division 8.8 / 8.8
+*******************************************************/
+#if defined (L_divha3)
+DEFUN __divha3
+ mov r0, r_divdH
+ eor r0, r_divH
+ sbrs r_divH, 7
+ rjmp 1f
+ NEG2 r_divL
+1:
+ sbrs r_divdH, 7
+ rjmp 2f
+ NEG2 r_divdL
+2:
+ XCALL __udivuha3
+ sbrs r0, 7 ; negate result if needed
+ ret
+ NEG2 r_quoL
+ ret
+ENDF __divha3
+#endif /* defined (L_divha3) */
+
+#if defined (L_udivuha3)
+DEFUN __udivuha3
+ mov r_quoH, r_divdL
+ mov r_divdL, r_divdH
+ clr r_divdH
+ lsl r_quoH ; shift quotient into carry
+ XJMP __udivuha3_common ; same as fractional after rearrange
+ENDF __udivuha3
+#endif /* defined (L_udivuha3) */
+
+#undef r_divdL
+#undef r_divdH
+#undef r_quoL
+#undef r_quoH
+#undef r_divL
+#undef r_divH
+#undef r_cnt
+
+/*******************************************************
+ Fixed Division 16.16 / 16.16
+*******************************************************/
+
+#define r_arg1L 24 /* arg1 gets passed already in place */
+#define r_arg1H 25
+#define r_arg1HL 26
+#define r_arg1HH 27
+#define r_divdL 26 /* dividend Low */
+#define r_divdH 27
+#define r_divdHL 30
+#define r_divdHH 31 /* dividend High */
+#define r_quoL 22 /* quotient Low */
+#define r_quoH 23
+#define r_quoHL 24
+#define r_quoHH 25 /* quotient High */
+#define r_divL 18 /* divisor Low */
+#define r_divH 19
+#define r_divHL 20
+#define r_divHH 21 /* divisor High */
+#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
+
+#if defined (L_divsa3)
+DEFUN __divsa3
+ mov r0, r_arg1HH
+ eor r0, r_divHH
+ sbrs r_divHH, 7
+ rjmp 1f
+ NEG4 r_divL
+1:
+ sbrs r_arg1HH, 7
+ rjmp 2f
+ NEG4 r_arg1L
+2:
+ XCALL __udivusa3
+ sbrs r0, 7 ; negate result if needed
+ ret
+ NEG4 r_quoL
+ ret
+ENDF __divsa3
+#endif /* defined (L_divsa3) */
+
+#if defined (L_udivusa3)
+DEFUN __udivusa3
+ ldi r_divdHL, 32 ; init loop counter
+ mov r_cnt, r_divdHL
+ clr r_divdHL
+ clr r_divdHH
+ wmov r_quoL, r_divdHL
+ lsl r_quoHL ; shift quotient into carry
+ rol r_quoHH
+__udivusa3_loop:
+ rol r_divdL ; shift dividend (with CARRY)
+ rol r_divdH
+ rol r_divdHL
+ rol r_divdHH
+ brcs __udivusa3_ep ; dividend overflow
+ cp r_divdL,r_divL ; compare dividend & divisor
+ cpc r_divdH,r_divH
+ cpc r_divdHL,r_divHL
+ cpc r_divdHH,r_divHH
+ brcc __udivusa3_ep ; dividend >= divisor
+ rol r_quoL ; shift quotient (with CARRY)
+ rjmp __udivusa3_cont
+__udivusa3_ep:
+ sub r_divdL,r_divL ; restore dividend
+ sbc r_divdH,r_divH
+ sbc r_divdHL,r_divHL
+ sbc r_divdHH,r_divHH
+ lsl r_quoL ; shift quotient (without CARRY)
+__udivusa3_cont:
+ rol r_quoH ; shift quotient
+ rol r_quoHL
+ rol r_quoHH
+ dec r_cnt ; decrement loop counter
+ brne __udivusa3_loop
+ com r_quoL ; complement result
+ com r_quoH ; because C flag was complemented in loop
+ com r_quoHL
+ com r_quoHH
+ ret
+ENDF __udivusa3
+#endif /* defined (L_udivusa3) */
+
+#undef r_arg1L
+#undef r_arg1H
+#undef r_arg1HL
+#undef r_arg1HH
+#undef r_divdL
+#undef r_divdH
+#undef r_divdHL
+#undef r_divdHH
+#undef r_quoL
+#undef r_quoH
+#undef r_quoHL
+#undef r_quoHH
+#undef r_divL
+#undef r_divH
+#undef r_divHL
+#undef r_divHH
+#undef r_cnt
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 95a7d3d4eeb..6b9879ee7d7 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -91,6 +91,35 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.endfunc
.endm
+;; Negate a 2-byte value held in consecutive registers
+.macro NEG2 reg
+ com \reg+1
+ neg \reg
+ sbci \reg+1, -1
+.endm
+
+;; Negate a 4-byte value held in consecutive registers
+.macro NEG4 reg
+ com \reg+3
+ com \reg+2
+ com \reg+1
+.if \reg >= 16
+ neg \reg
+ sbci \reg+1, -1
+ sbci \reg+2, -1
+ sbci \reg+3, -1
+.else
+ com \reg
+ adc \reg, __zero_reg__
+ adc \reg+1, __zero_reg__
+ adc \reg+2, __zero_reg__
+ adc \reg+3, __zero_reg__
+.endif
+.endm
+
+#define exp_lo(N) hlo8 ((N) << 23)
+#define exp_hi(N) hhi8 ((N) << 23)
+
.section .text.libgcc.mul, "ax", @progbits
@@ -126,175 +155,246 @@ ENDF __mulqi3
#endif /* defined (L_mulqi3) */
-#if defined (L_mulqihi3)
-DEFUN __mulqihi3
- clr r25
- sbrc r24, 7
- dec r25
- clr r23
- sbrc r22, 7
- dec r22
- XJMP __mulhi3
-ENDF __mulqihi3:
-#endif /* defined (L_mulqihi3) */
+
+/*******************************************************
+ Widening Multiplication 16 = 8 x 8 without MUL
+ Multiplication 16 x 16 without MUL
+*******************************************************/
+
+#define A0 r22
+#define A1 r23
+#define B0 r24
+#define BB0 r20
+#define B1 r25
+;; Output overlaps input, thus expand result in CC0/1
+#define C0 r24
+#define C1 r25
+#define CC0 __tmp_reg__
+#define CC1 R21
#if defined (L_umulqihi3)
+;;; R25:R24 = (unsigned int) R22 * (unsigned int) R24
+;;; (C1:C0) = (unsigned int) A0 * (unsigned int) B0
+;;; Clobbers: __tmp_reg__, R21..R23
DEFUN __umulqihi3
- clr r25
- clr r23
- XJMP __mulhi3
+ clr A1
+ clr B1
+ XJMP __mulhi3
ENDF __umulqihi3
-#endif /* defined (L_umulqihi3) */
+#endif /* L_umulqihi3 */
-/*******************************************************
- Multiplication 16 x 16 without MUL
-*******************************************************/
-#if defined (L_mulhi3)
-#define r_arg1L r24 /* multiplier Low */
-#define r_arg1H r25 /* multiplier High */
-#define r_arg2L r22 /* multiplicand Low */
-#define r_arg2H r23 /* multiplicand High */
-#define r_resL __tmp_reg__ /* result Low */
-#define r_resH r21 /* result High */
+#if defined (L_mulqihi3)
+;;; R25:R24 = (signed int) R22 * (signed int) R24
+;;; (C1:C0) = (signed int) A0 * (signed int) B0
+;;; Clobbers: __tmp_reg__, R20..R23
+DEFUN __mulqihi3
+ ;; Sign-extend B0
+ clr B1
+ sbrc B0, 7
+ com B1
+ ;; The multiplication runs twice as fast if A1 is zero, thus:
+ ;; Zero-extend A0
+ clr A1
+#ifdef __AVR_HAVE_JMP_CALL__
+ ;; Store B0 * sign of A
+ clr BB0
+ sbrc A0, 7
+ mov BB0, B0
+ call __mulhi3
+#else /* have no CALL */
+ ;; Skip sign-extension of A if A >= 0
+ ;; Same size as with the first alternative but avoids errata skip
+ ;; and is faster if A >= 0
+ sbrs A0, 7
+ rjmp __mulhi3
+ ;; If A < 0 store B
+ mov BB0, B0
+ rcall __mulhi3
+#endif /* HAVE_JMP_CALL */
+ ;; 1-extend A after the multiplication
+ sub C1, BB0
+ ret
+ENDF __mulqihi3
+#endif /* L_mulqihi3 */
+#if defined (L_mulhi3)
+;;; R25:R24 = R23:R22 * R25:R24
+;;; (C1:C0) = (A1:A0) * (B1:B0)
+;;; Clobbers: __tmp_reg__, R21..R23
DEFUN __mulhi3
- clr r_resH ; clear result
- clr r_resL ; clear result
-__mulhi3_loop:
- sbrs r_arg1L,0
- rjmp __mulhi3_skip1
- add r_resL,r_arg2L ; result + multiplicand
- adc r_resH,r_arg2H
-__mulhi3_skip1:
- add r_arg2L,r_arg2L ; shift multiplicand
- adc r_arg2H,r_arg2H
-
- cp r_arg2L,__zero_reg__
- cpc r_arg2H,__zero_reg__
- breq __mulhi3_exit ; while multiplicand != 0
-
- lsr r_arg1H ; gets LSB of multiplier
- ror r_arg1L
- sbiw r_arg1L,0
- brne __mulhi3_loop ; exit if multiplier = 0
-__mulhi3_exit:
- mov r_arg1H,r_resH ; result to return register
- mov r_arg1L,r_resL
- ret
-ENDF __mulhi3
-#undef r_arg1L
-#undef r_arg1H
-#undef r_arg2L
-#undef r_arg2H
-#undef r_resL
-#undef r_resH
+ ;; Clear result
+ clr CC0
+ clr CC1
+ rjmp 3f
+1:
+ ;; Bit n of A is 1 --> C += B << n
+ add CC0, B0
+ adc CC1, B1
+2:
+ lsl B0
+ rol B1
+3:
+ ;; If B == 0 we are ready
+ sbiw B0, 0
+ breq 9f
+
+ ;; Carry = n-th bit of A
+ lsr A1
+ ror A0
+ ;; If bit n of A is set, then go add B * 2^n to C
+ brcs 1b
+
+ ;; Carry = 0 --> The ROR above acts like CP A0, 0
+ ;; Thus, it is sufficient to CPC the high part to test A against 0
+ cpc A1, __zero_reg__
+ ;; Only proceed if A != 0
+ brne 2b
+9:
+ ;; Move Result into place
+ mov C0, CC0
+ mov C1, CC1
+ ret
+ENDF __mulhi3
+#endif /* L_mulhi3 */
-#endif /* defined (L_mulhi3) */
+#undef A0
+#undef A1
+#undef B0
+#undef BB0
+#undef B1
+#undef C0
+#undef C1
+#undef CC0
+#undef CC1
+
+
+#define A0 22
+#define A1 A0+1
+#define A2 A0+2
+#define A3 A0+3
+
+#define B0 18
+#define B1 B0+1
+#define B2 B0+2
+#define B3 B0+3
+
+#define CC0 26
+#define CC1 CC0+1
+#define CC2 30
+#define CC3 CC2+1
+
+#define C0 22
+#define C1 C0+1
+#define C2 C0+2
+#define C3 C0+3
/*******************************************************
Widening Multiplication 32 = 16 x 16 without MUL
*******************************************************/
-#if defined (L_mulhisi3)
-DEFUN __mulhisi3
-;;; FIXME: This is dead code (noone calls it)
- mov_l r18, r24
- mov_h r19, r25
- clr r24
- sbrc r23, 7
- dec r24
- mov r25, r24
- clr r20
- sbrc r19, 7
- dec r20
- mov r21, r20
- XJMP __mulsi3
-ENDF __mulhisi3
-#endif /* defined (L_mulhisi3) */
-
#if defined (L_umulhisi3)
DEFUN __umulhisi3
-;;; FIXME: This is dead code (noone calls it)
- mov_l r18, r24
- mov_h r19, r25
- clr r24
- clr r25
- mov_l r20, r24
- mov_h r21, r25
+ wmov B0, 24
+ ;; Zero-extend B
+ clr B2
+ clr B3
+ ;; Zero-extend A
+ wmov A2, B2
XJMP __mulsi3
ENDF __umulhisi3
-#endif /* defined (L_umulhisi3) */
+#endif /* L_umulhisi3 */
+
+#if defined (L_mulhisi3)
+DEFUN __mulhisi3
+ wmov B0, 24
+ ;; Sign-extend B
+ lsl r25
+ sbc B2, B2
+ mov B3, B2
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ ;; Sign-extend A
+ clr A2
+ sbrc A1, 7
+ com A2
+ mov A3, A2
+ XJMP __mulsi3
+#else /* no __AVR_ERRATA_SKIP_JMP_CALL__ */
+ ;; Zero-extend A and __mulsi3 will run at least twice as fast
+ ;; compared to a sign-extended A.
+ clr A2
+ clr A3
+ sbrs A1, 7
+ XJMP __mulsi3
+ ;; If A < 0 then perform the B * 0xffff.... before the
+ ;; very multiplication by initializing the high part of the
+ ;; result CC with -B.
+ wmov CC2, A2
+ sub CC2, B0
+ sbc CC3, B1
+ XJMP __mulsi3_helper
+#endif /* __AVR_ERRATA_SKIP_JMP_CALL__ */
+ENDF __mulhisi3
+#endif /* L_mulhisi3 */
+
-#if defined (L_mulsi3)
/*******************************************************
Multiplication 32 x 32 without MUL
*******************************************************/
-#define r_arg1L r22 /* multiplier Low */
-#define r_arg1H r23
-#define r_arg1HL r24
-#define r_arg1HH r25 /* multiplier High */
-
-#define r_arg2L r18 /* multiplicand Low */
-#define r_arg2H r19
-#define r_arg2HL r20
-#define r_arg2HH r21 /* multiplicand High */
-
-#define r_resL r26 /* result Low */
-#define r_resH r27
-#define r_resHL r30
-#define r_resHH r31 /* result High */
+#if defined (L_mulsi3)
DEFUN __mulsi3
- clr r_resHH ; clear result
- clr r_resHL ; clear result
- clr r_resH ; clear result
- clr r_resL ; clear result
-__mulsi3_loop:
- sbrs r_arg1L,0
- rjmp __mulsi3_skip1
- add r_resL,r_arg2L ; result + multiplicand
- adc r_resH,r_arg2H
- adc r_resHL,r_arg2HL
- adc r_resHH,r_arg2HH
-__mulsi3_skip1:
- add r_arg2L,r_arg2L ; shift multiplicand
- adc r_arg2H,r_arg2H
- adc r_arg2HL,r_arg2HL
- adc r_arg2HH,r_arg2HH
-
- lsr r_arg1HH ; gets LSB of multiplier
- ror r_arg1HL
- ror r_arg1H
- ror r_arg1L
- brne __mulsi3_loop
- sbiw r_arg1HL,0
- cpc r_arg1H,r_arg1L
- brne __mulsi3_loop ; exit if multiplier = 0
-__mulsi3_exit:
- mov_h r_arg1HH,r_resHH ; result to return register
- mov_l r_arg1HL,r_resHL
- mov_h r_arg1H,r_resH
- mov_l r_arg1L,r_resL
- ret
-ENDF __mulsi3
+ ;; Clear result
+ clr CC2
+ clr CC3
+ ;; FALLTHRU
+ENDF __mulsi3
-#undef r_arg1L
-#undef r_arg1H
-#undef r_arg1HL
-#undef r_arg1HH
-
-#undef r_arg2L
-#undef r_arg2H
-#undef r_arg2HL
-#undef r_arg2HH
-
-#undef r_resL
-#undef r_resH
-#undef r_resHL
-#undef r_resHH
+DEFUN __mulsi3_helper
+ clr CC0
+ clr CC1
+ rjmp 3f
+
+1: ;; If bit n of A is set, then add B * 2^n to the result in CC
+ ;; CC += B
+ add CC0,B0 $ adc CC1,B1 $ adc CC2,B2 $ adc CC3,B3
+
+2: ;; B <<= 1
+ lsl B0 $ rol B1 $ rol B2 $ rol B3
+
+3: ;; A >>= 1: Carry = n-th bit of A
+ lsr A3 $ ror A2 $ ror A1 $ ror A0
+
+ brcs 1b
+ ;; Only continue if A != 0
+ sbci A1, 0
+ brne 2b
+ sbiw A2, 0
+ brne 2b
+
+ ;; All bits of A are consumed: Copy result to return register C
+ wmov C0, CC0
+ wmov C2, CC2
+ ret
+ENDF __mulsi3_helper
+#endif /* L_mulsi3 */
-#endif /* defined (L_mulsi3) */
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef CC0
+#undef CC1
+#undef CC2
+#undef CC3
#endif /* !defined (__AVR_HAVE_MUL__) */
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -316,7 +416,7 @@ ENDF __mulsi3
#define C3 C0+3
/*******************************************************
- Widening Multiplication 32 = 16 x 16
+ Widening Multiplication 32 = 16 x 16 with MUL
*******************************************************/
#if defined (L_mulhisi3)
@@ -364,7 +464,17 @@ DEFUN __umulhisi3
mul A1, B1
movw C2, r0
mul A0, B1
+#ifdef __AVR_HAVE_JMP_CALL__
+ ;; This function is used by many other routines, often multiple times.
+ ;; Therefore, if the flash size is not too limited, avoid the RCALL
+ ;; and inverst 6 Bytes to speed things up.
+ add C1, r0
+ adc C2, r1
+ clr __zero_reg__
+ adc C3, __zero_reg__
+#else
rcall 1f
+#endif
mul A1, B0
1: add C1, r0
adc C2, r1
@@ -375,7 +485,7 @@ ENDF __umulhisi3
#endif /* L_umulhisi3 */
/*******************************************************
- Widening Multiplication 32 = 16 x 32
+ Widening Multiplication 32 = 16 x 32 with MUL
*******************************************************/
#if defined (L_mulshisi3)
@@ -425,7 +535,7 @@ ENDF __muluhisi3
#endif /* L_muluhisi3 */
/*******************************************************
- Multiplication 32 x 32
+ Multiplication 32 x 32 with MUL
*******************************************************/
#if defined (L_mulsi3)
@@ -468,7 +578,7 @@ ENDF __mulsi3
#endif /* __AVR_HAVE_MUL__ */
/*******************************************************
- Multiplication 24 x 24
+ Multiplication 24 x 24 with MUL
*******************************************************/
#if defined (L_mulpsi3)
@@ -1247,6 +1357,19 @@ __divmodsi4_exit:
ENDF __divmodsi4
#endif /* defined (L_divmodsi4) */
+#undef r_remHH
+#undef r_remHL
+#undef r_remH
+#undef r_remL
+#undef r_arg1HH
+#undef r_arg1HL
+#undef r_arg1H
+#undef r_arg1L
+#undef r_arg2HH
+#undef r_arg2HL
+#undef r_arg2H
+#undef r_arg2L
+#undef r_cnt
/*******************************************************
Division 64 / 64
@@ -2757,9 +2880,7 @@ DEFUN __fmulsu_exit
XJMP __fmul
1: XCALL __fmul
;; C = -C iff A0.7 = 1
- com C1
- neg C0
- sbci C1, -1
+ NEG2 C0
ret
ENDF __fmulsu_exit
#endif /* L_fmulsu */
@@ -2794,3 +2915,5 @@ ENDF __fmul
#undef B1
#undef C0
#undef C1
+
+#include "lib1funcs-fixed.S"
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index 43caa94ca2a..749613376b3 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -2,6 +2,7 @@ LIB1ASMSRC = avr/lib1funcs.S
LIB1ASMFUNCS = \
_mulqi3 \
_mulhi3 \
+ _mulqihi3 _umulqihi3 \
_mulpsi3 _mulsqipsi3 \
_mulhisi3 \
_umulhisi3 \
@@ -55,6 +56,24 @@ LIB1ASMFUNCS = \
_cmpdi2 _cmpdi2_s8 \
_fmul _fmuls _fmulsu
+# Fixed point routines in avr/lib1funcs-fixed.S
+LIB1ASMFUNCS += \
+ _fractqqsf _fractuqqsf \
+ _fracthqsf _fractuhqsf _fracthasf _fractuhasf \
+ _fractsasf _fractusasf _fractsqsf _fractusqsf \
+ \
+ _fractsfqq _fractsfuqq \
+ _fractsfhq _fractsfuhq _fractsfha _fractsfuha \
+ _fractsfsa _fractsfusa \
+ _mulqq3 \
+ _mulhq3 _muluhq3 \
+ _mulha3 _muluha3 _muluha3_round \
+ _mulsa3 _mulusa3 \
+ _divqq3 _udivuqq3 \
+ _divhq3 _udivuhq3 \
+ _divha3 _udivuha3 \
+ _divsa3 _udivusa3
+
LIB2FUNCS_EXCLUDE = \
_moddi3 _umoddi3 \
_clz
@@ -81,3 +100,49 @@ libgcc-objects += $(patsubst %,%$(objext),$(hiintfuncs16))
ifeq ($(enable_shared),yes)
libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16))
endif
+
+
+# Filter out supported conversions from fixed-bit.c
+
+conv_XY=$(conv)$(mode1)$(mode2)
+func_X=$(func)$(mode)
+
+# Conversions supported by the compiler
+
+convf_modes = QI UQI QQ UQQ \
+ HI UHI HQ UHQ HA UHA \
+ SI USI SQ USQ SA USA \
+ DI UDI DQ UDQ DA UDA \
+ TI UTI TQ UTQ TA UTA
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach conv,_fract _fractuns,\
+ $(foreach mode1,$(convf_modes),\
+ $(foreach mode2,$(convf_modes),$(conv_XY))))
+
+# Conversions supported by lib1funcs-fixed.S
+
+conv_to_sf_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA
+conv_from_sf_modes = QQ UQQ HQ UHQ HA UHA SA USA
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach conv,_fract, \
+ $(foreach mode1,$(conv_to_sf_modes), \
+ $(foreach mode2,SF,$(conv_XY))))
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach conv,_fract,\
+ $(foreach mode1,SF,\
+ $(foreach mode2,$(conv_from_sf_modes),$(conv_XY))))
+
+# Arithmetik supported by the compiler
+
+allfix_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA DA UDA DQ UDQ TQ UTQ TA UTA
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach func,_add _sub,\
+ $(foreach mode,$(allfix_modes),$(func_X)3))
+
+LIB2FUNCS_EXCLUDE += \
+ $(foreach func,_lshr _ashl _ashr _cmp,\
+ $(foreach mode,$(allfix_modes),$(func_X)))
diff --git a/libgcc/config/i386/libgcc-cygming.ver b/libgcc/config/i386/libgcc-cygming.ver
new file mode 100644
index 00000000000..8966cfb5322
--- /dev/null
+++ b/libgcc/config/i386/libgcc-cygming.ver
@@ -0,0 +1,22 @@
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 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
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+GCC_4.8 {
+ _GCC_specific_handler
+ __gcc_personality_seh0
+}
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index 228d6901abd..9528431f7e6 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -83,6 +83,9 @@
#endif
+# The amount of space we ask for when calling non-split-stack code.
+#define NON_SPLIT_STACK 0x100000
+
# 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
@@ -109,7 +112,7 @@ __morestack_non_split:
movl %esp,%eax # Current stack,
subl 8(%esp),%eax # less required stack frame size,
- subl $0x4000,%eax # less space for non-split code.
+ subl $NON_SPLIT_STACK,%eax # less space for non-split code.
cmpl %gs:0x30,%eax # See if we have enough space.
jb 2f # Get more space if we need it.
@@ -171,7 +174,8 @@ __morestack_non_split:
.cfi_adjust_cfa_offset -4 # Account for popped register.
- addl $0x5000+BACKOFF,4(%esp) # Increment space we request.
+ # Increment space we request.
+ addl $NON_SPLIT_STACK+0x1000+BACKOFF,4(%esp)
# Fall through into morestack.
@@ -186,7 +190,7 @@ __morestack_non_split:
movq %rsp,%rax # Current stack,
subq %r10,%rax # less required stack frame size,
- subq $0x4000,%rax # less space for non-split code.
+ subq $NON_SPLIT_STACK,%rax # less space for non-split code.
#ifdef __LP64__
cmpq %fs:0x70,%rax # See if we have enough space.
@@ -219,7 +223,8 @@ __morestack_non_split:
.cfi_adjust_cfa_offset -8 # Adjust for popped register.
- addq $0x5000+BACKOFF,%r10 # Increment space we request.
+ # Increment space we request.
+ addq $NON_SPLIT_STACK+0x1000+BACKOFF,%r10
# Fall through into morestack.
diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux
index 29b4c223983..4f47f7bfa59 100644
--- a/libgcc/config/i386/t-linux
+++ b/libgcc/config/i386/t-linux
@@ -2,3 +2,5 @@
# Need to support TImode for x86. Override the settings from
# t-slibgcc-elf-ver and t-linux
SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver
+
+HOST_LIBGCC2_CFLAGS += -mlong-double-80
diff --git a/libgcc/config/i386/t-seh-eh b/libgcc/config/i386/t-seh-eh
new file mode 100644
index 00000000000..066ca54b010
--- /dev/null
+++ b/libgcc/config/i386/t-seh-eh
@@ -0,0 +1,6 @@
+
+# We are using SEH EH.
+EH_MODEL = seh
+
+# Use SEH exception handling.
+LIB2ADDEH = $(srcdir)/unwind-seh.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/i386/t-slibgcc-cygming b/libgcc/config/i386/t-slibgcc-cygming
index 3bee8b98084..6236c78e466 100644
--- a/libgcc/config/i386/t-slibgcc-cygming
+++ b/libgcc/config/i386/t-slibgcc-cygming
@@ -55,4 +55,4 @@ SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
# We'd like to use SHLIB_SONAME here too, but shlib_base_name
# does not get substituted before mkmap-flat.awk is run.
SHLIB_MKMAP_OPTS = -v pe_dll=libgcc_s_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
-SHLIB_MAPFILES = libgcc-std.ver
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-cygming.ver
diff --git a/libgcc/config/m32c/lib2funcs.c b/libgcc/config/m32c/lib2funcs.c
index 274affc4ab0..76b237cdf26 100644
--- a/libgcc/config/m32c/lib2funcs.c
+++ b/libgcc/config/m32c/lib2funcs.c
@@ -1,5 +1,5 @@
/* libgcc routines for R8C/M16C/M32C
- Copyright (C) 2005, 2009
+ Copyright (C) 2005, 2009, 2012
Free Software Foundation, Inc.
Contributed by Red Hat.
@@ -132,3 +132,17 @@ __umoddi3 (uint32_type a, uint32_type b)
{
return udivmodsi4 (a, b, 1);
}
+
+/* Returns the number of leading redundant sign bits in X.
+ I.e. the number of bits following the most significant bit which are
+ identical to it. There are no special cases for 0 or other values. */
+
+int
+__clrsbhi2 (word_type x)
+{
+ if (x < 0)
+ x = ~x;
+ if (x == 0)
+ return 15;
+ return __builtin_clz (x) - 1;
+}
diff --git a/libgcc/config/m68k/linux-atomic.c b/libgcc/config/m68k/linux-atomic.c
index 6e81d6b5d5e..a2bba596d53 100644
--- a/libgcc/config/m68k/linux-atomic.c
+++ b/libgcc/config/m68k/linux-atomic.c
@@ -1,5 +1,5 @@
/* Linux-specific atomic operations for m68k Linux.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2012 Free Software Foundation, Inc.
Based on code contributed by CodeSourcery for ARM EABI Linux.
This file is part of GCC.
@@ -207,5 +207,5 @@ SUBWORD_BOOL_CAS (unsigned char, 1)
#define COMMA ,
WORD_SYNC_OP (test_and_set, , COMMA, oldval)
-SUBWORD_SYNC_OP (test_and_set, , COMMA, unsigned short, 1, oldval)
+SUBWORD_SYNC_OP (test_and_set, , COMMA, unsigned char, 1, oldval)
SUBWORD_SYNC_OP (test_and_set, , COMMA, unsigned short, 2, oldval)
diff --git a/libgcc/config/stormy16/clrsbhi2.c b/libgcc/config/stormy16/clrsbhi2.c
new file mode 100644
index 00000000000..3ce41aca061
--- /dev/null
+++ b/libgcc/config/stormy16/clrsbhi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_CLRSBHI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/lib2funcs.c b/libgcc/config/stormy16/lib2funcs.c
index a10a9b28119..a996fd15e24 100644
--- a/libgcc/config/stormy16/lib2funcs.c
+++ b/libgcc/config/stormy16/lib2funcs.c
@@ -311,6 +311,22 @@ __ffshi2 (UHWtype u)
}
#endif
+#ifdef XSTORMY16_CLRSBHI2
+/* Returns the number of leading redundant sign bits in X.
+ I.e. the number of bits following the most significant bit which are
+ identical to it. There are no special cases for 0 or other values. */
+
+int
+__clrsbhi2 (HWtype x)
+{
+ if (x < 0)
+ x = ~x;
+ if (x == 0)
+ return 15;
+ return __builtin_clz (x) - 1;
+}
+#endif
+
#ifdef XSTORMY16_UCMPSI2
/* Performs an unsigned comparison of two 32-bit values: A and B.
If A is less than B, then 0 is returned. If A is greater than B,
diff --git a/libgcc/config/stormy16/t-stormy16 b/libgcc/config/stormy16/t-stormy16
index d62d167d93d..48ded89d3bf 100644
--- a/libgcc/config/stormy16/t-stormy16
+++ b/libgcc/config/stormy16/t-stormy16
@@ -33,6 +33,7 @@ LIB2ADD = \
$(srcdir)/config/stormy16/clzhi2.c \
$(srcdir)/config/stormy16/ctzhi2.c \
$(srcdir)/config/stormy16/ffshi2.c \
+ $(srcdir)/config/stormy16/clrsbhi2.c \
$(srcdir)/config/stormy16/cmpsi2.c \
$(srcdir)/config/stormy16/ucmpsi2.c
diff --git a/libgcc/config/t-darwin b/libgcc/config/t-darwin
index 3365f010225..a69169fa610 100644
--- a/libgcc/config/t-darwin
+++ b/libgcc/config/t-darwin
@@ -1,7 +1,5 @@
-# Pass -fno-tree-dominator-opts to work around bug 26840.
crt3.o: $(srcdir)/config/darwin-crt3.c
- $(crt_compile) \
- -fno-tree-dominator-opts $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $<
+ $(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $<
crttms.o: $(srcdir)/config/darwin-crt-tm.c
$(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -DSTART -c $<
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
index 5d820fa45ac..973956ac322 100644
--- a/libgcc/crtstuff.c
+++ b/libgcc/crtstuff.c
@@ -1,7 +1,7 @@
/* Specialized bits of code needed to support construction and
destruction of file-scope objects in C++ code.
Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
+ 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
@@ -113,6 +113,20 @@ call_ ## FUNC (void) \
# define USE_PT_GNU_EH_FRAME
# endif
#endif
+
+#if defined(OBJECT_FORMAT_ELF) \
+ && !defined(OBJECT_FORMAT_FLAT) \
+ && defined(HAVE_LD_EH_FRAME_HDR) \
+ && !defined(CRTSTUFFT_O) \
+ && defined(inhibit_libc) \
+ && (defined(__GLIBC__) || defined(__gnu_linux__) || defined(__GNU__))
+/* On systems using glibc, an inhibit_libc build of libgcc is only
+ part of a bootstrap process. Build the same crt*.o as would be
+ built with headers present, so that it is not necessary to build
+ glibc more than once for the bootstrap to converge. */
+# define USE_PT_GNU_EH_FRAME
+#endif
+
#if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME)
# define USE_EH_FRAME_REGISTRY
#endif
diff --git a/libgcc/fixed-obj.mk b/libgcc/fixed-obj.mk
index ac699d2f9e3..4db7a5792c7 100644
--- a/libgcc/fixed-obj.mk
+++ b/libgcc/fixed-obj.mk
@@ -22,6 +22,7 @@ endif
#$(info $o$(objext): -DL$($o-label) $($o-opt))
+ifneq ($o,$(filter $o,$(LIB2FUNCS_EXCLUDE)))
$o$(objext): %$(objext): $(srcdir)/fixed-bit.c
$(gcc_compile) -DL$($*-label) $($*-opt) -c $(srcdir)/fixed-bit.c $(vis_hide)
@@ -29,3 +30,4 @@ ifeq ($(enable_shared),yes)
$(o)_s$(objext): %_s$(objext): $(srcdir)/fixed-bit.c
$(gcc_s_compile) -DL$($*-label) $($*-opt) -c $(srcdir)/fixed-bit.c
endif
+endif
diff --git a/libgcc/libgcov.c b/libgcc/libgcov.c
index 8ed897117f7..a22e8f4c3ee 100644
--- a/libgcc/libgcov.c
+++ b/libgcc/libgcov.c
@@ -1040,8 +1040,7 @@ __gcov_average_profiler (gcov_type *counters, gcov_type value)
#endif
#ifdef L_gcov_ior_profiler
-/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
- to saturate up. */
+/* Bitwise-OR VALUE into COUNTER. */
void
__gcov_ior_profiler (gcov_type *counters, gcov_type value)
diff --git a/libgcc/longlong.h b/libgcc/longlong.h
index 04277183963..30e638ca131 100644
--- a/libgcc/longlong.h
+++ b/libgcc/longlong.h
@@ -850,8 +850,6 @@ UDItype __umulsidi3 (USItype, USItype);
FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good
enough, since that hits ARM and m68k too. */
#if (defined (_ARCH_PPC) /* AIX */ \
- || defined (_ARCH_PWR) /* AIX */ \
- || defined (_ARCH_COM) /* AIX */ \
|| defined (__powerpc__) /* gcc */ \
|| defined (__POWERPC__) /* BEOS */ \
|| defined (__ppc__) /* Darwin */ \
@@ -862,37 +860,37 @@ UDItype __umulsidi3 (USItype, USItype);
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
do { \
if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
else \
- __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \
: "=r" (sh), "=&r" (sl) \
: "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
} while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
do { \
if (__builtin_constant_p (ah) && (ah) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
else if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
else \
- __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \
: "=r" (sh), "=&r" (sl) \
: "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
} while (0)
#define count_leading_zeros(count, x) \
- __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
+ __asm__ ("cntlzw %0,%1" : "=r" (count) : "r" (x))
#define COUNT_LEADING_ZEROS_0 32
#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
|| defined (__ppc__) \
@@ -914,14 +912,6 @@ UDItype __umulsidi3 (USItype, USItype);
} while (0)
#define SMUL_TIME 14
#define UDIV_TIME 120
-#elif defined (_ARCH_PWR)
-#define UMUL_TIME 8
-#define smul_ppmm(xh, xl, m0, m1) \
- __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1))
-#define SMUL_TIME 4
-#define sdiv_qrnnd(q, r, nh, nl, d) \
- __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d))
-#define UDIV_TIME 100
#endif
#endif /* 32-bit POWER architecture variants. */
@@ -931,32 +921,32 @@ UDItype __umulsidi3 (USItype, USItype);
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
do { \
if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
- __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
else \
- __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \
: "=r" (sh), "=&r" (sl) \
: "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
} while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
do { \
if (__builtin_constant_p (ah) && (ah) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
else if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \
: "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
else \
- __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \
: "=r" (sh), "=&r" (sl) \
: "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
} while (0)
diff --git a/libgcc/static-object.mk b/libgcc/static-object.mk
index 930f009cd42..4f536369f0d 100644
--- a/libgcc/static-object.mk
+++ b/libgcc/static-object.mk
@@ -24,7 +24,13 @@ $(error Unsupported file type: $o)
endif
endif
-$(base)$(objext): $o
- $(gcc_compile) -c -xassembler-with-cpp $<
+$(base)$(objext): $o $(base).vis
+ $(gcc_compile) -c -xassembler-with-cpp -include $*.vis $<
+
+$(base).vis: $(base)_s$(objext)
+ $(gen-hide-list)
+
+$(base)_s$(objext): $o
+ $(gcc_s_compile) -c -xassembler-with-cpp $<
endif
diff --git a/libgcc/unwind-c.c b/libgcc/unwind-c.c
index bd4941db3e2..eb50ad82a17 100644
--- a/libgcc/unwind-c.c
+++ b/libgcc/unwind-c.c
@@ -93,6 +93,8 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
#ifdef __USING_SJLJ_EXCEPTIONS__
#define PERSONALITY_FUNCTION __gcc_personality_sj0
#define __builtin_eh_return_data_regno(x) x
+#elif defined(__SEH__)
+#define PERSONALITY_FUNCTION __gcc_personality_imp
#else
#define PERSONALITY_FUNCTION __gcc_personality_v0
#endif
@@ -107,6 +109,9 @@ PERSONALITY_FUNCTION (_Unwind_State state,
struct _Unwind_Exception * ue_header,
struct _Unwind_Context * context)
#else
+#ifdef __SEH__
+static
+#endif
_Unwind_Reason_Code
PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
@@ -227,3 +232,13 @@ PERSONALITY_FUNCTION (int version,
_Unwind_SetIP (context, landing_pad);
return _URC_INSTALL_CONTEXT;
}
+
+#ifdef __SEH__
+EXCEPTION_DISPOSITION
+__gcc_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
+ PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
+{
+ return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
+ ms_disp, __gcc_personality_imp);
+}
+#endif /* SEH */
diff --git a/libgcc/unwind-generic.h b/libgcc/unwind-generic.h
index 4ff9017b88b..c9c993b2785 100644
--- a/libgcc/unwind-generic.h
+++ b/libgcc/unwind-generic.h
@@ -28,6 +28,11 @@
#ifndef _UNWIND_H
#define _UNWIND_H
+#ifdef __SEH__
+/* Only for _GCC_specific_handler. */
+#include <windows.h>
+#endif
+
#ifndef HIDE_EXPORTS
#pragma GCC visibility push(default)
#endif
@@ -86,8 +91,13 @@ struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
+
+#if !defined (__USING_SJLJ_EXCEPTIONS__) && defined (__SEH__)
+ _Unwind_Word private_[6];
+#else
_Unwind_Word private_1;
_Unwind_Word private_2;
+#endif
/* @@@ The IA-64 ABI says that this structure must be double-word aligned.
Taking that literally does not make much sense generically. Instead we
@@ -265,6 +275,13 @@ extern void * _Unwind_FindEnclosingFunction (void *pc);
# error "What type shall we use for _sleb128_t?"
#endif
+#ifdef __SEH__
+/* Handles the mapping from SEH to GCC interfaces. */
+EXCEPTION_DISPOSITION _GCC_specific_handler (PEXCEPTION_RECORD, void *,
+ PCONTEXT, PDISPATCHER_CONTEXT,
+ _Unwind_Personality_Fn);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/libgcc/unwind-seh.c b/libgcc/unwind-seh.c
new file mode 100644
index 00000000000..24e4280fde7
--- /dev/null
+++ b/libgcc/unwind-seh.c
@@ -0,0 +1,483 @@
+/* Structured Exception Handling (SEH) runtime interface routines.
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 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"
+#include "unwind.h"
+
+#ifdef __SEH__
+
+/* At the moment everything is written for x64, but in theory this could
+ also be used for i386, arm, mips and other extant embedded Windows. */
+#ifndef __x86_64__
+#error "Unsupported architecture."
+#endif
+
+/* Define GCC's exception codes. See
+ http://msdn.microsoft.com/en-us/library/het71c37(v=VS.80).aspx
+ In particular, MS defines bits:
+ [31:30] = 3 (error), 2 (warning), 1 (info), 0 (success)
+ [29] = 1 (user-defined)
+ [28] = 0 (reserved)
+ We define bits:
+ [24:27] = type
+ [0:23] = magic
+ We set "magic" to "GCC", which is similar to MVC++ which uses "msc"
+ as the low 3 bytes of its user-defined codes for C++ exceptions.
+
+ We define the ExceptionInformation entries as follows:
+ [0] = _Unwind_Exception pointer
+ [1] = target frame
+ [2] = target ip
+ [3] = target rdx
+*/
+
+#define STATUS_USER_DEFINED (1U << 29)
+
+#define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C')
+#define GCC_EXCEPTION(TYPE) \
+ (STATUS_USER_DEFINED | ((TYPE) << 24) | GCC_MAGIC)
+
+#define STATUS_GCC_THROW GCC_EXCEPTION (0)
+#define STATUS_GCC_UNWIND GCC_EXCEPTION (1)
+#define STATUS_GCC_FORCED GCC_EXCEPTION (2)
+
+
+struct _Unwind_Context
+{
+ _Unwind_Word cfa;
+ _Unwind_Word ra;
+ _Unwind_Word reg[2];
+ PDISPATCHER_CONTEXT disp;
+};
+
+/* Get the value of register INDEX as saved in CONTEXT. */
+
+_Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *c, int index)
+{
+ if (index < 0 || index > 2)
+ abort ();
+ return c->reg[index];
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
+
+void
+_Unwind_SetGR (struct _Unwind_Context *c, int index, _Unwind_Word val)
+{
+ if (index < 0 || index > 2)
+ abort ();
+ c->reg[index] = val;
+}
+
+/* Get the value of the CFA as saved in CONTEXT. */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *c)
+{
+ return c->cfa;
+}
+
+/* Retrieve the return address for CONTEXT. */
+
+_Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *c)
+{
+ return c->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+ or after first not yet fully executed instruction. */
+
+_Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *c, int *ip_before_insn)
+{
+ /* ??? Is there a concept of a signal context properly? There's
+ obviously an UNWP_PUSH_MACHFRAME opcode, but the runtime might
+ have arranged for that not to matter, really. */
+ *ip_before_insn = 0;
+ return c->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL. */
+
+void
+_Unwind_SetIP (struct _Unwind_Context *c, _Unwind_Ptr val)
+{
+ c->ra = val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *c)
+{
+ return c->disp->HandlerData;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *c)
+{
+ return c->disp->FunctionEntry->BeginAddress + c->disp->ImageBase;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+ PRUNTIME_FUNCTION entry;
+ ULONG64 ImageBase;
+
+ entry = RtlLookupFunctionEntry ((ULONG64)pc, &ImageBase, NULL);
+
+ return (entry ? (void *)(entry->BeginAddress + ImageBase) : NULL);
+}
+
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *c ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *c)
+{
+ return c->disp->ImageBase;
+}
+
+
+/* The two-phase unwind process that GCC uses is ordered differently
+ from the two-phase unwind process that SEH uses. The mechansism
+ that GCC uses is to have the filter return _URC_HANDER_FOUND; the
+ mechanism that SEH uses is for the filter function call back into
+ the unwinder.
+
+ An Ideal port to SEH would have GCC emit handler functions that
+ can be called, given a pointer to the "EstablisherFrame" (i.e.
+ the frame pointer base of the user-level function) can manipulate
+ the user-level variables within the user-level function's stack
+ frame. Once done manipulating the variables, it would return
+ a ExceptionContinueSearch, and the unwind process would continue.
+
+ GCC has always done things a bit differently. We continue to
+ transfer control back into the user-level function which, once
+ done manipulating the user-level variables, re-throws the exception. */
+
+/* The "real" language-specific personality handler forwards to here
+ where we handle the MS SEH state and transforms it into the GCC
+ unwind state as per GCC's <unwind.h>, at which point we defer to
+ the regular language-specfic exception handler, which is passed in. */
+
+EXCEPTION_DISPOSITION
+_GCC_specific_handler (PEXCEPTION_RECORD ms_exc, void *this_frame,
+ PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp,
+ _Unwind_Personality_Fn gcc_per)
+{
+ DWORD ms_flags = ms_exc->ExceptionFlags;
+ DWORD ms_code = ms_exc->ExceptionCode;
+
+ struct _Unwind_Exception *gcc_exc
+ = (struct _Unwind_Exception *) ms_exc->ExceptionInformation[0];
+ struct _Unwind_Context gcc_context;
+ _Unwind_Action gcc_action;
+ _Unwind_Reason_Code gcc_reason;
+
+ if (ms_flags & EXCEPTION_TARGET_UNWIND)
+ {
+ /* This frame is known to be the target frame. We've already
+ "installed" the target_ip and RAX value via the arguments
+ to RtlUnwindEx. All that's left is to set the RDX value
+ and "continue" to have the context installed. */
+ ms_disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];
+ return ExceptionContinueSearch;
+ }
+
+ if (ms_code == STATUS_GCC_UNWIND)
+ {
+ /* This is a colliding exception that we threw so that we could
+ cancel the already in-flight exception and stop in a frame
+ that wanted to perform some unwind action. The only relevant
+ test is that we're the target frame. */
+ if (ms_exc->ExceptionInformation[1] == (_Unwind_Ptr) this_frame)
+ {
+ RtlUnwindEx (this_frame, ms_exc->ExceptionInformation[2],
+ ms_exc, gcc_exc, ms_orig_context,
+ ms_disp->HistoryTable);
+ abort ();
+ }
+ return ExceptionContinueSearch;
+ }
+
+ gcc_context.cfa = ms_disp->ContextRecord->Rsp;
+ gcc_context.ra = ms_disp->ControlPc;
+ gcc_context.reg[0] = 0xdeadbeef; /* These are write-only. */
+ gcc_context.reg[1] = 0xdeadbeef;
+ gcc_context.disp = ms_disp;
+
+ if (ms_code == STATUS_GCC_FORCED)
+ {
+ _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) gcc_exc->private_[0];
+ void *stop_argument = (void *) gcc_exc->private_[4];
+
+ gcc_action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
+
+ stop (1, gcc_action, gcc_exc->exception_class, gcc_exc,
+ &gcc_context, stop_argument);
+
+ goto phase2;
+ }
+
+ /* ??? TODO: handling non-gcc user-defined exceptions as foreign. */
+ if (ms_code != STATUS_GCC_THROW)
+ return ExceptionContinueSearch;
+
+ if (ms_flags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
+ {
+ /* This is Phase 2. */
+ /* We know this isn't the target frame because we've already tested
+ EXCEPTION_TARGET_UNWIND. The remaining possibility is that the
+ gcc personality has unwind code to run. */
+
+ gcc_action = _UA_CLEANUP_PHASE;
+ phase2:
+ gcc_reason = gcc_per (1, gcc_action, gcc_exc->exception_class,
+ gcc_exc, &gcc_context);
+
+ if (gcc_reason == _URC_CONTINUE_UNWIND)
+ return ExceptionContinueSearch;
+
+ if (gcc_reason == _URC_INSTALL_CONTEXT)
+ {
+ /* Scratch space for the bits for the unwind catch. */
+ ms_exc->ExceptionInformation[1] = (_Unwind_Ptr) this_frame;
+ ms_exc->ExceptionInformation[2] = gcc_context.ra;
+ ms_exc->ExceptionInformation[3] = gcc_context.reg[1];
+
+ /* Cancel the current exception by raising another. */
+ RaiseException (STATUS_GCC_UNWIND, EXCEPTION_NONCONTINUABLE,
+ 4, ms_exc->ExceptionInformation);
+
+ /* Is RaiseException declared noreturn? */
+ }
+
+ /* In _Unwind_RaiseException_Phase2 we return _URC_FATAL_PHASE2_ERROR. */
+ }
+ else
+ {
+ /* This is Phase 1. */
+ gcc_reason = gcc_per (1, _UA_SEARCH_PHASE, gcc_exc->exception_class,
+ gcc_exc, &gcc_context);
+
+ if (gcc_reason == _URC_CONTINUE_UNWIND)
+ return ExceptionContinueSearch;
+
+ if (gcc_reason == _URC_HANDLER_FOUND)
+ {
+ /* We really need some of the information that GCC's personality
+ routines compute during phase 2 right now, like the target IP.
+ Go ahead and ask for it now, and cache it. */
+ gcc_reason = gcc_per (1, _UA_CLEANUP_PHASE | _UA_HANDLER_FRAME,
+ gcc_exc->exception_class, gcc_exc,
+ &gcc_context);
+ if (gcc_reason != _URC_INSTALL_CONTEXT)
+ abort ();
+
+ gcc_exc->private_[1] = (_Unwind_Ptr) this_frame;
+ gcc_exc->private_[2] = gcc_context.ra;
+ gcc_exc->private_[3] = gcc_context.reg[1];
+
+ ms_exc->NumberParameters = 4;
+ ms_exc->ExceptionInformation[1] = (_Unwind_Ptr) this_frame;
+ ms_exc->ExceptionInformation[2] = gcc_context.ra;
+ ms_exc->ExceptionInformation[3] = gcc_context.reg[1];
+
+ /* Begin phase 2. Perform the unwinding. */
+ RtlUnwindEx (this_frame, gcc_context.ra, ms_exc, gcc_exc,
+ ms_orig_context, ms_disp->HistoryTable);
+ }
+
+ /* In _Unwind_RaiseException we return _URC_FATAL_PHASE1_ERROR. */
+ }
+ abort ();
+}
+
+/* Raise an exception, passing along the given exception object. */
+
+_Unwind_Reason_Code
+_Unwind_RaiseException (struct _Unwind_Exception *exc)
+{
+ memset (exc->private_, 0, sizeof (exc->private_));
+
+ /* The ExceptionInformation array will have only 1 element, EXC. */
+ RaiseException (STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exc);
+
+ /* The exception handler installed in crt0 will continue any GCC
+ exception that reaches there (and isn't marked non-continuable).
+ Returning allows the C++ runtime to call std::terminate. */
+ return _URC_END_OF_STACK;
+}
+
+/* Resume propagation of an existing exception. This is used after
+ e.g. executing cleanup code, and not to implement rethrowing. */
+
+void
+_Unwind_Resume (struct _Unwind_Exception *gcc_exc)
+{
+ UNWIND_HISTORY_TABLE ms_history;
+ EXCEPTION_RECORD ms_exc;
+ CONTEXT ms_context;
+
+ memset (&ms_exc, 0, sizeof(ms_exc));
+ memset (&ms_history, 0, sizeof(ms_history));
+
+ /* ??? Not 100% perfect, since we aren't passing on the *original*
+ exception context, but should be good enough. */
+ ms_exc.ExceptionCode = STATUS_GCC_THROW;
+ ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ ms_exc.NumberParameters = 4;
+ ms_exc.ExceptionInformation[0] = (ULONG_PTR) gcc_exc;
+ ms_exc.ExceptionInformation[1] = gcc_exc->private_[1];
+ ms_exc.ExceptionInformation[2] = gcc_exc->private_[2];
+ ms_exc.ExceptionInformation[3] = gcc_exc->private_[3];
+
+ ms_context.ContextFlags = CONTEXT_ALL;
+ RtlCaptureContext (&ms_context);
+
+ RtlUnwindEx ((void *) gcc_exc->private_[1], gcc_exc->private_[2],
+ &ms_exc, gcc_exc, &ms_context, &ms_history);
+
+ /* Is RtlUnwindEx declared noreturn? */
+ abort ();
+}
+
+static _Unwind_Reason_Code
+_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc)
+{
+ _Unwind_Stop_Fn stop;
+ void * stop_argument;
+
+ RaiseException (STATUS_GCC_FORCED, 0, 1, (ULONG_PTR *)&exc);
+
+ /* If we get here, we got to top-of-stack. */
+ /* ??? We no longer have a context pointer to pass in. */
+
+ stop = (_Unwind_Stop_Fn) exc->private_[0];
+ stop_argument = (void *) exc->private_[4];
+ stop (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK,
+ exc->exception_class, exc, NULL, stop_argument);
+
+ return _UA_END_OF_STACK;
+}
+
+_Unwind_Reason_Code
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
+{
+ if (exc->private_[0] == 0)
+ _Unwind_RaiseException (exc);
+ else
+ _Unwind_ForcedUnwind_Phase2 (exc);
+ abort ();
+}
+
+/* Raise an exception for forced unwinding. */
+
+_Unwind_Reason_Code
+_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
+ _Unwind_Stop_Fn stop, void * stop_argument)
+{
+ /* ??? This is a hack that only works with _GCC_specific_handler.
+ There's no way to invoke STOP within frames that use a different
+ exception handler. This is essentially just good enough to run
+ the code within the gcc testsuite. */
+
+ memset (exc->private_, 0, sizeof (exc->private_));
+ exc->private_[0] = (_Unwind_Ptr) stop;
+ exc->private_[4] = (_Unwind_Ptr) stop_argument;
+
+ return _Unwind_ForcedUnwind_Phase2 (exc);
+}
+
+/* A convenience function that calls the exception_cleanup field. */
+
+void
+_Unwind_DeleteException (struct _Unwind_Exception *exc)
+{
+ if (exc->exception_cleanup)
+ (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+}
+
+/* Perform stack backtrace through unwind data. */
+
+_Unwind_Reason_Code
+_Unwind_Backtrace(_Unwind_Trace_Fn trace ATTRIBUTE_UNUSED,
+ void *trace_argument ATTRIBUTE_UNUSED)
+{
+#if 0
+ UNWIND_HISTORY_TABLE ms_history;
+ CONTEXT ms_context;
+ struct _Unwind_Context gcc_context;
+
+ memset (&ms_history, 0, sizeof(ms_history));
+ memset (&gcc_context, 0, sizeof(gcc_context));
+
+ ms_context.ContextFlags = CONTEXT_ALL;
+ RtlCaptureContext (&ms_context);
+
+ gcc_context.disp.ContextRecord = &ms_context;
+ gcc_context.disp.HistoryTable = &ms_history;
+
+ while (1)
+ {
+ gcc_context.disp.ControlPc = ms_context.Rip;
+ gcc_context.disp.FunctionEntry
+ = RtlLookupFunctionEntry (ms_context.Rip, &gcc_context.disp.ImageBase,
+ &ms_history);
+
+ if (gcc_context.disp.FunctionEntry)
+ {
+ gcc_context.disp.LanguageHandler
+ = RtlVirtualUnwind (0, gcc_context.disp.ImageBase, ms_context.Rip,
+ gcc_context.disp.FunctionEntry, &ms_context,
+ &gcc_context.disp.HandlerData,
+ &gcc_context.disp.EstablisherFrame, NULL);
+ }
+ else
+ {
+ ms_context.Rip = *(ULONG_PTR *)ms_context.Rsp;
+ ms_context.Rsp += 8;
+ }
+
+ /* Call trace function. */
+ if (trace (&gcc_context, trace_argument) != _URC_NO_REASON)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* ??? Check for invalid stack pointer. */
+ if (ms_context.Rip == 0)
+ return _URC_END_OF_STACK;
+ }
+#else
+ return _URC_END_OF_STACK;
+#endif
+}
+#endif /* __SEH__ */