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