]>
Commit | Line | Data |
---|---|---|
03261851 RK |
1 | /* |
2 | * crt0.S -- startup file for MIPS. | |
3 | * | |
24b1ccc6 | 4 | * Copyright (c) 1995, 1996, 1997, 2001 Cygnus Support |
03261851 RK |
5 | * |
6 | * The authors hereby grant permission to use, copy, modify, distribute, | |
7 | * and license this software and its documentation for any purpose, provided | |
8 | * that existing copyright notices are retained in all copies and that this | |
9 | * notice is included verbatim in any distributions. No written agreement, | |
10 | * license, or royalty fee is required for any of the authorized uses. | |
11 | * Modifications to this software may be copyrighted by their authors | |
12 | * and need not follow the licensing terms described here, provided that | |
13 | * the new terms are clearly indicated on the first page of each file where | |
14 | * they apply. | |
15 | */ | |
16 | ||
17 | #ifdef __mips16 | |
18 | /* This file contains 32 bit assembly code. */ | |
19 | .set nomips16 | |
20 | #endif | |
21 | ||
22 | #include "regs.S" | |
23 | ||
24 | /* | |
25 | * Set up some room for a stack. We just grab a chunk of memory. | |
26 | */ | |
27 | #define STACK_SIZE 0x4000 | |
28 | #define GLOBAL_SIZE 0x2000 | |
29 | ||
30 | #define STARTUP_STACK_SIZE 0x0100 | |
31 | ||
32 | /* This is for referencing addresses that are not in the .sdata or | |
33 | .sbss section under embedded-pic, or before we've set up gp. */ | |
34 | #ifdef __mips_embedded_pic | |
35 | # ifdef __mips64 | |
36 | # define LA(t,x) la t,x-PICBASE ; daddu t,s0,t | |
37 | # else | |
38 | # define LA(t,x) la t,x-PICBASE ; addu t,s0,t | |
39 | # endif | |
2d210c7f | 40 | #else /* __mips_embedded_pic */ |
03261851 | 41 | # define LA(t,x) la t,x |
2d210c7f | 42 | #endif /* __mips_embedded_pic */ |
03261851 RK |
43 | |
44 | .comm __memsize, 12 | |
45 | .comm __lstack, STARTUP_STACK_SIZE | |
03261851 RK |
46 | |
47 | .text | |
48 | .align 2 | |
49 | ||
50 | /* Without the following nop, GDB thinks _start is a data variable. | |
51 | * This is probably a bug in GDB in handling a symbol that is at the | |
52 | * start of the .text section. | |
53 | */ | |
54 | nop | |
55 | ||
451e4528 | 56 | .globl hardware_hazard_hook .text |
03261851 RK |
57 | .globl _start |
58 | .ent _start | |
59 | _start: | |
60 | .set noreorder | |
61 | #ifdef __mips_embedded_pic | |
451e4528 | 62 | #define PICBASE start_PICBASE |
03261851 RK |
63 | PICBASE = .+8 |
64 | bal PICBASE | |
65 | nop | |
66 | move s0,$31 | |
67 | #endif | |
0978efa0 | 68 | #if !defined(__mips64) || (__mips_fpr==32) |
03261851 RK |
69 | #define STATUS_MASK (SR_CU1|SR_PE) |
70 | #else | |
71 | # For mips3 or mips4, turn on 64-bit addressing and additional float regs | |
72 | #define STATUS_MASK (SR_CU1|SR_PE|SR_FR|SR_KX|SR_SX|SR_UX) | |
73 | #endif | |
74 | li v0, STATUS_MASK | |
75 | mtc0 v0, C0_SR | |
76 | mtc0 zero, C0_CAUSE | |
77 | nop | |
78 | ||
451e4528 JJ |
79 | /* Avoid hazard from FPU enable and other SR changes. */ |
80 | LA (t0, hardware_hazard_hook) | |
81 | beq t0,zero,1f | |
82 | nop | |
83 | jal t0 | |
84 | nop | |
85 | 1: | |
86 | ||
03261851 RK |
87 | /* Check for FPU presence. Don't check if we know that soft_float is |
88 | being used. (This also avoids illegal instruction exceptions.) */ | |
89 | ||
90 | #ifndef __mips_soft_float | |
91 | li t2,0xAAAA5555 | |
92 | mtc1 t2,fp0 /* write to FPR 0 */ | |
93 | mtc1 zero,fp1 /* write to FPR 1 */ | |
94 | mfc1 t0,fp0 | |
95 | mfc1 t1,fp1 | |
96 | nop | |
97 | bne t0,t2,1f /* check for match */ | |
98 | nop | |
99 | bne t1,zero,1f /* double check */ | |
100 | nop | |
101 | j 2f /* FPU is present. */ | |
102 | nop | |
103 | #endif | |
104 | 1: | |
105 | /* FPU is not present. Set status register to say that. */ | |
106 | li v0, (STATUS_MASK-(STATUS_MASK & SR_CU1)) | |
107 | mtc0 v0, C0_SR | |
108 | nop | |
451e4528 JJ |
109 | /* Avoid hazard from FPU disable. */ |
110 | LA (t0, hardware_hazard_hook) | |
111 | beq t0,zero,2f | |
112 | nop | |
113 | jal t0 | |
114 | nop | |
03261851 RK |
115 | 2: |
116 | ||
117 | ||
2d210c7f | 118 | /* Fix high bits, if any, of the PC so that exception handling |
03261851 RK |
119 | doesn't get confused. */ |
120 | LA (v0, 3f) | |
121 | jr v0 | |
122 | nop | |
123 | 3: | |
124 | LA (gp, _gp) # set the global data pointer | |
125 | .end _start | |
126 | ||
127 | /* | |
128 | * zero out the bss section. | |
129 | */ | |
130 | .globl __memsize | |
131 | .globl get_mem_info .text | |
132 | .globl __stack | |
133 | .globl __global | |
03261851 RK |
134 | .ent zerobss |
135 | zerobss: | |
136 | LA (v0, _fbss) | |
137 | LA (v1, _end) | |
138 | 3: | |
139 | sw zero,0(v0) | |
140 | bltu v0,v1,3b | |
141 | addiu v0,v0,4 # executed in delay slot | |
142 | ||
143 | la t0, __lstack # make a small stack so we | |
144 | addiu sp, t0, STARTUP_STACK_SIZE # can run some C code | |
145 | la a0, __memsize # get the usable memory size | |
146 | jal get_mem_info | |
147 | nop | |
148 | ||
149 | /* setup the stack pointer */ | |
150 | LA (t0, __stack) # is __stack set ? | |
151 | bne t0,zero,4f | |
152 | nop | |
153 | ||
154 | /* NOTE: a0[0] contains the amount of memory available, and | |
155 | not the last memory address. */ | |
325d68a2 | 156 | la a0, __memsize |
03261851 RK |
157 | lw t0,0(a0) # last address of memory available |
158 | la t1,K0BASE # cached kernel memory | |
159 | addu t0,t0,t1 # get the end of memory address | |
afa53b05 RS |
160 | /* Allocate 32 bytes for the register parameters. Allocate 16 |
161 | bytes for a null argv and envp. Round the result up to 64 | |
162 | bytes to preserve alignment. */ | |
163 | subu t0,t0,64 | |
03261851 RK |
164 | 4: |
165 | move sp,t0 # set stack pointer | |
03261851 RK |
166 | .end zerobss |
167 | ||
168 | /* | |
169 | * initialize target specific stuff. Only execute these | |
170 | * functions it they exist. | |
171 | */ | |
172 | .globl hardware_init_hook .text | |
173 | .globl software_init_hook .text | |
0a7908a6 EC |
174 | .type _fini,@function |
175 | .type _init,@function | |
03261851 RK |
176 | .globl atexit .text |
177 | .globl exit .text | |
03261851 RK |
178 | .ent init |
179 | init: | |
180 | LA (t9, hardware_init_hook) # init the hardware if needed | |
181 | beq t9,zero,6f | |
182 | nop | |
183 | jal t9 | |
184 | nop | |
185 | 6: | |
186 | LA (t9, software_init_hook) # init the hardware if needed | |
187 | beq t9,zero,7f | |
188 | nop | |
189 | jal t9 | |
190 | nop | |
191 | 7: | |
0a7908a6 | 192 | LA (a0, _fini) |
03261851 RK |
193 | jal atexit |
194 | nop | |
195 | ||
196 | #ifdef GCRT0 | |
197 | .globl _ftext | |
198 | .globl _extext | |
199 | LA (a0, _ftext) | |
200 | LA (a1, _etext) | |
201 | jal monstartup | |
202 | nop | |
203 | #endif | |
204 | ||
2d210c7f | 205 | |
0a7908a6 EC |
206 | jal _init # run global constructors |
207 | nop | |
208 | ||
afa53b05 RS |
209 | addiu a1,sp,32 # argv = sp + 32 |
210 | addiu a2,sp,40 # envp = sp + 40 | |
211 | #if __mips64 | |
212 | sd zero,(a1) # argv[argc] = 0 | |
213 | sd zero,(a2) # envp[0] = 0 | |
214 | #else | |
215 | sw zero,(a1) | |
216 | sw zero,(a2) | |
217 | #endif | |
03261851 | 218 | jal main # call the program start function |
afa53b05 | 219 | move a0,zero # set argc to 0 |
03261851 RK |
220 | |
221 | # fall through to the "exit" routine | |
222 | jal exit # call libc exit to run the G++ | |
223 | # destructors | |
224 | move a0,v0 # pass through the exit code | |
225 | .end init | |
451e4528 | 226 | |
2d210c7f | 227 | |
451e4528 JJ |
228 | /* Assume the PICBASE set up above is no longer valid below here. */ |
229 | #ifdef __mips_embedded_pic | |
230 | #undef PICBASE | |
231 | #endif | |
03261851 RK |
232 | |
233 | /* | |
234 | * _exit -- Exit from the application. Normally we cause a user trap | |
235 | * to return to the ROM monitor for another run. NOTE: This is | |
236 | * the only other routine we provide in the crt0.o object, since | |
237 | * it may be tied to the "_start" routine. It also allows | |
238 | * executables that contain a complete world to be linked with | |
239 | * just the crt0.o object. | |
240 | */ | |
451e4528 | 241 | .globl hardware_exit_hook .text |
03261851 RK |
242 | .globl _exit |
243 | .ent _exit | |
244 | _exit: | |
245 | 7: | |
451e4528 JJ |
246 | #ifdef __mips_embedded_pic |
247 | /* Need to reinit PICBASE, since we might be called via exit() | |
248 | rather than via a return path which would restore old s0. */ | |
249 | #define PICBASE exit_PICBASE | |
250 | PICBASE = .+8 | |
251 | bal PICBASE | |
252 | nop | |
253 | move s0,$31 | |
254 | #endif | |
03261851 | 255 | #ifdef GCRT0 |
451e4528 JJ |
256 | LA (t0, _mcleanup) |
257 | jal t0 | |
03261851 RK |
258 | nop |
259 | #endif | |
451e4528 JJ |
260 | LA (t0, hardware_exit_hook) |
261 | beq t0,zero,1f | |
262 | nop | |
263 | jal t0 | |
264 | nop | |
265 | 1: | |
266 | ||
03261851 RK |
267 | # break instruction can cope with 0xfffff, but GAS limits the range: |
268 | break 1023 | |
03261851 RK |
269 | b 7b # but loop back just in-case |
270 | nop | |
271 | .end _exit | |
2d210c7f | 272 | |
451e4528 JJ |
273 | /* Assume the PICBASE set up above is no longer valid below here. */ |
274 | #ifdef __mips_embedded_pic | |
275 | #undef PICBASE | |
276 | #endif | |
277 | ||
03261851 | 278 | /* EOF crt0.S */ |