]>
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 | |
40 | #else /* __mips_embedded_pic */ | |
41 | # define LA(t,x) la t,x | |
42 | #endif /* __mips_embedded_pic */ | |
43 | ||
44 | .comm __memsize, 12 | |
45 | .comm __lstack, STARTUP_STACK_SIZE | |
46 | .comm __stackbase,4 | |
47 | ||
48 | .text | |
49 | .align 2 | |
50 | ||
51 | /* Without the following nop, GDB thinks _start is a data variable. | |
52 | * This is probably a bug in GDB in handling a symbol that is at the | |
53 | * start of the .text section. | |
54 | */ | |
55 | nop | |
56 | ||
57 | .globl _start | |
58 | .ent _start | |
59 | _start: | |
60 | .set noreorder | |
61 | #ifdef __mips_embedded_pic | |
62 | PICBASE = .+8 | |
63 | bal PICBASE | |
64 | nop | |
65 | move s0,$31 | |
66 | #endif | |
24b1ccc6 | 67 | #if (__mips < 3) || (__mips_fpr==32) |
03261851 RK |
68 | #define STATUS_MASK (SR_CU1|SR_PE) |
69 | #else | |
70 | # For mips3 or mips4, turn on 64-bit addressing and additional float regs | |
71 | #define STATUS_MASK (SR_CU1|SR_PE|SR_FR|SR_KX|SR_SX|SR_UX) | |
72 | #endif | |
73 | li v0, STATUS_MASK | |
74 | mtc0 v0, C0_SR | |
75 | mtc0 zero, C0_CAUSE | |
76 | nop | |
77 | ||
78 | /* Check for FPU presence. Don't check if we know that soft_float is | |
79 | being used. (This also avoids illegal instruction exceptions.) */ | |
80 | ||
81 | #ifndef __mips_soft_float | |
82 | li t2,0xAAAA5555 | |
83 | mtc1 t2,fp0 /* write to FPR 0 */ | |
84 | mtc1 zero,fp1 /* write to FPR 1 */ | |
85 | mfc1 t0,fp0 | |
86 | mfc1 t1,fp1 | |
87 | nop | |
88 | bne t0,t2,1f /* check for match */ | |
89 | nop | |
90 | bne t1,zero,1f /* double check */ | |
91 | nop | |
92 | j 2f /* FPU is present. */ | |
93 | nop | |
94 | #endif | |
95 | 1: | |
96 | /* FPU is not present. Set status register to say that. */ | |
97 | li v0, (STATUS_MASK-(STATUS_MASK & SR_CU1)) | |
98 | mtc0 v0, C0_SR | |
99 | nop | |
100 | 2: | |
101 | ||
102 | ||
103 | /* Fix high bits, if any, of the PC so that exception handling | |
104 | doesn't get confused. */ | |
105 | LA (v0, 3f) | |
106 | jr v0 | |
107 | nop | |
108 | 3: | |
109 | LA (gp, _gp) # set the global data pointer | |
110 | .end _start | |
111 | ||
112 | /* | |
113 | * zero out the bss section. | |
114 | */ | |
115 | .globl __memsize | |
116 | .globl get_mem_info .text | |
117 | .globl __stack | |
118 | .globl __global | |
03261851 RK |
119 | .ent zerobss |
120 | zerobss: | |
121 | LA (v0, _fbss) | |
122 | LA (v1, _end) | |
123 | 3: | |
124 | sw zero,0(v0) | |
125 | bltu v0,v1,3b | |
126 | addiu v0,v0,4 # executed in delay slot | |
127 | ||
128 | la t0, __lstack # make a small stack so we | |
129 | addiu sp, t0, STARTUP_STACK_SIZE # can run some C code | |
130 | la a0, __memsize # get the usable memory size | |
131 | jal get_mem_info | |
132 | nop | |
133 | ||
134 | /* setup the stack pointer */ | |
135 | LA (t0, __stack) # is __stack set ? | |
136 | bne t0,zero,4f | |
137 | nop | |
138 | ||
139 | /* NOTE: a0[0] contains the amount of memory available, and | |
140 | not the last memory address. */ | |
141 | lw t0,0(a0) # last address of memory available | |
142 | la t1,K0BASE # cached kernel memory | |
143 | addu t0,t0,t1 # get the end of memory address | |
144 | /* We must subtract 24 bytes for the 3 8 byte arguments to main, in | |
145 | case main wants to write them back to the stack. The caller is | |
146 | supposed to allocate stack space for parameters in registers in | |
147 | the old MIPS ABIs. We must do this even though we aren't passing | |
148 | arguments, because main might be declared to have them. | |
149 | ||
150 | Some ports need a larger alignment for the stack, so we subtract | |
151 | 32, which satisifes the stack for the arguments and keeps the | |
152 | stack pointer better aligned. */ | |
153 | subu t0,t0,32 # and generate a starting stack-pointer | |
154 | 4: | |
155 | move sp,t0 # set stack pointer | |
156 | sw sp,__stackbase # keep this for future ref | |
157 | .end zerobss | |
158 | ||
159 | /* | |
160 | * initialize target specific stuff. Only execute these | |
161 | * functions it they exist. | |
162 | */ | |
163 | .globl hardware_init_hook .text | |
164 | .globl software_init_hook .text | |
0a7908a6 EC |
165 | .type _fini,@function |
166 | .type _init,@function | |
03261851 RK |
167 | .globl atexit .text |
168 | .globl exit .text | |
03261851 RK |
169 | .ent init |
170 | init: | |
171 | LA (t9, hardware_init_hook) # init the hardware if needed | |
172 | beq t9,zero,6f | |
173 | nop | |
174 | jal t9 | |
175 | nop | |
176 | 6: | |
177 | LA (t9, software_init_hook) # init the hardware if needed | |
178 | beq t9,zero,7f | |
179 | nop | |
180 | jal t9 | |
181 | nop | |
182 | 7: | |
0a7908a6 | 183 | LA (a0, _fini) |
03261851 RK |
184 | jal atexit |
185 | nop | |
186 | ||
187 | #ifdef GCRT0 | |
188 | .globl _ftext | |
189 | .globl _extext | |
190 | LA (a0, _ftext) | |
191 | LA (a1, _etext) | |
192 | jal monstartup | |
193 | nop | |
194 | #endif | |
195 | ||
0a7908a6 EC |
196 | jal _init # run global constructors |
197 | nop | |
198 | ||
03261851 RK |
199 | move a0,zero # set argc to 0 |
200 | jal main # call the program start function | |
201 | nop | |
202 | ||
203 | # fall through to the "exit" routine | |
204 | jal exit # call libc exit to run the G++ | |
205 | # destructors | |
206 | move a0,v0 # pass through the exit code | |
207 | .end init | |
208 | ||
209 | /* | |
210 | * _exit -- Exit from the application. Normally we cause a user trap | |
211 | * to return to the ROM monitor for another run. NOTE: This is | |
212 | * the only other routine we provide in the crt0.o object, since | |
213 | * it may be tied to the "_start" routine. It also allows | |
214 | * executables that contain a complete world to be linked with | |
215 | * just the crt0.o object. | |
216 | */ | |
217 | .globl _exit | |
218 | .ent _exit | |
219 | _exit: | |
220 | 7: | |
221 | #ifdef GCRT0 | |
222 | jal _mcleanup | |
223 | nop | |
224 | #endif | |
225 | # break instruction can cope with 0xfffff, but GAS limits the range: | |
226 | break 1023 | |
227 | nop | |
228 | b 7b # but loop back just in-case | |
229 | nop | |
230 | .end _exit | |
231 | ||
232 | /* EOF crt0.S */ |