1/*
2 * Copyright (C) 2004-2007 Atmel Corporation
3 *
4 * This file is subject to the terms and conditions of the GNU Lesser General
5 * Public License.  See the file "COPYING.LIB" in the main directory of this
6 * archive for more details.
7 *
8 * When we enter _start, the stack looks like this:
9 *	argc		argument counter
10 *	argv[0]		pointer to program name
11 *	argv[1..argc-1]	pointers to program args
12 *	NULL
13 *	env[0..N]	pointers to environment variables
14 *	NULL
15 *
16 * r12 contains a function pointer to be registered with `atexit'.
17 * This is how the dynamic linker arranges to have DT_FINI functions
18 * called for shared libraries that have been loaded before this
19 * code runs.
20 *
21 * We're going to call the following function:
22 * __uClibc_main(int (*main)(int, char **, char **), int argc,
23 *		 char **argv, void (*app_init)(void), void (*app_fini)(void),
24 *		 void (*rtld_fini)(void), void *stack_end)
25 *
26 * So we need to set up things as follows:
27 *	r12 = address of main
28 *	r11 = argc
29 *	r10 = &argv[0]
30 *	r9  = address of _init
31 *	r8  = address of _fini
32 *	sp[0] = whatever we got passed in r12
33 */
34
35#include <features.h>
36
37	.text
38	.global _start
39	.type	_start, @function
40_start:
41	/* Clear the frame pointer and link register since this is the outermost frame.  */
42	mov	r7, 0
43	mov	lr, 0
44
45	ld.w	r11, sp++		/* argc		*/
46	mov	r10, sp			/* &argv[0]	*/
47
48	st.w	--sp, r10		/* stack_end */
49	st.w	--sp, r12		/* rtld_fini */
50
51#ifdef __PIC__
52	lddpc	r6, .L_GOT
53.L_RGOT:
54	rsub	r6, pc
55	lda.w	r9, _init
56	lda.w	r8, _fini
57	lda.w	r12, main
58
59	/* Ok, now run uClibc's main() -- should not return */
60	call	__uClibc_main
61
62	.align	2
63.L_GOT:
64	.long	.L_RGOT - _GLOBAL_OFFSET_TABLE_
65#else
66	lddpc	r9, __init_addr		/* app_init */
67	lddpc	r8, __fini_addr		/* app_fini */
68	lddpc	r12, __main_addr	/* main */
69
70	/* Ok, now run uClibc's main() -- should not return */
71	lddpc	pc, ___uClibc_main_addr
72
73	.align	2
74__init_addr:
75	.long	_init
76__fini_addr:
77	.long	_fini
78__main_addr:
79	.long	main
80___uClibc_main_addr:
81	.long	__uClibc_main
82#endif
83	.size	_start, . - _start
84
85	/*
86	 * The LSB says we need this.
87	 */
88	.section ".note.ABI-tag", "a"
89	.align	4
90	.long	2f - 1f		/* namesz */
91	.long	4f - 3f		/* descsz */
92	.long	1		/* type   */
931:	.asciz	"GNU"		/* name */
942:	.align	4
953:	.long	0		/* Linux executable */
96	.long	2,6,0		/* Earliest compatible kernel */
974:	.align	4
98