10e45f7beSBastian Koppelmann/* 20e45f7beSBastian Koppelmann * crt0-tc2x.S -- Startup code for GNU/TriCore applications. 30e45f7beSBastian Koppelmann * 40e45f7beSBastian Koppelmann * Copyright (C) 1998-2014 HighTec EDV-Systeme GmbH. 50e45f7beSBastian Koppelmann * 60e45f7beSBastian Koppelmann * This file is part of GCC. 70e45f7beSBastian Koppelmann * 80e45f7beSBastian Koppelmann * GCC is free software; you can redistribute it and/or modify 90e45f7beSBastian Koppelmann * it under the terms of the GNU General Public License as published by 100e45f7beSBastian Koppelmann * the Free Software Foundation; either version 3, or (at your option) 110e45f7beSBastian Koppelmann * any later version. 120e45f7beSBastian Koppelmann * 130e45f7beSBastian Koppelmann * GCC is distributed in the hope that it will be useful, 140e45f7beSBastian Koppelmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 150e45f7beSBastian Koppelmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 160e45f7beSBastian Koppelmann * GNU General Public License for more details. 170e45f7beSBastian Koppelmann * 180e45f7beSBastian Koppelmann * Under Section 7 of GPL version 3, you are granted additional 190e45f7beSBastian Koppelmann * permissions described in the GCC Runtime Library Exception, version 200e45f7beSBastian Koppelmann * 3.1, as published by the Free Software Foundation. 210e45f7beSBastian Koppelmann * 220e45f7beSBastian Koppelmann * You should have received a copy of the GNU General Public License and 230e45f7beSBastian Koppelmann * a copy of the GCC Runtime Library Exception along with this program; 240e45f7beSBastian Koppelmann * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 250e45f7beSBastian Koppelmann * <http://www.gnu.org/licenses/>. */ 260e45f7beSBastian Koppelmann 270e45f7beSBastian Koppelmann/* Define the Derivate Name as a hexvalue. This value 280e45f7beSBastian Koppelmann * is built-in defined in tricore-c.c (from tricore-devices.c) 290e45f7beSBastian Koppelmann * the derivate number as a hexvalue (e.g. TC1796 => 0x1796 300e45f7beSBastian Koppelmann * This name will be used in the memory.x Memory description to 310e45f7beSBastian Koppelmann * to confirm that the crt0.o and the memory.x will be get from 320e45f7beSBastian Koppelmann * same directory 330e45f7beSBastian Koppelmann */ 340e45f7beSBastian Koppelmann .section ".startup_code", "ax", @progbits 350e45f7beSBastian Koppelmann .global _start 360e45f7beSBastian Koppelmann .type _start,@function 370e45f7beSBastian Koppelmann 380e45f7beSBastian Koppelmann/* default BMI header (only TC2xxx devices) */ 390e45f7beSBastian Koppelmann .word 0x00000000 400e45f7beSBastian Koppelmann .word 0xb3590070 410e45f7beSBastian Koppelmann .word 0x00000000 420e45f7beSBastian Koppelmann .word 0x00000000 430e45f7beSBastian Koppelmann .word 0x00000000 440e45f7beSBastian Koppelmann .word 0x00000000 450e45f7beSBastian Koppelmann .word 0x791eb864 460e45f7beSBastian Koppelmann .word 0x86e1479b 470e45f7beSBastian Koppelmann 480e45f7beSBastian Koppelmann_start: 490e45f7beSBastian Koppelmann .code32 500e45f7beSBastian Koppelmann j _startaddr 510e45f7beSBastian Koppelmann .align 2 520e45f7beSBastian Koppelmann 530e45f7beSBastian Koppelmann_startaddr: 540e45f7beSBastian Koppelmann /* 550e45f7beSBastian Koppelmann * initialize user and interrupt stack pointers 560e45f7beSBastian Koppelmann */ 570e45f7beSBastian Koppelmann movh.a %sp,hi:__USTACK # load %sp 580e45f7beSBastian Koppelmann lea %sp,[%sp]lo:__USTACK 590e45f7beSBastian Koppelmann movh %d0,hi:__ISTACK # load $isp 600e45f7beSBastian Koppelmann addi %d0,%d0,lo:__ISTACK 610e45f7beSBastian Koppelmann mtcr $isp,%d0 620e45f7beSBastian Koppelmann isync 630e45f7beSBastian Koppelmann 640e45f7beSBastian Koppelmann#; install trap handlers 650e45f7beSBastian Koppelmann 660e45f7beSBastian Koppelmann movh %d0,hi:first_trap_table #; load $btv 670e45f7beSBastian Koppelmann addi %d0,%d0,lo:first_trap_table 680e45f7beSBastian Koppelmann mtcr $btv,%d0 690e45f7beSBastian Koppelmann isync 700e45f7beSBastian Koppelmann 710e45f7beSBastian Koppelmann /* 720e45f7beSBastian Koppelmann * initialize call depth counter 730e45f7beSBastian Koppelmann */ 740e45f7beSBastian Koppelmann 750e45f7beSBastian Koppelmann mfcr %d0,$psw 760e45f7beSBastian Koppelmann or %d0,%d0,0x7f # disable call depth counting 770e45f7beSBastian Koppelmann andn %d0,%d0,0x80 # clear CDE bit 780e45f7beSBastian Koppelmann mtcr $psw,%d0 790e45f7beSBastian Koppelmann isync 800e45f7beSBastian Koppelmann 810e45f7beSBastian Koppelmann /* 820e45f7beSBastian Koppelmann * initialize access to system global registers 830e45f7beSBastian Koppelmann */ 840e45f7beSBastian Koppelmann 850e45f7beSBastian Koppelmann mfcr %d0,$psw 860e45f7beSBastian Koppelmann or %d0,%d0,0x100 # set GW bit 870e45f7beSBastian Koppelmann mtcr $psw,%d0 880e45f7beSBastian Koppelmann isync 890e45f7beSBastian Koppelmann 900e45f7beSBastian Koppelmann /* 910e45f7beSBastian Koppelmann * initialize SDA base pointers 920e45f7beSBastian Koppelmann */ 930e45f7beSBastian Koppelmann .global _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_ 940e45f7beSBastian Koppelmann .weak _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_ 950e45f7beSBastian Koppelmann 960e45f7beSBastian Koppelmann movh.a %a0,hi:_SMALL_DATA_ # %a0 addresses .sdata/.sbss 970e45f7beSBastian Koppelmann lea %a0,[%a0]lo:_SMALL_DATA_ 980e45f7beSBastian Koppelmann movh.a %a1,hi:_SMALL_DATA2_ # %a1 addresses .sdata2/.sbss2 990e45f7beSBastian Koppelmann lea %a1,[%a1]lo:_SMALL_DATA2_ 1000e45f7beSBastian Koppelmann movh.a %a8,hi:_SMALL_DATA3_ # %a8 addresses .sdata3/.sbss3 1010e45f7beSBastian Koppelmann lea %a8,[%a8]lo:_SMALL_DATA3_ 1020e45f7beSBastian Koppelmann movh.a %a9,hi:_SMALL_DATA4_ # %a9 addresses .sdata4/.sbss4 1030e45f7beSBastian Koppelmann lea %a9,[%a9]lo:_SMALL_DATA4_ 1040e45f7beSBastian Koppelmann 1050e45f7beSBastian Koppelmann /* 1060e45f7beSBastian Koppelmann * reset access to system global registers 1070e45f7beSBastian Koppelmann */ 1080e45f7beSBastian Koppelmann 1090e45f7beSBastian Koppelmann mfcr %d0,$psw 1100e45f7beSBastian Koppelmann andn %d0,%d0,0x100 # clear GW bit 1110e45f7beSBastian Koppelmann mtcr $psw,%d0 1120e45f7beSBastian Koppelmann isync 1130e45f7beSBastian Koppelmann 1140e45f7beSBastian Koppelmann /* 1150e45f7beSBastian Koppelmann * initialize context save areas 1160e45f7beSBastian Koppelmann */ 1170e45f7beSBastian Koppelmann 1180e45f7beSBastian Koppelmann jl __init_csa 1190e45f7beSBastian Koppelmann 1200e45f7beSBastian Koppelmann 1210e45f7beSBastian Koppelmann 1220e45f7beSBastian Koppelmann /* 1230e45f7beSBastian Koppelmann * handle clear table (i.e., fill BSS with zeros) 1240e45f7beSBastian Koppelmann */ 1250e45f7beSBastian Koppelmann 1260e45f7beSBastian Koppelmann jl __clear_table_func 1270e45f7beSBastian Koppelmann 1280e45f7beSBastian Koppelmann 1290e45f7beSBastian Koppelmann /* 1300e45f7beSBastian Koppelmann * handle copy table (support for romable code) 1310e45f7beSBastian Koppelmann */ 1320e45f7beSBastian Koppelmann 1330e45f7beSBastian Koppelmann jl __copy_table_func 1340e45f7beSBastian Koppelmann 1350e45f7beSBastian Koppelmann 1360e45f7beSBastian Koppelmann /* 1370e45f7beSBastian Koppelmann * _exit (main (0, NULL)); 1380e45f7beSBastian Koppelmann */ 1390e45f7beSBastian Koppelmann mov %d4,0 # argc = 0 1400e45f7beSBastian Koppelmann sub.a %sp,8 1410e45f7beSBastian Koppelmann st.w [%sp]0,%d4 1420e45f7beSBastian Koppelmann st.w [%sp]4,%d4 1430e45f7beSBastian Koppelmann mov.aa %a4,%sp # argv 1440e45f7beSBastian Koppelmann 1450e45f7beSBastian Koppelmann call main # int retval = main (0, NULL); 1460e45f7beSBastian Koppelmann mov.a %a14,%d2 # move exit code to match trap handler 1470e45f7beSBastian Koppelmann j _exit # _exit (retval); 1480e45f7beSBastian Koppelmann 1490e45f7beSBastian Koppelmann debug # should never come here 1500e45f7beSBastian Koppelmann 1510e45f7beSBastian Koppelmann 1520e45f7beSBastian Koppelmann /* 1530e45f7beSBastian Koppelmann * initialize context save areas (CSAs), PCXI, LCX and FCX 1540e45f7beSBastian Koppelmann */ 1550e45f7beSBastian Koppelmann 1560e45f7beSBastian Koppelmann .global __init_csa 1570e45f7beSBastian Koppelmann .type __init_csa,function 1580e45f7beSBastian Koppelmann 1590e45f7beSBastian Koppelmann__init_csa: 1600e45f7beSBastian Koppelmann movh %d0,0 1610e45f7beSBastian Koppelmann mtcr $pcxi,%d0 1620e45f7beSBastian Koppelmann isync 1630e45f7beSBastian Koppelmann movh %d0,hi:__CSA_BEGIN #; %d0 = begin of CSA 1640e45f7beSBastian Koppelmann addi %d0,%d0,lo:__CSA_BEGIN 1650e45f7beSBastian Koppelmann addi %d0,%d0,63 #; force alignment (2^6) 1660e45f7beSBastian Koppelmann andn %d0,%d0,63 1670e45f7beSBastian Koppelmann movh %d2,hi:__CSA_END #; %d2 = end of CSA 1680e45f7beSBastian Koppelmann addi %d2,%d2,lo:__CSA_END 1690e45f7beSBastian Koppelmann andn %d2,%d2,63 #; force alignment (2^6) 1700e45f7beSBastian Koppelmann sub %d2,%d2,%d0 1710e45f7beSBastian Koppelmann sh %d2,%d2,-6 #; %d2 = number of CSAs 1720e45f7beSBastian Koppelmann mov.a %a3,%d0 #; %a3 = address of first CSA 1730e45f7beSBastian Koppelmann extr.u %d0,%d0,28,4 #; %d0 = segment << 16 1740e45f7beSBastian Koppelmann sh %d0,%d0,16 1750e45f7beSBastian Koppelmann lea %a4,0 #; %a4 = previous CSA = 0 1760e45f7beSBastian Koppelmann st.a [%a3],%a4 #; store it in 1st CSA 1770e45f7beSBastian Koppelmann mov.aa %a4,%a3 #; %a4 = current CSA 1780e45f7beSBastian Koppelmann lea %a3,[%a3]64 #; %a3 = %a3->nextCSA 1790e45f7beSBastian Koppelmann mov.d %d1,%a3 1800e45f7beSBastian Koppelmann extr.u %d1,%d1,6,16 #; get CSA index 1810e45f7beSBastian Koppelmann or %d1,%d1,%d0 #; add segment number 1820e45f7beSBastian Koppelmann mtcr $lcx,%d1 #; initialize LCX 1830e45f7beSBastian Koppelmann add %d2,%d2,-2 #; CSAs to initialize -= 2 1840e45f7beSBastian Koppelmann mov.a %a5,%d2 #; %a5 = loop counter 1850e45f7beSBastian Koppelmanncsa_loop: 1860e45f7beSBastian Koppelmann mov.d %d1,%a4 #; %d1 = current CSA address 1870e45f7beSBastian Koppelmann extr.u %d1,%d1,6,16 #; get CSA index 1880e45f7beSBastian Koppelmann or %d1,%d1,%d0 #; add segment number 1890e45f7beSBastian Koppelmann st.w [%a3],%d1 #; store "nextCSA" pointer 1900e45f7beSBastian Koppelmann mov.aa %a4,%a3 #; %a4 = current CSA address 1910e45f7beSBastian Koppelmann lea %a3,[%a3]64 #; %a3 = %a3->nextCSA 1920e45f7beSBastian Koppelmann loop %a5,csa_loop #; repeat until done 1930e45f7beSBastian Koppelmann 1940e45f7beSBastian Koppelmann mov.d %d1,%a4 #; %d1 = current CSA address 1950e45f7beSBastian Koppelmann extr.u %d1,%d1,6,16 #; get CSA index 1960e45f7beSBastian Koppelmann or %d1,%d1,%d0 #; add segment number 1970e45f7beSBastian Koppelmann mtcr $fcx,%d1 #; initialize FCX 1980e45f7beSBastian Koppelmann isync 1990e45f7beSBastian Koppelmann ji %a11 2000e45f7beSBastian Koppelmann 2010e45f7beSBastian Koppelmann 2020e45f7beSBastian Koppelmann 2030e45f7beSBastian Koppelmann 2040e45f7beSBastian Koppelmann /* 2050e45f7beSBastian Koppelmann * handle clear table (i.e., fill BSS with zeros) 2060e45f7beSBastian Koppelmann */ 2070e45f7beSBastian Koppelmann .global __clear_table_func 2080e45f7beSBastian Koppelmann .type __clear_table_func,@function 2090e45f7beSBastian Koppelmann 2100e45f7beSBastian Koppelmann__clear_table_func: 2110e45f7beSBastian Koppelmann mov %d14,0 # %e14 = 0 2120e45f7beSBastian Koppelmann mov %d15,0 2130e45f7beSBastian Koppelmann movh.a %a13,hi:__clear_table # %a13 = &first table entry 2140e45f7beSBastian Koppelmann lea %a13,[%a13]lo:__clear_table 2150e45f7beSBastian Koppelmann 2160e45f7beSBastian Koppelmann__clear_table_next: 2170e45f7beSBastian Koppelmann ld.a %a15,[%a13+]4 # %a15 = current block base 2180e45f7beSBastian Koppelmann ld.w %d3,[%a13+]4 # %d3 = current block length 2190e45f7beSBastian Koppelmann jeq %d3,-1,__clear_table_done # length == -1 => end of table 2200e45f7beSBastian Koppelmann sh %d0,%d3,-3 # %d0 = length / 8 (doublewords) 2210e45f7beSBastian Koppelmann and %d1,%d3,7 # %d1 = length % 8 (rem. bytes) 2220e45f7beSBastian Koppelmann jz %d0,__clear_word # block size < 8 => clear word 2230e45f7beSBastian Koppelmann addi %d0,%d0,-1 # else doublewords -= 1 2240e45f7beSBastian Koppelmann mov.a %a2,%d0 # %a2 = loop counter 2250e45f7beSBastian Koppelmann__clear_dword: 2260e45f7beSBastian Koppelmann st.d [%a15+]8,%e14 # clear one doubleword 2270e45f7beSBastian Koppelmann loop %a2,__clear_dword 2280e45f7beSBastian Koppelmann__clear_word: 2290e45f7beSBastian Koppelmann jz %d1,__clear_table_next 2300e45f7beSBastian Koppelmann sh %d0,%d1,-2 # %d0 = length / 4 (words) 2310e45f7beSBastian Koppelmann and %d1,%d1,3 # %d1 = length % 4 (rem. bytes) 2320e45f7beSBastian Koppelmann jz %d0,__clear_hword # block size < 4 => clear hword 2330e45f7beSBastian Koppelmann st.w [%a15+]4,%d15 # clear one word 2340e45f7beSBastian Koppelmann__clear_hword: 2350e45f7beSBastian Koppelmann jz %d1,__clear_table_next 2360e45f7beSBastian Koppelmann sh %d0,%d1,-1 # %d0 = length / 2 (halfwords) 2370e45f7beSBastian Koppelmann and %d1,%d1,1 # %d1 = length % 2 (rem. bytes) 2380e45f7beSBastian Koppelmann jz %d0,__clear_byte # block size < 2 => clear byte 2390e45f7beSBastian Koppelmann st.h [%a15+]2,%d15 # clear one halfword 2400e45f7beSBastian Koppelmann__clear_byte: 2410e45f7beSBastian Koppelmann jz %d1,__clear_table_next 2420e45f7beSBastian Koppelmann st.b [%a15],%d15 # clear one byte 2430e45f7beSBastian Koppelmann j __clear_table_next # handle next clear table entry 2440e45f7beSBastian Koppelmann__clear_table_done: 2450e45f7beSBastian Koppelmann 2460e45f7beSBastian Koppelmann ji %a11 2470e45f7beSBastian Koppelmann 2480e45f7beSBastian Koppelmann 2490e45f7beSBastian Koppelmann 2500e45f7beSBastian Koppelmann /* 2510e45f7beSBastian Koppelmann * handle copy table (support for romable code) 2520e45f7beSBastian Koppelmann */ 2530e45f7beSBastian Koppelmann .global __copy_table_func 2540e45f7beSBastian Koppelmann .type __copy_table_func,@function 2550e45f7beSBastian Koppelmann 2560e45f7beSBastian Koppelmann__copy_table_func: 2570e45f7beSBastian Koppelmann movh.a %a13,hi:__copy_table # %a13 = &first table entry 2580e45f7beSBastian Koppelmann lea %a13,[%a13]lo:__copy_table 2590e45f7beSBastian Koppelmann 2600e45f7beSBastian Koppelmann__copy_table_next: 2610e45f7beSBastian Koppelmann ld.a %a15,[%a13+]4 # %a15 = src address 2620e45f7beSBastian Koppelmann ld.a %a14,[%a13+]4 # %a14 = dst address 2630e45f7beSBastian Koppelmann ld.w %d3,[%a13+]4 # %d3 = block length 2640e45f7beSBastian Koppelmann jeq %d3,-1,__copy_table_done # length == -1 => end of table 2650e45f7beSBastian Koppelmann sh %d0,%d3,-3 # %d0 = length / 8 (doublewords) 266*8b81968cSMichael Tokarev and %d1,%d3,7 # %d1 = length % 8 (rem. bytes) 2670e45f7beSBastian Koppelmann jz %d0,__copy_word # block size < 8 => copy word 2680e45f7beSBastian Koppelmann addi %d0,%d0,-1 # else doublewords -= 1 2690e45f7beSBastian Koppelmann mov.a %a2,%d0 # %a2 = loop counter 2700e45f7beSBastian Koppelmann__copy_dword: 2710e45f7beSBastian Koppelmann ld.d %e14,[%a15+]8 # copy one doubleword 2720e45f7beSBastian Koppelmann st.d [%a14+]8,%e14 2730e45f7beSBastian Koppelmann loop %a2,__copy_dword 2740e45f7beSBastian Koppelmann__copy_word: 2750e45f7beSBastian Koppelmann jz %d1,__copy_table_next 2760e45f7beSBastian Koppelmann sh %d0,%d1,-2 # %d0 = length / 4 (words) 277*8b81968cSMichael Tokarev and %d1,%d1,3 # %d1 = length % 4 (rem. bytes) 2780e45f7beSBastian Koppelmann jz %d0,__copy_hword # block size < 4 => copy hword 2790e45f7beSBastian Koppelmann ld.w %d14,[%a15+]4 # copy one word 2800e45f7beSBastian Koppelmann st.w [%a14+]4,%d14 2810e45f7beSBastian Koppelmann__copy_hword: 2820e45f7beSBastian Koppelmann jz %d1,__copy_table_next 2830e45f7beSBastian Koppelmann sh %d0,%d1,-1 # %d0 = length / 2 (halfwords) 2840e45f7beSBastian Koppelmann and %d1,%d1,1 # %d1 = length % 2 (rem. bytes) 2850e45f7beSBastian Koppelmann jz %d0,__copy_byte # block size < 2 => copy byte 2860e45f7beSBastian Koppelmann ld.h %d14,[%a15+]2 # copy one halfword 2870e45f7beSBastian Koppelmann st.h [%a14+]2,%d14 2880e45f7beSBastian Koppelmann__copy_byte: 2890e45f7beSBastian Koppelmann jz %d1,__copy_table_next 2900e45f7beSBastian Koppelmann ld.b %d14,[%a15]0 # copy one byte 2910e45f7beSBastian Koppelmann st.b [%a14],%d14 2920e45f7beSBastian Koppelmann j __copy_table_next # handle next copy table entry 2930e45f7beSBastian Koppelmann__copy_table_done: 2940e45f7beSBastian Koppelmann 2950e45f7beSBastian Koppelmann ji %a11 2960e45f7beSBastian Koppelmann 2970e45f7beSBastian Koppelmann_exit: 2980e45f7beSBastian Koppelmann movh.a %a15, hi:__TESTDEVICE 2990e45f7beSBastian Koppelmann lea %a15,[%a15]lo:__TESTDEVICE 3000e45f7beSBastian Koppelmann mov.d %d2, %a14 3010e45f7beSBastian Koppelmann st.w [%a15], %d2 # write exit code to testdevice 3020e45f7beSBastian Koppelmann debug 3030e45f7beSBastian Koppelmann 3040e45f7beSBastian Koppelmann/*============================================================================* 3050e45f7beSBastian Koppelmann * Exception handlers (exceptions in startup code) 3060e45f7beSBastian Koppelmann * 3070e45f7beSBastian Koppelmann * This is a minimal trap vector table, which consists of eight 3080e45f7beSBastian Koppelmann * entries, each consisting of eight words (32 bytes). 3090e45f7beSBastian Koppelmann *============================================================================*/ 3100e45f7beSBastian Koppelmann 3110e45f7beSBastian Koppelmann 3120e45f7beSBastian Koppelmann#; .section .traptab, "ax", @progbits 3130e45f7beSBastian Koppelmann 3140e45f7beSBastian Koppelmann.macro trapentry from=0, to=7 3150e45f7beSBastian Koppelmann mov.u %d14, \from << 8 3160e45f7beSBastian Koppelmann add %d14,%d14,%d15 3170e45f7beSBastian Koppelmann mov.a %a14,%d14 3180e45f7beSBastian Koppelmann addih.a %a14,%a14,0 # if we trap, we fail 3190e45f7beSBastian Koppelmann j _exit 3200e45f7beSBastian Koppelmann0: 3210e45f7beSBastian Koppelmann j 0b 3220e45f7beSBastian Koppelmann nop 3230e45f7beSBastian Koppelmann rfe 3240e45f7beSBastian Koppelmann .align 5 3250e45f7beSBastian Koppelmann 3260e45f7beSBastian Koppelmann .if \to-\from 3270e45f7beSBastian Koppelmann trapentry "(\from+1)",\to 3280e45f7beSBastian Koppelmann .endif 3290e45f7beSBastian Koppelmann.endm 3300e45f7beSBastian Koppelmann 3310e45f7beSBastian Koppelmann .align 8 3320e45f7beSBastian Koppelmann .global first_trap_table 3330e45f7beSBastian Koppelmannfirst_trap_table: 3340e45f7beSBastian Koppelmann trapentry 0, 7 3350e45f7beSBastian Koppelmann 336