diff options
Diffstat (limited to 'libc/sysdeps/linux/avr32/crt1.S')
-rw-r--r-- | libc/sysdeps/linux/avr32/crt1.S | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/avr32/crt1.S b/libc/sysdeps/linux/avr32/crt1.S new file mode 100644 index 000000000..0f0a2e87d --- /dev/null +++ b/libc/sysdeps/linux/avr32/crt1.S @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * When we enter _start, the stack looks like this: + * argc argument counter + * argv[0] pointer to program name + * argv[1..argc-1] pointers to program args + * NULL + * env[0..N] pointers to environment variables + * NULL + * + * r12 contains a function pointer to be registered with `atexit'. + * This is how the dynamic linker arranges to have DT_FINI functions + * called for shared libraries that have been loaded before this + * code runs. + * + * We're going to call the following function: + * __uClibc_main(int (*main)(int, char **, char **), int argc, + * char **argv, void (*app_init)(void), void (*app_fini)(void), + * void (*rtld_fini)(void), void *stack_end) + * + * So we need to set up things as follows: + * r12 = address of main + * r11 = argc + * r10 = &argv[0] + * r9 = address of _init + * r8 = address of _fini + * sp[0] = whatever we got passed in r12 + */ + +#include <features.h> + + .text + .global _start + .type _start, @function +_start: + /* Clear the frame pointer and link register since this is the outermost frame. */ + mov r7, 0 + mov lr, 0 + + ld.w r11, sp++ /* argc */ + mov r10, sp /* &argv[0] */ + + st.w --sp, r10 /* stack_end */ + st.w --sp, r12 /* rtld_fini */ + +#ifdef __PIC__ + lddpc r6, .L_GOT +.L_RGOT: + rsub r6, pc + lda.w r9, _init + lda.w r8, _fini + lda.w r12, main + + /* Ok, now run uClibc's main() -- should not return */ + call __uClibc_main + + .align 2 +.L_GOT: + .long .L_RGOT - _GLOBAL_OFFSET_TABLE_ +#else + lddpc r9, __init_addr /* app_init */ + lddpc r8, __fini_addr /* app_fini */ + lddpc r12, __main_addr /* main */ + + /* Ok, now run uClibc's main() -- should not return */ + lddpc pc, ___uClibc_main_addr + + .align 2 +__init_addr: + .long _init +__fini_addr: + .long _fini +__main_addr: + .long main +___uClibc_main_addr: + .long __uClibc_main +#endif + .size _start, . - _start + + /* + * The LSB says we need this. + */ + .section ".note.ABI-tag", "a" + .align 4 + .long 2f - 1f /* namesz */ + .long 4f - 3f /* descsz */ + .long 1 /* type */ +1: .asciz "GNU" /* name */ +2: .align 4 +3: .long 0 /* Linux executable */ + .long 2,6,0 /* Earliest compatible kernel */ +4: .align 4 |