xref: /qemu/tests/tcg/tricore/c/crt0-tc2x.S (revision 6e0dc9d2)
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
185csa_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
3200:
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
333first_trap_table:
334    trapentry 0, 7
335
336