summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/arm/crt1.S
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2005-06-10 23:22:23 +0000
committerEric Andersen <andersen@codepoet.org>2005-06-10 23:22:23 +0000
commit299d67551ee7473ccf2d3ace53b73383b295fe27 (patch)
tree9e5a54fba1bdb614f09e35b5a647e19b32088319 /libc/sysdeps/linux/arm/crt1.S
parentcaaf3c4862005856b6de88c4e447ec1cdbd1b135 (diff)
Based on start.S from debian's glibc, this gets arm working
properly with the new ABI
Diffstat (limited to 'libc/sysdeps/linux/arm/crt1.S')
-rw-r--r--libc/sysdeps/linux/arm/crt1.S207
1 files changed, 69 insertions, 138 deletions
diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S
index 65f27d0dc..8ae897c06 100644
--- a/libc/sysdeps/linux/arm/crt1.S
+++ b/libc/sysdeps/linux/arm/crt1.S
@@ -1,148 +1,80 @@
-/* When we enter this piece of code, the program stack looks like this:
- argc argument counter (integer)
- argv[0] program name (pointer)
- argv[1...N] program args (pointers)
- argv[argc-1] end of args (integer)
- NULL
- env[0...N] environment variables (pointers)
- NULL
-
- For uClinux it looks like this:
-
- argc argument counter (integer)
- argv char *argv[]
- envp char *envp[]
- argv[0] program name (pointer)
- argv[1...N] program args (pointers)
- argv[argc-1] end of args (integer)
- NULL
- env[0...N] environment variables (pointers)
- NULL
-
- When we are done here, we want
- a1=argc
- a2=argv[0]
- a3=argv[argc+1]
-
-ARM register quick reference:
-
- Name Number ARM Procedure Calling Standard Role
-
- a1 r0 argument 1 / integer result / scratch register / argc
- a2 r1 argument 2 / scratch register / argv
- a3 r2 argument 3 / scratch register / envp
- a4 r3 argument 4 / scratch register
- v1 r4 register variable
- v2 r5 register variable
- v3 r6 register variable
- v4 r7 register variable
- v5 r8 register variable
- sb/v6 r9 static base / register variable
- sl/v7 r10 stack limit / stack chunk handle / reg. variable
- fp r11 frame pointer
- ip r12 scratch register / new-sb in inter-link-unit calls
- sp r13 lower end of current stack frame
- lr r14 link address / scratch register
- pc r15 program counter
+/* Startup code for ARM & ELF
+ Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment.
+
+ Note that the code in the .init section has already been run.
+ This includes _init and _libc_init
+
+
+ At this entry point, most registers' values are unspecified, except:
+
+ a1 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.
+
+ sp The stack contains the arguments and environment:
+ 0(sp) argc
+ 4(sp) argv[0]
+ ...
+ (4*argc)(sp) NULL
+ (4*(argc+1))(sp) envp[0]
+ ...
+ NULL
*/
-#include <features.h>
+ .text
+ .globl _start
+ .type _start,#function
+_start:
+ /* Fetch address of fini */
+ ldr ip, =_fini
-.text
- .global _start
- .type _start,%function
- .type _init,%function
- .type _fini,%function
- .type main,%function
- .type __uClibc_main,%function
+ /* Clear the frame pointer since this is the outermost frame. */
+ mov fp, #0
+ /* Pop argc off the stack and save a pointer to argv */
+ ldr a2, [sp], #4
+ mov a3, sp
-.text
-_start:
- /* Save a copy of rtld_fini before r0 gets nuked */
- mov r5, r0
-
- /* clear the frame pointer */
- mov fp, #0
-
-
- /* Load register r0 with main */
-#ifdef __PIC__
- adr r8, .L_main
- ldr r0, .L_main
- add r0, r0, r8
-#else
- ldr r0, =main
-#endif
-
-
-#ifdef __ARCH_HAS_MMU__
-
- /* Load register r1 from the stack to its final resting place */
- ldr r1, [sp], #4
-
- /* Copy argv pointer into r2 -- which its final resting place */
- mov r2, sp
-#else
- /*
- * uClinux stacks look a little different from normal
- * MMU-full Linux stacks (for no good reason)
- */
- /* pull argc and argv off the stack */
- ldr r1,[sp, #0]
- ldr r2,[sp, #4]
-#endif
-
- /* Store _init and _fini to r3 and r4 */
-#ifdef __PIC__
- adr r8, .L_init
- ldr r3, .L_init
- add r3, r3, r8
-
- ldr r4, .L_init + 4
- add r4, r4, r8
-#else
- ldr r3, =_init
- ldr r4, =_fini
-#endif
-
- /* Store _fini(r4), rtld_fini(r5), and stack_end(r2) on the stack */
- str r2, [sp, #-4]!
- str r5, [sp, #-4]!
- str r4, [sp, #-4]!
-
-
- /* We need to call __uClibc_main which should not return.
- __uClibc_main (int (*main) (int, char **, char **), int argc,
- char **argv, void (*init) (void), void (*fini) (void),
- void (*rtld_fini) (void), void *stack_end)
- */
- bl __uClibc_main
+ /* Push stack limit */
+ str a3, [sp, #-4]!
- /* Crash if somehow `exit' returns anyways. */
- bl abort
+ /* Push rtld_fini */
+ str a1, [sp, #-4]!
-#ifdef __PIC__
-.L_init:
- .word _init
- .word _fini
-.L_main:
- .word main
-#endif
+ /* Set up the other arguments in registers */
+ ldr a1, =main
+ ldr a4, =_init
-/* We need this stuff to make gdb behave itself, otherwise
- gdb will choke with SIGILL when trying to debug apps.
-*/
- .section ".note.ABI-tag", "a"
- .align 4
- .long 1f - 0f
- .long 3f - 2f
- .long 1
-0: .asciz "GNU"
-1: .align 4
-2: .long 0
- .long 2,0,0
-3: .align 4
+ /* Push fini */
+ str ip, [sp, #-4]!
+
+ /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
+
+ /* Let the libc call main and exit with its return code. */
+ bl __uClibc_main
+
+ /* should never get here....*/
+ bl abort
/* Define a symbol for the first piece of initialized data. */
.data
@@ -151,4 +83,3 @@ __data_start:
.long 0
.weak data_start
data_start = __data_start
-