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