Add copyright text.
[kopensolaris-gnu/glibc.git] / sysdeps / powerpc / elf / start.c
1 /* Startup code compliant to the ELF PowerPC ABI.
2    Copyright (C) 1997 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 /* This is SVR4/PPC ABI compliant, and works under Linux when
21    statically linked.  */
22
23 #include <unistd.h>
24 #include <stdlib.h>
25
26 /* Just a little assembler stub before gcc gets its hands on our
27    stack pointer... */
28 asm ("\
29         .section \".text\"
30         .align 2
31         .globl _start
32         .type _start,@function
33 _start:
34  # save the stack pointer, in case we're statically linked under Linux
35         mr 8,1
36  # set up an initial stack frame, and clear the LR
37         addi 1,1,-16
38         clrrwi 1,1,4
39         li 0,0
40         stw 0,0(1)
41         mtlr 0
42  # set r13 to point at the 'small data area'
43         lis 13,_SDA_BASE_@ha
44         addi 13,13,_SDA_BASE_@l
45  # and continue below.
46         b __start1
47 0:
48         .size    _start,0b-_start
49  # undo '.section text'.
50         .previous
51 ");
52
53 /* Define a symbol for the first piece of initialized data.  */
54 int __data_start = 0;
55 weak_alias (__data_start, data_start)
56
57 /* these probably should go, at least go somewhere else
58    (sysdeps/mach/something?). */
59 void (*_mach_init_routine) (void);
60 void (*_thread_init_routine) (void);
61
62 extern void __libc_init_first (int argc, char **argv, char **envp);
63 extern int main (int argc, char **argv, char **envp, void *auxvec);
64 #ifdef HAVE_INITFINI
65 extern void _init (void);
66 extern void _fini (void);
67 #endif
68
69 #if 0
70 /* I'd like to say this, but it causes GCC to strip the whole procedure
71    from the object file (this is sort of reasonable, because you've told
72    GCC that the procedure is unused). :-( */
73 static void __start1(int argc, char **argv, char **envp,
74                      void *auxvec, void (*exitfn) (void),
75                      char **stack_on_entry)
76      __attribute__ ((unused));
77
78 static
79 #endif
80 void
81 __start1(int argc, char **argv, char **envp,
82          void *auxvec, void (*exitfn) (void),
83          char **stack_on_entry)
84 {
85   /* the PPC SVR4 ABI says that the top thing on the stack will
86      be a NULL pointer, so if not we assume that we're being called
87      as a statically-linked program by Linux...  */
88   if (*stack_on_entry != NULL)
89     {
90       /* ...in which case, we have argc as the top thing on the
91          stack, followed by argv (NULL-terminated), envp (likewise),
92          and the auxilary vector.  */
93       argc = *(int *) stack_on_entry;
94       argv = stack_on_entry + 1;
95       envp = argv + argc + 1;
96       auxvec = envp;
97       while (*(char **) auxvec != NULL)
98         ++auxvec;
99       ++auxvec;
100       exitfn = NULL;
101     }
102
103   if (exitfn != NULL)
104     atexit (exitfn);
105
106   /* libc init routine, in case we are statically linked
107      (otherwise ld.so will have called it when it loaded libc, but
108      calling it twice doesn't hurt). */
109   __libc_init_first (argc, argv, envp);
110
111 #ifdef HAVE_INITFINI
112   /* ELF constructors/destructors */
113   atexit (_fini);
114   _init ();
115 #endif
116
117   /* Stuff so we can build Mach/Linux executables (like vmlinux).  */
118   if (_mach_init_routine != 0)
119     _mach_init_routine ();
120   if (_thread_init_routine != 0)
121     _thread_init_routine ();
122
123   /* the rest of the program */
124   exit (main (argc, argv, envp, auxvec));
125 }