Update and reformat copyright, remove trailing white spaces and send
[kopensolaris-gnu/glibc.git] / sysdeps / mips / elf / start.S
1 /* Startup code compliant to the ELF Mips ABI.
2    Copyright (C) 1995, 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 the canonical entry point, usually the first thing in the text
21    segment.  The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
22    point runs, most registers' values are unspecified, except for:
23
24    v1 ($2)      Contains a function pointer to be registered with `atexit'.
25                 This is how the dynamic linker arranges to have DT_FINI
26                 functions called for shared libraries that have been loaded
27                 before this code runs.
28
29    sp ($29)     The stack contains the arguments and environment:
30                 0(%esp)                 argc
31                 4(%esp)                 argv[0]
32                 ...
33                 (4*argc)(%esp)          NULL
34                 (4*(argc+1))(%esp)      envp[0]
35                 ...
36                                         NULL
37    ra ($31)     The return address register is set to zero so that programs
38                 that search backword through stack frames recognize the last
39                 stack frame.
40 */
41
42 #ifdef PIC
43 /* A macro to (re)initialize gp. We can get the run time address of 0f in
44    ra ($31) by blezal instruction. In this early phase, we can't save gp
45    in stack and .cprestore doesn't work properly. So we set gp by using
46    this macro. */
47 #define SET_GP \
48         .set noreorder; \
49         bltzal $0,0f;   \
50         nop;            \
51 0:      .cpload $31;    \
52         .set reorder;
53 #endif
54
55         .text
56         .globl _start
57 _start:
58 #ifdef PIC
59         SET_GP
60 #endif
61         move $31, $0
62
63         /* $2 contains the address of the shared library termination
64            function, which we will register with `atexit' to be called by
65            `exit'.  I suspect that on some systems, and when statically
66            linked, this will not be set by anything to any function
67            pointer; hopefully it will be zero so we don't try to call
68            random pointers.  */
69         beq $2, $0, nofini
70         move $4, $2
71         jal atexit
72 #ifdef PIC
73         SET_GP
74 #endif
75 nofini:
76
77         /* Do essential libc initialization.  In statically linked
78            programs under the GNU Hurd, this is what sets up the
79            arguments on the stack for the code below. Since the argument
80            registers (a0 - a3) saved to the first 4 stack entries by
81            the prologue of __libc_init_first, we preload them to
82            prevent clobbering the stack tops. In Hurd case, stack pointer
83            ($29) may be VM_MAX_ADDRESS here. If so, we must modify it.  */
84 #if (__mips64)
85         dli $4, 0x10000000000
86         bne $29, $4, 1f
87         dsubu $29, 32
88         sd $0, 0($29)
89         sd $0, 8($29)
90         sd $0, 16($29)
91         sd $0, 24($29)
92 1:
93         ld $4, 0($29)
94         ld $5, 8($29)
95         ld $6, 16($29)
96         ld $7, 24($29)
97 #else  /* __mips64 */
98         li $4, 0x80000000
99         bne $29, $4, 1f
100         subu $29, 16
101         sw $0, 0($29)
102         sw $0, 4($29)
103         sw $0, 8($29)
104         sw $0, 12($29)
105 1:
106         lw $4, 0($29)
107         lw $5, 4($29)
108         lw $6, 8($29)
109         lw $7, 12($29)
110 #endif  /* __mips64 */
111
112         jal __libc_init_first
113 #ifdef PIC
114         SET_GP
115 #endif
116 #if (__mips64)
117         ld $4, 0($29)
118         ld $5, 8($29)
119         ld $6, 16($29)
120         ld $7, 24($29)
121 #else  /* __mips64 */
122         lw $4, 0($29)
123         lw $5, 4($29)
124         lw $6, 8($29)
125         lw $7, 12($29)
126 #endif  /* __mips64 */
127
128         /* Call `_init', which is the entry point to our own `.init'
129            section; and register with `atexit' to have `exit' call
130            `_fini', which is the entry point to our own `.fini' section.  */
131         jal _init
132 #ifdef PIC
133         SET_GP
134 #endif
135 #if (__mips64)
136         dla $4, _fini
137 #else  /* __mips64 */
138         la $4, _fini
139 #endif  /* __mips64 */
140
141         jal atexit
142 #ifdef PIC
143         SET_GP
144 #endif
145
146         /* Extract the arguments and environment as encoded on the stack
147            and set up the arguments for `main': argc, argv, envp.  */
148 #if (__mips64)
149         ld $4, 0($29)           /* argc */
150         daddu $5, $29, 8        /* argv */
151         dsll $6, $4, 3
152         daddu $6, $6, 8
153         daddu $6, $5, $6        /* envp = &argv[argc + 1] */
154 #else  /* __mips64 */
155         lw $4, 0($29)           /* argc */
156         addu $5, $29, 4         /* argv */
157         sll $6, $4, 2
158         addu $6, $6, 4
159         addu $6, $5, $6         /* envp = &argv[argc + 1] */
160 #endif  /* __mips64 */
161
162         /* Call the user's main function, and exit with its value.  */
163         jal main
164 #ifdef PIC
165         SET_GP
166 #endif
167         move $4, $2
168         jal exit                /* This should never return.  */
169 hlt:    b hlt                   /* Crash if somehow it does return.  */
170
171 /* Define a symbol for the first piece of initialized data.  */
172         .data
173         .globl __data_start
174 __data_start:
175 #if (__mips64)
176         .dword 0
177 #else  /* __mips64 */
178         .word 0
179 #endif  /* __mips64 */
180         .weak data_start
181         data_start = __data_start