]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/config/avr/libgcc.S
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / config / avr / libgcc.S
index d324a2166a61e8918cc18b857ebda7b0eb249abf..b6262b338dde77f892801ee4cd12fd3d13779cf1 100644 (file)
@@ -1,36 +1,33 @@
 /*  -*- Mode: Asm -*-  */
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Denis Chertykov <denisc@overta.ru>
 
 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 2, or (at your option) any
+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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+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/>.  */
 
 #define __zero_reg__ r1
 #define __tmp_reg__ r0
 #define __SREG__ 0x3f
 #define __SP_H__ 0x3e
 #define __SP_L__ 0x3d
+#define __RAMPZ__ 0x3B
 
 /* Most of the functions here are called directly from avr.md
    patterns, instead of using the standard libcall mechanisms.
@@ -40,7 +37,7 @@ Boston, MA 02111-1307, USA.  */
        .section .text.libgcc, "ax", @progbits
 
        .macro  mov_l  r_dest, r_src
-#if defined (__AVR_ENHANCED__)
+#if defined (__AVR_HAVE_MOVW__)
        movw    \r_dest, \r_src
 #else
        mov     \r_dest, \r_src
@@ -48,7 +45,7 @@ Boston, MA 02111-1307, USA.  */
        .endm
 
        .macro  mov_h  r_dest, r_src
-#if defined (__AVR_ENHANCED__)
+#if defined (__AVR_HAVE_MOVW__)
        ; empty
 #else
        mov     \r_dest, \r_src
@@ -56,7 +53,7 @@ Boston, MA 02111-1307, USA.  */
        .endm
 
 /* Note: mulqi3, mulhi3 are open-coded on the enhanced core.  */
-#if !defined (__AVR_ENHANCED__)
+#if !defined (__AVR_HAVE_MUL__)
 /*******************************************************
                Multiplication  8 x 8
 *******************************************************/
@@ -159,7 +156,7 @@ __mulhi3_exit:
 
 .endfunc
 #endif /* defined (L_mulhi3) */
-#endif /* !defined (__AVR_ENHANCED__) */
+#endif /* !defined (__AVR_HAVE_MUL__) */
 
 #if defined (L_mulhisi3)
        .global __mulhisi3
@@ -217,7 +214,7 @@ __umulhisi3:
        .global __mulsi3
        .func   __mulsi3
 __mulsi3:
-#if defined (__AVR_ENHANCED__)
+#if defined (__AVR_HAVE_MUL__)
        mul     r_arg1L, r_arg2L
        movw    r_resL, r0
        mul     r_arg1H, r_arg2H
@@ -276,12 +273,12 @@ __mulsi3_skip1:
        cpc     r_arg1H,r_arg1L
        brne    __mulsi3_loop           ; exit if multiplier = 0
 __mulsi3_exit:
-       mov     r_arg1HH,r_resHH        ; result to return register
-       mov     r_arg1HL,r_resHL
-       mov     r_arg1H,r_resH
-       mov     r_arg1L,r_resL
+       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
-#endif /* !defined (__AVR_ENHANCED__) */
+#endif /* defined (__AVR_HAVE_MUL__) */
 #undef r_arg1L 
 #undef r_arg1H 
 #undef r_arg1HL
@@ -593,7 +590,12 @@ __prologue_saves__:
        out     __SP_H__,r29
        out     __SREG__,__tmp_reg__
        out     __SP_L__,r28
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+       eijmp
+#else
        ijmp
+#endif
+
 .endfunc
 #endif /* defined (L_prologue) */
 
@@ -637,11 +639,20 @@ __epilogue_restores__:
 #endif /* defined (L_epilogue) */
 
 #ifdef L_exit
-       .weak   _exit
+       .section .fini9,"ax",@progbits
+       .global _exit
        .func   _exit
 _exit:
-       rjmp    _exit
-.endfunc
+       .weak   exit
+exit:
+
+       /* Code from .fini8 ... .fini1 sections inserted by ld script.  */
+
+       .section .fini0,"ax",@progbits
+       cli
+__stop_program:
+       rjmp    __stop_program
+       .endfunc
 #endif /* defined (L_exit) */
 
 #ifdef L_cleanup
@@ -658,19 +669,231 @@ _cleanup:
 __tablejump2__:
        lsl     r30
        rol     r31
-#if defined (__AVR_ENHANCED__)
+       .global __tablejump__
+__tablejump__:
+#if defined (__AVR_HAVE_LPMX__)
        lpm     __tmp_reg__, Z+
        lpm     r31, Z
        mov     r30, __tmp_reg__
+
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+       eijmp
+#else
        ijmp
+#endif
+
 #else
        lpm
+       adiw    r30, 1
        push    r0
-       inc     r30     ; table is word aligned, no carry to high byte
        lpm
        push    r0
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+        push    __zero_reg__
+#endif
        ret
 #endif
-.endfunc
+       .endfunc
 #endif /* defined (L_tablejump) */
 
+#ifdef L_copy_data
+       .section .init4,"ax",@progbits
+       .global __do_copy_data
+__do_copy_data:
+#if defined(__AVR_HAVE_ELPMX__)
+       ldi     r17, hi8(__data_end)
+       ldi     r26, lo8(__data_start)
+       ldi     r27, hi8(__data_start)
+       ldi     r30, lo8(__data_load_start)
+       ldi     r31, hi8(__data_load_start)
+       ldi     r16, hh8(__data_load_start)
+       out     __RAMPZ__, r16
+       rjmp    .L__do_copy_data_start
+.L__do_copy_data_loop:
+       elpm    r0, Z+
+       st      X+, r0
+.L__do_copy_data_start:
+       cpi     r26, lo8(__data_end)
+       cpc     r27, r17
+       brne    .L__do_copy_data_loop
+#elif  !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__)
+       ldi     r17, hi8(__data_end)
+       ldi     r26, lo8(__data_start)
+       ldi     r27, hi8(__data_start)
+       ldi     r30, lo8(__data_load_start)
+       ldi     r31, hi8(__data_load_start)
+       ldi     r16, hh8(__data_load_start - 0x10000)
+.L__do_copy_data_carry:
+       inc     r16
+       out     __RAMPZ__, r16
+       rjmp    .L__do_copy_data_start
+.L__do_copy_data_loop:
+       elpm
+       st      X+, r0
+       adiw    r30, 1
+       brcs    .L__do_copy_data_carry
+.L__do_copy_data_start:
+       cpi     r26, lo8(__data_end)
+       cpc     r27, r17
+       brne    .L__do_copy_data_loop
+#elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__)
+       ldi     r17, hi8(__data_end)
+       ldi     r26, lo8(__data_start)
+       ldi     r27, hi8(__data_start)
+       ldi     r30, lo8(__data_load_start)
+       ldi     r31, hi8(__data_load_start)
+       rjmp    .L__do_copy_data_start
+.L__do_copy_data_loop:
+#if defined (__AVR_HAVE_LPMX__)
+       lpm     r0, Z+
+#else
+       lpm
+       adiw    r30, 1
+#endif
+       st      X+, r0
+.L__do_copy_data_start:
+       cpi     r26, lo8(__data_end)
+       cpc     r27, r17
+       brne    .L__do_copy_data_loop
+#endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */
+#endif /* L_copy_data */
+
+/* __do_clear_bss is only necessary if there is anything in .bss section.  */
+
+#ifdef L_clear_bss
+       .section .init4,"ax",@progbits
+       .global __do_clear_bss
+__do_clear_bss:
+       ldi     r17, hi8(__bss_end)
+       ldi     r26, lo8(__bss_start)
+       ldi     r27, hi8(__bss_start)
+       rjmp    .do_clear_bss_start
+.do_clear_bss_loop:
+       st      X+, __zero_reg__
+.do_clear_bss_start:
+       cpi     r26, lo8(__bss_end)
+       cpc     r27, r17
+       brne    .do_clear_bss_loop
+#endif /* L_clear_bss */
+
+/* __do_global_ctors and __do_global_dtors are only necessary
+   if there are any constructors/destructors.  */
+
+#if defined (__AVR_HAVE_JMP_CALL__)
+#define XCALL call
+#else
+#define XCALL rcall
+#endif
+
+#ifdef L_ctors
+       .section .init6,"ax",@progbits
+       .global __do_global_ctors
+#if defined(__AVR_HAVE_RAMPZ__)
+__do_global_ctors:
+       ldi     r17, hi8(__ctors_start)
+       ldi     r16, hh8(__ctors_start)
+       ldi     r28, lo8(__ctors_end)
+       ldi     r29, hi8(__ctors_end)
+       ldi     r20, hh8(__ctors_end)
+       rjmp    .L__do_global_ctors_start
+.L__do_global_ctors_loop:
+       sbiw    r28, 2
+       sbc     r20, __zero_reg__
+       mov_h   r31, r29
+       mov_l   r30, r28
+       out     __RAMPZ__, r20
+       XCALL   __tablejump_elpm__
+.L__do_global_ctors_start:
+       cpi     r28, lo8(__ctors_start)
+       cpc     r29, r17
+       cpc     r20, r16
+       brne    .L__do_global_ctors_loop
+#else
+__do_global_ctors:
+       ldi     r17, hi8(__ctors_start)
+       ldi     r28, lo8(__ctors_end)
+       ldi     r29, hi8(__ctors_end)
+       rjmp    .L__do_global_ctors_start
+.L__do_global_ctors_loop:
+       sbiw    r28, 2
+       mov_h   r31, r29
+       mov_l   r30, r28
+       XCALL   __tablejump__
+.L__do_global_ctors_start:
+       cpi     r28, lo8(__ctors_start)
+       cpc     r29, r17
+       brne    .L__do_global_ctors_loop
+#endif /* defined(__AVR_HAVE_RAMPZ__) */
+#endif /* L_ctors */
+
+#ifdef L_dtors
+       .section .fini6,"ax",@progbits
+       .global __do_global_dtors
+#if defined(__AVR_HAVE_RAMPZ__)
+__do_global_dtors:
+       ldi     r17, hi8(__dtors_end)
+       ldi     r16, hh8(__dtors_end)
+       ldi     r28, lo8(__dtors_start)
+       ldi     r29, hi8(__dtors_start)
+       ldi     r20, hh8(__dtors_start)
+       rjmp    .L__do_global_dtors_start
+.L__do_global_dtors_loop:
+       sbiw    r28, 2
+       sbc     r20, __zero_reg__
+       mov_h   r31, r29
+       mov_l   r30, r28
+       out     __RAMPZ__, r20
+       XCALL   __tablejump_elpm__
+.L__do_global_dtors_start:
+       cpi     r28, lo8(__dtors_end)
+       cpc     r29, r17
+       cpc     r20, r16
+       brne    .L__do_global_dtors_loop
+#else
+__do_global_dtors:
+       ldi     r17, hi8(__dtors_end)
+       ldi     r28, lo8(__dtors_start)
+       ldi     r29, hi8(__dtors_start)
+       rjmp    .L__do_global_dtors_start
+.L__do_global_dtors_loop:
+       mov_h   r31, r29
+       mov_l   r30, r28
+       XCALL   __tablejump__
+       adiw    r28, 2
+.L__do_global_dtors_start:
+       cpi     r28, lo8(__dtors_end)
+       cpc     r29, r17
+       brne    .L__do_global_dtors_loop
+#endif /* defined(__AVR_HAVE_RAMPZ__) */
+#endif /* L_dtors */
+
+#ifdef L_tablejump_elpm
+       .global __tablejump_elpm__
+       .func   __tablejump_elpm__
+__tablejump_elpm__:
+#if defined (__AVR_HAVE_ELPM__)
+#if defined (__AVR_HAVE_LPMX__)
+       elpm    __tmp_reg__, Z+
+       elpm    r31, Z
+       mov     r30, __tmp_reg__
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+       eijmp
+#else
+       ijmp
+#endif
+
+#else
+       elpm
+       adiw    r30, 1
+       push    r0
+       elpm
+       push    r0
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+        push    __zero_reg__
+#endif
+       ret
+#endif
+#endif /* defined (__AVR_HAVE_ELPM__) */
+       .endfunc
+#endif /* defined (L_tablejump_elpm) */
+