OSDN Git Service

Based on start.S from debian's glibc, this gets arm working
authorEric Andersen <andersen@codepoet.org>
Fri, 10 Jun 2005 23:22:23 +0000 (23:22 -0000)
committerEric Andersen <andersen@codepoet.org>
Fri, 10 Jun 2005 23:22:23 +0000 (23:22 -0000)
properly with the new ABI

libc/sysdeps/linux/arm/crt1.S

index 65f27d0..8ae897c 100644 (file)
-/* 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
-