]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crt1.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / arm / crt1.S
1 /* Startup code for ARM & ELF
2    Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002, 2005
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    In addition to the permissions in the GNU Lesser General Public
12    License, the Free Software Foundation gives you unlimited
13    permission to link the compiled version of this file with other
14    programs, and to distribute those programs without any restriction
15    coming from the use of this file. (The GNU Lesser General Public
16    License restrictions do apply in other respects; for example, they
17    cover modification of the file, and distribution when not linked
18    into another program.)
19
20    Note that people who make modified versions of this file are not
21    obligated to grant this special exception for their modified
22    versions; it is their choice whether to do so. The GNU Lesser
23    General Public License gives permission to release a modified
24    version without this exception; this exception also makes it
25    possible to release a modified version which carries forward this
26    exception.
27
28    The GNU C Library is distributed in the hope that it will be useful,
29    but WITHOUT ANY WARRANTY; without even the implied warranty of
30    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31    Lesser General Public License for more details.
32
33    You should have received a copy of the GNU Lesser General Public
34    License along with the GNU C Library; if not, see
35    <http://www.gnu.org/licenses/>.  */
36
37 /* This is the canonical entry point, usually the first thing in the text
38    segment.
39
40         Note that the code in the .init section has already been run.
41         This includes _init and _libc_init
42
43
44         At this entry point, most registers' values are unspecified, except:
45
46    a1           Contains a function pointer to be registered with `atexit'.
47                 This is how the dynamic linker arranges to have DT_FINI
48                 functions called for shared libraries that have been loaded
49                 before this code runs.
50
51    sp           The stack contains the arguments and environment:
52                 0(sp)                   argc
53                 4(sp)                   argv[0]
54                 ...
55                 (4*argc)(sp)            NULL
56                 (4*(argc+1))(sp)        envp[0]
57                 ...
58                                         NULL
59 */
60 /*
61    For uClinux it looks like this:
62
63         argc            argument counter (integer)
64         argv            char *argv[]
65         envp            char *envp[]
66         argv[0]         program name (pointer)
67         argv[1...N]     program args (pointers)
68         argv[argc-1]    end of args (integer)
69         NULL
70         env[0...N]      environment variables (pointers)
71         NULL
72
73 ARM register quick reference:
74
75     Name    Number       ARM Procedure Calling Standard Role
76
77     a1      r0           argument 1 / integer result / scratch register / argc
78     a2      r1           argument 2 / scratch register / argv
79     a3      r2           argument 3 / scratch register / envp
80     a4      r3           argument 4 / scratch register
81     v1      r4           register variable
82     v2      r5           register variable
83     v3      r6           register variable
84     v4      r7           register variable
85     v5      r8           register variable
86     sb/v6   r9           static base / register variable
87     sl/v7   r10          stack limit / stack chunk handle / reg. variable
88     fp      r11          frame pointer
89     ip      r12          scratch register / new-sb in inter-link-unit calls
90     sp      r13          lower end of current stack frame
91     lr      r14          link address / scratch register
92     pc      r15          program counter
93 */
94
95 #include <features.h>
96 #include <bits/arm_asm.h>
97
98 .text
99         .globl  _start
100         .type   _start,%function
101         .type   _init,%function
102         .type   _fini,%function
103 #ifndef __UCLIBC_CTOR_DTOR__
104         .weak   _init
105         .weak   _fini
106 #endif
107
108 #if defined(THUMB1_ONLY)
109 .thumb_func
110 _start:
111         /* Clear the frame pointer since this is the outermost frame.  */
112         mov r3, #0
113         mov fp, r3
114
115 #ifdef __ARCH_USE_MMU__
116         /* Pop argc off the stack and save a pointer to argv */
117         pop {a2}
118         mov a3, sp
119 #else
120         /*
121          * uClinux/arm stacks look a little different from normal
122          * MMU-full Linux/arm stacks (for no good reason)
123          */
124         /* pull argc and argv off the stack.  We are going to push 3
125          * arguments, so pop one here to maintain doubleword alignment.  */
126         pop {a2}
127         ldr a3, [sp]
128 #endif
129
130         /* Push stack limit and rtld_fini */
131         push {a1, a3}
132
133 #ifdef __PIC__
134         ldr r4, .L_GOT
135         adr r5, .L_GOT
136         add r4, r5, r4
137
138         ldr r5, .L_GOT+4        /* _fini */
139         ldr a1, [r4, r5]
140         push {a1}               /* Push _fini */
141
142         ldr r5, .L_GOT+8        /* _init */
143         ldr a4, [r4, r5]
144         
145         ldr r5, .L_GOT+12       /* main */
146         ldr a1, [r4, r5]
147
148 #else
149         /* Fetch address of fini */
150         ldr r4, =_fini
151         /* Push fini */
152         push {r4}
153
154         /* Set up the other arguments in registers */
155         ldr a1, =main
156         ldr a4, =_init
157 #endif
158         /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
159         /* Let the libc call main and exit with its return code.  */
160         bl __uClibc_main
161
162         /* should never get here....*/
163         bl abort
164 .pool
165
166 #ifdef __PIC__
167 .L_GOT:
168         .word   _GLOBAL_OFFSET_TABLE_-.L_GOT
169         .word _fini(GOT)
170         .word _init(GOT)
171         .word main(GOT)
172 #endif
173 #else /* !THUMB1_ONLY */
174 _start:
175         /* Clear the frame pointer and link register since this is the outermost frame.  */
176         mov fp, #0
177         mov lr, #0
178
179 #ifdef __ARCH_USE_MMU__
180         /* Pop argc off the stack and save a pointer to argv */
181         ldr a2, [sp], #4
182         mov a3, sp
183 #else
184         /*
185          * uClinux/arm stacks look a little different from normal
186          * MMU-full Linux/arm stacks (for no good reason)
187          */
188         /* pull argc and argv off the stack.  We are going to push 3
189          * arguments, so pop one here to maintain doubleword alignment.  */
190         ldr a2, [sp], #4
191         ldr a3, [sp]
192 #endif
193
194         /* Push stack limit */
195         str a3, [sp, #-4]!
196
197         /* Push rtld_fini */
198         str a1, [sp, #-4]!
199
200 #ifdef __PIC__
201         ldr sl, .L_GOT
202         adr a4, .L_GOT
203         add sl, sl, a4
204
205         ldr ip, .L_GOT+4        /* _fini */
206         ldr a1, [sl, ip]
207         str a1, [sp, #-4]!      /* Push _fini */
208
209         ldr ip, .L_GOT+8        /* _init */
210         ldr a4, [sl, ip]
211         
212         ldr ip, .L_GOT+12       /* main */
213         ldr a1, [sl, ip]
214
215         /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
216         /* Let the libc call main and exit with its return code.  */
217         b __uClibc_main(PLT)
218 #else
219         /* Fetch address of fini */
220         ldr ip, =_fini
221         /* Push fini */
222         str ip, [sp, #-4]!
223
224         /* Set up the other arguments in registers */
225         ldr a1, =main
226         ldr a4, =_init
227
228         /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
229
230         /* Let the libc call main and exit with its return code.  */
231         b __uClibc_main
232 #endif
233
234         /* should never get here....*/
235         bl abort
236
237 #ifdef __PIC__
238 .L_GOT:
239         .word _GLOBAL_OFFSET_TABLE_ - .L_GOT
240         .word _fini(GOT)
241         .word _init(GOT)
242         .word main(GOT)
243 #endif
244 #endif
245
246 /* Define a symbol for the first piece of initialized data.  */
247         .data
248         .globl __data_start
249 __data_start:
250         .long 0
251         .weak data_start
252         data_start = __data_start