master
s 335 lines 10 KB
Raw
1 /*
2 * crt0-tc2x.S -- Startup code for GNU/TriCore applications.
3 *
4 * Copyright (C) 1998-2014 HighTec EDV-Systeme GmbH.
5 *
6 * This file is part of GCC.
7 *
8 * GCC is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3, or (at your option)
11 * any later version.
12 *
13 * GCC is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * Under Section 7 of GPL version 3, you are granted additional
19 * permissions described in the GCC Runtime Library Exception, version
20 * 3.1, as published by the Free Software Foundation.
21 *
22 * You should have received a copy of the GNU General Public License and
23 * a copy of the GCC Runtime Library Exception along with this program;
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 * <http://www.gnu.org/licenses/>. */
26
27 /* Define the Derivate Name as a hexvalue. This value
28 * is built-in defined in tricore-c.c (from tricore-devices.c)
29 * the derivate number as a hexvalue (e.g. TC1796 => 0x1796
30 * This name will be used in the memory.x Memory description to
31 * to confirm that the crt0.o and the memory.x will be get from
32 * same directory
33 */
34 .section ".startup_code", "ax", @progbits
35 .global _start
36 .type _start,@function
37
38 /* default BMI header (only TC2xxx devices) */
39 .word 0x00000000
40 .word 0xb3590070
41 .word 0x00000000
42 .word 0x00000000
43 .word 0x00000000
44 .word 0x00000000
45 .word 0x791eb864
46 .word 0x86e1479b
47
48 _start:
49 .code32
50 j _startaddr
51 .align 2
52
53 _startaddr:
54 /*
55 * initialize user and interrupt stack pointers
56 */
57 movh.a %sp,hi:__USTACK # load %sp
58 lea %sp,[%sp]lo:__USTACK
59 movh %d0,hi:__ISTACK # load $isp
60 addi %d0,%d0,lo:__ISTACK
61 mtcr $isp,%d0
62 isync
63
64 #; install trap handlers
65
66 movh %d0,hi:first_trap_table #; load $btv
67 addi %d0,%d0,lo:first_trap_table
68 mtcr $btv,%d0
69 isync
70
71 /*
72 * initialize call depth counter
73 */
74
75 mfcr %d0,$psw
76 or %d0,%d0,0x7f # disable call depth counting
77 andn %d0,%d0,0x80 # clear CDE bit
78 mtcr $psw,%d0
79 isync
80
81 /*
82 * initialize access to system global registers
83 */
84
85 mfcr %d0,$psw
86 or %d0,%d0,0x100 # set GW bit
87 mtcr $psw,%d0
88 isync
89
90 /*
91 * initialize SDA base pointers
92 */
93 .global _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
94 .weak _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
95
96 movh.a %a0,hi:_SMALL_DATA_ # %a0 addresses .sdata/.sbss
97 lea %a0,[%a0]lo:_SMALL_DATA_
98 movh.a %a1,hi:_SMALL_DATA2_ # %a1 addresses .sdata2/.sbss2
99 lea %a1,[%a1]lo:_SMALL_DATA2_
100 movh.a %a8,hi:_SMALL_DATA3_ # %a8 addresses .sdata3/.sbss3
101 lea %a8,[%a8]lo:_SMALL_DATA3_
102 movh.a %a9,hi:_SMALL_DATA4_ # %a9 addresses .sdata4/.sbss4
103 lea %a9,[%a9]lo:_SMALL_DATA4_
104
105 /*
106 * reset access to system global registers
107 */
108
109 mfcr %d0,$psw
110 andn %d0,%d0,0x100 # clear GW bit
111 mtcr $psw,%d0
112 isync
113
114 /*
115 * initialize context save areas
116 */
117
118 jl __init_csa
119
120
121
122 /*
123 * handle clear table (i.e., fill BSS with zeros)
124 */
125
126 jl __clear_table_func
127
128
129 /*
130 * handle copy table (support for romable code)
131 */
132
133 jl __copy_table_func
134
135
136 /*
137 * _exit (main (0, NULL));
138 */
139 mov %d4,0 # argc = 0
140 sub.a %sp,8
141 st.w [%sp]0,%d4
142 st.w [%sp]4,%d4
143 mov.aa %a4,%sp # argv
144
145 call main # int retval = main (0, NULL);
146 mov.a %a14,%d2 # move exit code to match trap handler
147 j _exit # _exit (retval);
148
149 debug # should never come here
150
151
152 /*
153 * initialize context save areas (CSAs), PCXI, LCX and FCX
154 */
155
156 .global __init_csa
157 .type __init_csa,function
158
159 __init_csa:
160 movh %d0,0
161 mtcr $pcxi,%d0
162 isync
163 movh %d0,hi:__CSA_BEGIN #; %d0 = begin of CSA
164 addi %d0,%d0,lo:__CSA_BEGIN
165 addi %d0,%d0,63 #; force alignment (2^6)
166 andn %d0,%d0,63
167 movh %d2,hi:__CSA_END #; %d2 = end of CSA
168 addi %d2,%d2,lo:__CSA_END
169 andn %d2,%d2,63 #; force alignment (2^6)
170 sub %d2,%d2,%d0
171 sh %d2,%d2,-6 #; %d2 = number of CSAs
172 mov.a %a3,%d0 #; %a3 = address of first CSA
173 extr.u %d0,%d0,28,4 #; %d0 = segment << 16
174 sh %d0,%d0,16
175 lea %a4,0 #; %a4 = previous CSA = 0
176 st.a [%a3],%a4 #; store it in 1st CSA
177 mov.aa %a4,%a3 #; %a4 = current CSA
178 lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
179 mov.d %d1,%a3
180 extr.u %d1,%d1,6,16 #; get CSA index
181 or %d1,%d1,%d0 #; add segment number
182 mtcr $lcx,%d1 #; initialize LCX
183 add %d2,%d2,-2 #; CSAs to initialize -= 2
184 mov.a %a5,%d2 #; %a5 = loop counter
185 csa_loop:
186 mov.d %d1,%a4 #; %d1 = current CSA address
187 extr.u %d1,%d1,6,16 #; get CSA index
188 or %d1,%d1,%d0 #; add segment number
189 st.w [%a3],%d1 #; store "nextCSA" pointer
190 mov.aa %a4,%a3 #; %a4 = current CSA address
191 lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
192 loop %a5,csa_loop #; repeat until done
193
194 mov.d %d1,%a4 #; %d1 = current CSA address
195 extr.u %d1,%d1,6,16 #; get CSA index
196 or %d1,%d1,%d0 #; add segment number
197 mtcr $fcx,%d1 #; initialize FCX
198 isync
199 ji %a11
200
201
202
203
204 /*
205 * handle clear table (i.e., fill BSS with zeros)
206 */
207 .global __clear_table_func
208 .type __clear_table_func,@function
209
210 __clear_table_func:
211 mov %d14,0 # %e14 = 0
212 mov %d15,0
213 movh.a %a13,hi:__clear_table # %a13 = &first table entry
214 lea %a13,[%a13]lo:__clear_table
215
216 __clear_table_next:
217 ld.a %a15,[%a13+]4 # %a15 = current block base
218 ld.w %d3,[%a13+]4 # %d3 = current block length
219 jeq %d3,-1,__clear_table_done # length == -1 => end of table
220 sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
221 and %d1,%d3,7 # %d1 = length % 8 (rem. bytes)
222 jz %d0,__clear_word # block size < 8 => clear word
223 addi %d0,%d0,-1 # else doublewords -= 1
224 mov.a %a2,%d0 # %a2 = loop counter
225 __clear_dword:
226 st.d [%a15+]8,%e14 # clear one doubleword
227 loop %a2,__clear_dword
228 __clear_word:
229 jz %d1,__clear_table_next
230 sh %d0,%d1,-2 # %d0 = length / 4 (words)
231 and %d1,%d1,3 # %d1 = length % 4 (rem. bytes)
232 jz %d0,__clear_hword # block size < 4 => clear hword
233 st.w [%a15+]4,%d15 # clear one word
234 __clear_hword:
235 jz %d1,__clear_table_next
236 sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
237 and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
238 jz %d0,__clear_byte # block size < 2 => clear byte
239 st.h [%a15+]2,%d15 # clear one halfword
240 __clear_byte:
241 jz %d1,__clear_table_next
242 st.b [%a15],%d15 # clear one byte
243 j __clear_table_next # handle next clear table entry
244 __clear_table_done:
245
246 ji %a11
247
248
249
250 /*
251 * handle copy table (support for romable code)
252 */
253 .global __copy_table_func
254 .type __copy_table_func,@function
255
256 __copy_table_func:
257 movh.a %a13,hi:__copy_table # %a13 = &first table entry
258 lea %a13,[%a13]lo:__copy_table
259
260 __copy_table_next:
261 ld.a %a15,[%a13+]4 # %a15 = src address
262 ld.a %a14,[%a13+]4 # %a14 = dst address
263 ld.w %d3,[%a13+]4 # %d3 = block length
264 jeq %d3,-1,__copy_table_done # length == -1 => end of table
265 sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
266 and %d1,%d3,7 # %d1 = length % 8 (rem. bytes)
267 jz %d0,__copy_word # block size < 8 => copy word
268 addi %d0,%d0,-1 # else doublewords -= 1
269 mov.a %a2,%d0 # %a2 = loop counter
270 __copy_dword:
271 ld.d %e14,[%a15+]8 # copy one doubleword
272 st.d [%a14+]8,%e14
273 loop %a2,__copy_dword
274 __copy_word:
275 jz %d1,__copy_table_next
276 sh %d0,%d1,-2 # %d0 = length / 4 (words)
277 and %d1,%d1,3 # %d1 = length % 4 (rem. bytes)
278 jz %d0,__copy_hword # block size < 4 => copy hword
279 ld.w %d14,[%a15+]4 # copy one word
280 st.w [%a14+]4,%d14
281 __copy_hword:
282 jz %d1,__copy_table_next
283 sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
284 and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
285 jz %d0,__copy_byte # block size < 2 => copy byte
286 ld.h %d14,[%a15+]2 # copy one halfword
287 st.h [%a14+]2,%d14
288 __copy_byte:
289 jz %d1,__copy_table_next
290 ld.b %d14,[%a15]0 # copy one byte
291 st.b [%a14],%d14
292 j __copy_table_next # handle next copy table entry
293 __copy_table_done:
294
295 ji %a11
296
297 _exit:
298 movh.a %a15, hi:__TESTDEVICE
299 lea %a15,[%a15]lo:__TESTDEVICE
300 mov.d %d2, %a14
301 st.w [%a15], %d2 # write exit code to testdevice
302 debug
303
304 /*============================================================================*
305 * Exception handlers (exceptions in startup code)
306 *
307 * This is a minimal trap vector table, which consists of eight
308 * entries, each consisting of eight words (32 bytes).
309 *============================================================================*/
310
311
312 #; .section .traptab, "ax", @progbits
313
314 .macro trapentry from=0, to=7
315 mov.u %d14, \from << 8
316 add %d14,%d14,%d15
317 mov.a %a14,%d14
318 addih.a %a14,%a14,0 # if we trap, we fail
319 j _exit
320 0:
321 j 0b
322 nop
323 rfe
324 .align 5
325
326 .if \to-\from
327 trapentry "(\from+1)",\to
328 .endif
329 .endm
330
331 .align 8
332 .global first_trap_table
333 first_trap_table:
334 trapentry 0, 7
335