/* $NetBSD: crtbegin.S,v 1.3 2013/09/12 15:36:14 joerg Exp $ */ /*- * Copyright (c) 2012 Valeriy E. Ushakov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include RCSID("$NetBSD: crtbegin.S,v 1.3 2013/09/12 15:36:14 joerg Exp $") .section .ctors, "aw", @progbits .p2align 2 __CTOR_LIST__: .long -1 .section .dtors, "aw", @progbits .p2align 2 __DTOR_LIST__: .long -1 .section .eh_frame, "a", @progbits .p2align 2 __EH_FRAME_LIST__: .section .jcr, "aw", @progbits .p2align 2 __JCR_LIST__: .section .data.rel, "aw", @progbits .p2align 2 .globl __dso_handle .hidden __dso_handle .type __dso_handle, @object .size __dso_handle, 4 __dso_handle: #ifdef SHARED .long __dso_handle #else .long 0 #endif __dwarf_eh_object: .zero 32 __initialized: .zero 1 __finished: .zero 1 .text .weak __cxa_finalize .weak __deregister_frame_info .weak __register_frame_info .weak _Jv_RegisterClasses /* * A bit of CPP syntactic sugar for accessing variables. * * For PIC we are obliged to use @(r0, r12) since r12 has the GOT * address and only r0 can be used in @(r0, Rm) addressing mode, so we * always load variable address to r0. */ #ifdef __PIC__ #define VAR_DATUM(var) var@GOTOFF #define FUNC_DATUM(f) f@GOT #define R0VAR (r0, r12) #else #define VAR_DATUM(var) var #define FUNC_DATUM(f) f #define R0VAR r0 #endif __do_global_ctors_aux: mov.l r8, @-sp mov.l r9, @-sp #ifdef __PIC__ mov.l r12, @-sp mov.l .Lc_got, r12 mova .Lc_got, r0 add r0, r12 #endif mov.l r14, @-sp sts.l pr, @-sp mov sp, r14 !! if (__initialized) return; mov.l .Lc___initialized, r0 mov.b @R0VAR, r1 tst r1, r1 bf .Lc_return !! __initialized = 1; mov #1, r1 mov.b r1, @R0VAR !! if (__register_frame_info) !! __register_frame_info(&__EH_FRAME_LIST__[0], &__dwarf_eh_object) #ifdef __PIC__ mov.l .Lc___register_frame_info_GOT, r0 mov.l @R0VAR, r1 tst r1, r1 bt .Lc___register_frame_info_done mov.l .Lc___register_frame_info, r0 mov.l .Lc___EH_FRAME_LIST__, r4 mov.l .Lc___dwarf_eh_object, r5 add r12, r4 .Lc___register_frame_info_call: CALL r0 add r12, r5 #else /* !PIC */ mov.l .Lc___register_frame_info, r0 tst r0, r0 bt .Lc___register_frame_info_done mov.l .Lc___EH_FRAME_LIST__, r4 mov.l .Lc___dwarf_eh_object, r5 CALL r0 nop #endif .Lc___register_frame_info_done: !! if (_Jv_RegisterClasses && __JCR_LIST__[0]) !! _Jv_RegisterClasses(&__JCR_LIST__[0]); #ifdef __PIC__ mov.l .Lc__Jv_RegisterClasses_GOT, r0 mov.l @R0VAR, r1 tst r1, r1 bt .Lc__Jv_RegisterClasses_done mov.l .Lc___JCR_LIST__, r0 mov.l @R0VAR, r1 tst r1, r1 bt .Lc__Jv_RegisterClasses_done mov.l .Lc__Jv_RegisterClasses, r2 mov r0, r4 .Lc__Jv_RegisterClasses_call: CALL r2 add r12, r4 #else /* !PIC */ mov.l .Lc__Jv_RegisterClasses, r2 tst r2, r2 bt .Lc__Jv_RegisterClasses_done mov.l .Lc___JCR_LIST__, r0 mov.l @R0VAR, r1 tst r1, r1 bt .Lc__Jv_RegisterClasses_done mov r0, r4 .Lc__Jv_RegisterClasses_call: CALL r2 add r12, r4 #endif .Lc__Jv_RegisterClasses_done: !! call all constructors on __CTOR_LIST__ in reverse order mov.l .Lc___CTOR_LIST_END__, r8 #ifdef __PIC__ add r12, r8 #endif add #-4, r8 mov.l @r8, r9 not r9, r0 ! sentinel at __CTOR_LIST__[0] is -1 .Lc_ctor_list_loop: tst r0, r0 bt.s .Lc_ctor_list_done add #-4, r8 jsr @r9 mov.l @r8, r9 bra .Lc_ctor_list_loop not r9, r0 .Lc_ctor_list_done: .Lc_return: mov r14, sp lds.l @sp+, pr mov.l @sp+, r14 #ifdef __PIC__ mov.l @sp+, r12 #endif mov.l @sp+, r9 rts mov.l @sp+, r8 .p2align 2 .Lc_got: PIC_GOT_DATUM .Lc___initialized: .long VAR_DATUM(__initialized) #ifdef __PIC__ .Lc___register_frame_info_GOT: .long __register_frame_info@GOT #endif .Lc___register_frame_info: CALL_DATUM(__register_frame_info, .Lc___register_frame_info_call) .Lc___EH_FRAME_LIST__: .long VAR_DATUM(__EH_FRAME_LIST__) .Lc___dwarf_eh_object: .long VAR_DATUM(__dwarf_eh_object) #ifdef __PIC__ .Lc__Jv_RegisterClasses_GOT: .long _Jv_RegisterClasses@GOT #endif .Lc__Jv_RegisterClasses: CALL_DATUM(_Jv_RegisterClasses, .Lc__Jv_RegisterClasses_call) .Lc___JCR_LIST__: .long VAR_DATUM(__JCR_LIST__) .Lc___CTOR_LIST_END__: .long VAR_DATUM(__CTOR_LIST_END__) __do_global_dtors_aux: mov.l r8, @-sp mov.l r9, @-sp #ifdef __PIC__ mov.l r12, @-sp mov.l .Ld_got, r12 mova .Ld_got, r0 add r0, r12 #endif mov.l r14, @-sp sts.l pr, @-sp mov sp, r14 !! if (__finished) return; mov.l .Ld___finished, r0 mov.b @R0VAR, r1 tst r1, r1 bf .Ld_return !! __finished = 1; mov #1, r1 mov.b r1, @R0VAR #ifdef SHARED /* implies PIC */ !! if (__cxa_finalize) !! __cxa_finalize(&__dso_handle); mov.l .Ld___cxa_finalize_GOT, r0 mov.l @R0VAR, r1 tst r1, r1 bt .Ld___cxa_finalize_done mov.l .Ld___cxa_finalize, r0 mov.l .Ld___dso_handle, r4 .Ld___cxa_finalize_call: CALL r0 add r12, r4 .Ld___cxa_finalize_done: #endif /* SHARED */ !! call all destructors on __DTOR_LIST__ mov.l .Ld___DTOR_LIST__, r8 #ifdef __PIC__ add r12, r8 #endif add #4, r8 ! skip first entry that we know to be -1 mov.l @r8+, r9 tst r9, r9 .Ld_dtor_list_loop: bt .Ld_dtor_list_done jsr @r9 mov.l @r8+, r9 bra .Ld_dtor_list_loop tst r9, r9 .Ld_dtor_list_done: !! if (__deregister_frame_info) !! __deregister_frame_info(&__EH_FRAME_LIST__[0]); #ifdef __PIC__ mov.l .Ld___deregister_frame_info_GOT, r0 mov.l @R0VAR, r1 tst r1, r1 bt .Ld___deregister_frame_info_done mov.l .Ld___deregister_frame_info, r0 mov.l .Ld___EH_FRAME_LIST__, r4 .Ld___deregister_frame_info_call: CALL r0 add r12, r4 #else /* !PIC */ mov.l .Ld___deregister_frame_info, r0 tst r0, r0 bt .Ld___deregister_frame_info_done mov.l .Ld___EH_FRAME_LIST__, r4 CALL r0 nop #endif .Ld___deregister_frame_info_done: .Ld_return: mov r14, sp lds.l @sp+, pr mov.l @sp+, r14 #ifdef __PIC__ mov.l @sp+, r12 #endif mov.l @sp+, r9 rts mov.l @sp+, r8 .p2align 2 .Ld_got: PIC_GOT_DATUM .Ld___finished: .long VAR_DATUM(__finished) #ifdef SHARED /* implies PIC */ .Ld___cxa_finalize_GOT: .long __cxa_finalize@GOT .Ld___cxa_finalize: CALL_DATUM(__cxa_finalize, .Ld___cxa_finalize_call) .Ld___dso_handle: .long VAR_DATUM(__dso_handle) #endif .Ld___DTOR_LIST__: .long VAR_DATUM(__DTOR_LIST__) #ifdef __PIC__ .Ld___deregister_frame_info_GOT: .long __deregister_frame_info@GOT #endif .Ld___deregister_frame_info: CALL_DATUM(__deregister_frame_info, .Ld___deregister_frame_info_call) .Ld___EH_FRAME_LIST__: .long VAR_DATUM(__EH_FRAME_LIST__) #define _CALL_INIT_FINI_FUNCTION(func) \ mov.l 1f, r1; \ mova 2f, r0; \ 0: braf r1; /* NB: branch, not call ... */ \ lds r0, pr; /* skip the following .long when returning */ \ .p2align 2; \ 1: .long func - (0b+4); \ 2: ; .section .init, "ax", @progbits _CALL_INIT_FINI_FUNCTION(__do_global_ctors_aux) .section .fini, "ax", @progbits _CALL_INIT_FINI_FUNCTION(__do_global_dtors_aux)