]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crt1.S
18e3686fadbb08177a34d26f2da99dadd0d79c57
[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, write to the Free
35    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
36    02111-1307 USA.  */
37
38 /* This is the canonical entry point, usually the first thing in the text
39    segment.
40
41         Note that the code in the .init section has already been run.
42         This includes _init and _libc_init
43
44
45         At this entry point, most registers' values are unspecified, except:
46
47    a1           Contains a function pointer to be registered with `atexit'.
48                 This is how the dynamic linker arranges to have DT_FINI
49                 functions called for shared libraries that have been loaded
50                 before this code runs.
51
52    sp           The stack contains the arguments and environment:
53                 0(sp)                   argc
54                 4(sp)                   argv[0]
55                 ...
56                 (4*argc)(sp)            NULL
57                 (4*(argc+1))(sp)        envp[0]
58                 ...
59                                         NULL
60 */
61 /*
62    For uClinux it looks like this:
63
64         argc            argument counter (integer)
65         argv            char *argv[]
66         envp            char *envp[]
67         argv[0]         program name (pointer)
68         argv[1...N]     program args (pointers)
69         argv[argc-1]    end of args (integer)
70         NULL
71         env[0...N]      environment variables (pointers)
72         NULL
73
74 ARM register quick reference:
75
76     Name    Number       ARM Procedure Calling Standard Role
77
78     a1      r0           argument 1 / integer result / scratch register / argc
79     a2      r1           argument 2 / scratch register / argv
80     a3      r2           argument 3 / scratch register / envp
81     a4      r3           argument 4 / scratch register
82     v1      r4           register variable
83     v2      r5           register variable
84     v3      r6           register variable
85     v4      r7           register variable
86     v5      r8           register variable
87     sb/v6   r9           static base / register variable
88     sl/v7   r10          stack limit / stack chunk handle / reg. variable
89     fp      r11          frame pointer
90     ip      r12          scratch register / new-sb in inter-link-unit calls
91     sp      r13          lower end of current stack frame
92     lr      r14          link address / scratch register
93     pc      r15          program counter
94 */
95
96 #include <features.h>
97 #include <bits/arm_asm.h>
98
99 .text
100         .globl  _start
101         .type   _start,%function
102         .type   _init,%function
103         .type   _fini,%function
104 #ifndef __UCLIBC_CTOR_DTOR__
105         .weak   _init
106         .weak   _fini
107 #endif
108
109 #if defined(THUMB1_ONLY)
110 .thumb_func
111 _start:
112         /* Clear the frame pointer since this is the outermost frame.  */
113         mov r3, #0
114         mov fp, r3
115
116 #ifdef __ARCH_USE_MMU__
117         /* Pop argc off the stack and save a pointer to argv */
118         pop {a2}
119         mov a3, sp
120 #else
121         /*
122          * uClinux/arm stacks look a little different from normal
123          * MMU-full Linux/arm stacks (for no good reason)
124          */
125         /* pull argc and argv off the stack.  We are going to push 3
126          * arguments, so pop one here to maintain doubleword alignment.  */
127         pop {a2}
128         ldr a3, [sp]
129 #endif
130
131         /* Push stack limit and rtld_fini */
132         push {a1, a3}
133
134 #ifdef __PIC__
135         ldr r4, .L_GOT
136 .L_GOT_OFF:
137         adr r5, .L_GOT
138         add r4, r5, r4
139
140         ldr r5, .L_GOT+4        /* _fini */
141         ldr a1, [r4, r5]
142         push {a1}               /* Push _fini */
143
144         ldr r5, .L_GOT+8        /* _init */
145         ldr a4, [r4, r5]
146         
147         ldr r5, .L_GOT+12       /* main */
148         ldr a1, [r4, r5]
149
150 #else
151         /* Fetch address of fini */
152         ldr r4, =_fini
153         /* Push fini */
154         push {r4}
155
156         /* Set up the other arguments in registers */
157         ldr a1, =main
158         ldr a4, =_init
159 #endif
160         /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
161         /* Let the libc call main and exit with its return code.  */
162         bl __uClibc_main
163
164         /* should never get here....*/
165         bl abort
166 .pool
167
168 #ifdef __PIC__
169 .L_GOT:
170         .word   _GLOBAL_OFFSET_TABLE_-.L_GOT
171         .word _fini(GOT)
172         .word _init(GOT)
173         .word main(GOT)
174 #endif
175 #else /* !THUMB1_ONLY */
176 _start:
177         /* Clear the frame pointer and link register since this is the outermost frame.  */
178         mov fp, #0
179         mov lr, #0
180
181 #ifdef __ARCH_USE_MMU__
182         /* Pop argc off the stack and save a pointer to argv */
183         ldr a2, [sp], #4
184         mov a3, sp
185 #else
186         /*
187          * uClinux/arm stacks look a little different from normal
188          * MMU-full Linux/arm stacks (for no good reason)
189          */
190         /* pull argc and argv off the stack.  We are going to push 3
191          * arguments, so pop one here to maintain doubleword alignment.  */
192         ldr a2, [sp], #4
193         ldr a3, [sp]
194 #endif
195
196         /* Push stack limit */
197         str a3, [sp, #-4]!
198
199         /* Push rtld_fini */
200         str a1, [sp, #-4]!
201
202 #ifdef __PIC__
203         ldr sl, .L_GOT
204 .L_GOT_OFF:
205         add sl, pc, sl
206
207         ldr ip, .L_GOT+4        /* _fini */
208         ldr a1, [sl, ip]
209         str a1, [sp, #-4]!      /* Push _fini */
210
211         ldr ip, .L_GOT+8        /* _init */
212         ldr a4, [sl, ip]
213         
214         ldr ip, .L_GOT+12       /* main */
215         ldr a1, [sl, ip]
216
217         /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
218         /* Let the libc call main and exit with its return code.  */
219         b __uClibc_main(PLT)
220 #else
221         /* Fetch address of fini */
222         ldr ip, =_fini
223         /* Push fini */
224         str ip, [sp, #-4]!
225
226         /* Set up the other arguments in registers */
227         ldr a1, =main
228         ldr a4, =_init
229
230         /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
231
232         /* Let the libc call main and exit with its return code.  */
233         b __uClibc_main
234 #endif
235
236         /* should never get here....*/
237         bl abort
238
239 #ifdef __PIC__
240 .L_GOT:
241 #ifdef __thumb__
242         .word   _GLOBAL_OFFSET_TABLE_-(.L_GOT_OFF+4)
243 #else /* __thumb2__ */
244         .word   _GLOBAL_OFFSET_TABLE_-(.L_GOT_OFF+8)
245 #endif
246         .word _fini(GOT)
247         .word _init(GOT)
248         .word main(GOT)
249 #endif
250 #endif
251
252 /* Define a symbol for the first piece of initialized data.  */
253         .data
254         .globl __data_start
255 __data_start:
256         .long 0
257         .weak data_start
258         data_start = __data_start