123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- /*
- * crt0-tc2x.S -- Startup code for GNU/TriCore applications.
- *
- * Copyright (C) 1998-2014 HighTec EDV-Systeme GmbH.
- *
- * This file is part of GCC.
- *
- * GCC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GCC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Under Section 7 of GPL version 3, you are granted additional
- * permissions described in the GCC Runtime Library Exception, version
- * 3.1, as published by the Free Software Foundation.
- *
- * You should have received a copy of the GNU General Public License and
- * a copy of the GCC Runtime Library Exception along with this program;
- * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- * <http://www.gnu.org/licenses/>. */
- #ifndef __TRICORE_NAME__
- #error Please define __TRICOR_NAME__
- #endif
- #if __TRICORE_CORE__ == 0x161
- CORE_ID = 0xfe1c
- SCU_WDTCPU0CON0 = 0xf0036100
- SCU_WDTCPU0CON1 = 0xf0036104
- SCU_WDTSCON0 = 0xf00360F0
- SCU_WDTSCON1 = 0xf00360F4
- #elif __TRICORE_CORE__ == 0x162
- CORE_ID = 0xfe1c
- SCU_WDTCPU0CON0 = 0xf003624C
- SCU_WDTCPU0CON1 = 0xf0036250
- SCU_WDTSCON0 = 0xf00362A8
- SCU_WDTSCON1 = 0xf00362AC
- #else
- #error unsupported TriCore core
- #endif
- /* Define the Derivate Name as a hexvalue. This value
- * is built-in defined in tricore-c.c (from tricore-devices.c)
- * the derivate number as a hexvalue (e.g. TC1796 => 0x1796
- * This name will be used in the memory.x Memory description to
- * to confirm that the crt0.o and the memory.x will be get from
- * same directory
- */
- .global __TRICORE_DERIVATE_NAME__
- .type __TRICORE_DERIVATE_NAME__,@object
- .set __TRICORE_DERIVATE_NAME__,__TRICORE_NAME__
- .section ".startup_code", "ax", @progbits
- .global _start
- .type _start,@function
- #if __TRICORE_CORE__ == 0x161
- /* default BMI header (only TC2xxx devices) */
- .word 0x00000000
- .word 0xb3590070
- .word 0x00000000
- .word 0x00000000
- .word 0x00000000
- .word 0x00000000
- .word 0x791eb864
- .word 0x86e1479b
- #endif
- _start:
- .code32
- j _startaddr
- .align 2
- _startaddr:
- mfcr %d0,CORE_ID # core ID
- and %d1,%d0,7 # CORE_ID_MASK
- sh %d2,%d1,3 # <n> * 8
- sh %d1,%d1,2 # <n> * 4
- add %d2,%d2,%d1 # offset for SCU_WDTCPUnCON0 reg = <n> * 12
- movh.a %a2,hi:SCU_WDTCPU0CON0
- lea %a2,[%a2]lo:SCU_WDTCPU0CON0
- mov.a %a7,%d2
- add.a %a7,%a2,%a7 # addr of SCU_WDTCPUnCON0
- do_endinit_cpuN:
- ld.w %d1,[%a7]0 # %d1 = *SCU_WDTCPUnCON0
- jz.t %d1,1,endinit_done_cpuN # einit is cleared, set it
- mov.aa %a4,%a7
- jl asm_set_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
- endinit_done_cpuN:
- mfcr %d0,CORE_ID # core ID
- jz %d0,do_endinit_s # Safety WDT handled by CPU0
- j init_stack_pointers
- do_endinit_s:
- movh.a %a4,hi:SCU_WDTSCON0
- lea %a4,[%a4]lo:SCU_WDTSCON0
- ld.w %d1,[%a4]0 # %d1 = *SCU_WDTSCON0
- jz.t %d1,1,endinit_done_s # einit is cleared, set it
- jl asm_set_endinit_xx # %a4 is set to SCU_WDTSCON0
- endinit_done_s:
- movh.a %a4,hi:SCU_WDTCPU0CON0
- lea %a4,[%a4]lo:SCU_WDTCPU0CON0
- jl asm_clear_endinit_xx # %a4 is set to cpu0
- init_stack_pointers:
- /*
- * initialize user and interrupt stack pointers
- */
- movh.a %sp,hi:__USTACK # load %sp
- lea %sp,[%sp]lo:__USTACK
- movh %d0,hi:__ISTACK # load $isp
- addi %d0,%d0,lo:__ISTACK
- mtcr $isp,%d0
- isync
- #; install trap handlers
- movh %d0,hi:first_trap_table #; load $btv
- addi %d0,%d0,lo:first_trap_table
- mtcr $btv,%d0
- isync
- /*
- * initialize call depth counter
- */
- mfcr %d0,$psw
- or %d0,%d0,0x7f # disable call depth counting
- andn %d0,%d0,0x80 # clear CDE bit
- mtcr $psw,%d0
- isync
- /*
- * initialize access to system global registers
- */
- mfcr %d0,$psw
- or %d0,%d0,0x100 # set GW bit
- mtcr $psw,%d0
- isync
- /*
- * initialize SDA base pointers
- */
- .global _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
- .weak _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
- movh.a %a0,hi:_SMALL_DATA_ # %a0 addresses .sdata/.sbss
- lea %a0,[%a0]lo:_SMALL_DATA_
- movh.a %a1,hi:_SMALL_DATA2_ # %a1 addresses .sdata2/.sbss2
- lea %a1,[%a1]lo:_SMALL_DATA2_
- movh.a %a8,hi:_SMALL_DATA3_ # %a8 addresses .sdata3/.sbss3
- lea %a8,[%a8]lo:_SMALL_DATA3_
- movh.a %a9,hi:_SMALL_DATA4_ # %a9 addresses .sdata4/.sbss4
- lea %a9,[%a9]lo:_SMALL_DATA4_
- /*
- * reset access to system global registers
- */
- mfcr %d0,$psw
- andn %d0,%d0,0x100 # clear GW bit
- mtcr $psw,%d0
- isync
- mov.aa %a4,%a7
- jl asm_set_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
- # disable wdt cpuN
- mov.aa %a4,%a7
- jl asm_clear_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
- ld.w %d0,[%a4]4
- or %d0,%d0,8
- st.w [%a4]4,%d0 # *SCU_WDTCPUnCON1 |= SCU_WDTCPUNCON1_DR
- jl asm_set_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
- mfcr %d0,CORE_ID # core ID
- jz %d0,disable_safety_wdt
- j jump_to_remapped
- disable_safety_wdt:
- # disable safety watchdog
- movh.a %a4,hi:SCU_WDTSCON0
- lea %a4,[%a4]lo:SCU_WDTSCON0
- jl asm_clear_endinit_xx # %a4 is set to SCU_WDTSCON0
- movh.a %a5,hi:SCU_WDTSCON1
- lea %a5,[%a5]lo:SCU_WDTSCON1
- ld.w %d0,[%a4]4
- or %d0,%d0,8
- st.w [%a4]4,%d0 # *SCU_WDTSCON1 |= SCU_WDTSCON1_DR
- jl asm_set_endinit_xx # %a4 is set to SCU_WDTSCON0
- /*
- * initialize target environment (PLLCLC, BUSCONx, ADDSELx etc)
- *
- * nothing to do here because there is no EBU
- */
- jump_to_remapped:
- #; force PC to remapped ROM address
- movh.a %a15,hi:__remapped
- lea %a15,[%a15]lo:__remapped
- nop
- ji %a15
- __remapped:
- /*
- * initialize context save areas
- */
- jl __init_csa
- /*
- * handle clear table (i.e., fill BSS with zeros)
- */
- jl __clear_table_func
- /*
- * handle copy table (support for romable code)
- */
- jl __copy_table_func
- /*
- * call the initializer, constructors etc.
- */
- call _init
- /*
- * _exit (main (0, NULL));
- */
- mov %d4,0 # argc = 0
- sub.a %sp,8
- st.w [%sp]0,%d4
- st.w [%sp]4,%d4
- mov.aa %a4,%sp # argv
- call main # int retval = main (0, NULL);
- mov %d4,%d2
- lea %sp,[%sp]8 # remove argv[0]
- mov.u %d1,0x900d # set exit code i(A14) for the simulator to
- mov %d15,%d2 # 0x900d if the exit status is 0
- movh %d3,0xffff
- or %d2,%d2,%d3
- cmov %d1,%d15,%d2
- mov.a %a14,%d1
- j _exit # _exit (retval);
- debug # should never come here
- # %a4 contains wdtcon0
- asm_clear_endinit_xx:
- ld.w %d15,[%a4]0
- andn %d4, %d15,1
- andn %d15,%d15,14
- or %d15,%d15,241
- st.w [%a4]0,%d15
- dsync
- andn %d4,%d4,12
- or %d4,%d4,242
- st.w [%a4]0,%d4
- ld.w %d15,[%a4]0 # read back new value ==> synchronise LFI
- ji %a11
- asm_set_endinit_xx:
- ld.w %d15,[%a4]0
- or %d4,%d15,1
- andn %d15,%d15,14
- or %d15,%d15,241
- st.w [%a4]0,%d15
- dsync
- andn %d4,%d4,12
- or %d4,%d4,242
- st.w [%a4]0,%d4
- ld.w %d15,[%a4]0 # read back new value ==> synchronise LFI
- ji %a11
- /*
- * initialize context save areas (CSAs), PCXI, LCX and FCX
- */
- .global __init_csa
- .type __init_csa,function
- __init_csa:
- movh %d0,0
- mtcr $pcxi,%d0
- isync
- movh %d0,hi:__CSA_BEGIN #; %d0 = begin of CSA
- addi %d0,%d0,lo:__CSA_BEGIN
- addi %d0,%d0,63 #; force alignment (2^6)
- andn %d0,%d0,63
- movh %d2,hi:__CSA_END #; %d2 = end of CSA
- addi %d2,%d2,lo:__CSA_END
- andn %d2,%d2,63 #; force alignment (2^6)
- sub %d2,%d2,%d0
- sh %d2,%d2,-6 #; %d2 = number of CSAs
- mov.a %a3,%d0 #; %a3 = address of first CSA
- extr.u %d0,%d0,28,4 #; %d0 = segment << 16
- sh %d0,%d0,16
- lea %a4,0 #; %a4 = previous CSA = 0
- st.a [%a3],%a4 #; store it in 1st CSA
- mov.aa %a4,%a3 #; %a4 = current CSA
- lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
- mov.d %d1,%a3
- extr.u %d1,%d1,6,16 #; get CSA index
- or %d1,%d1,%d0 #; add segment number
- mtcr $lcx,%d1 #; initialize LCX
- add %d2,%d2,-2 #; CSAs to initialize -= 2
- mov.a %a5,%d2 #; %a5 = loop counter
- csa_loop:
- mov.d %d1,%a4 #; %d1 = current CSA address
- extr.u %d1,%d1,6,16 #; get CSA index
- or %d1,%d1,%d0 #; add segment number
- st.w [%a3],%d1 #; store "nextCSA" pointer
- mov.aa %a4,%a3 #; %a4 = current CSA address
- lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
- loop %a5,csa_loop #; repeat until done
- mov.d %d1,%a4 #; %d1 = current CSA address
- extr.u %d1,%d1,6,16 #; get CSA index
- or %d1,%d1,%d0 #; add segment number
- mtcr $fcx,%d1 #; initialize FCX
- isync
- ji %a11
- /*
- * handle clear table (i.e., fill BSS with zeros)
- */
- .global __clear_table_func
- .type __clear_table_func,@function
- __clear_table_func:
- mov %d14,0 # %e14 = 0
- mov %d15,0
- movh.a %a13,hi:__clear_table # %a13 = &first table entry
- lea %a13,[%a13]lo:__clear_table
- __clear_table_next:
- ld.a %a15,[%a13+]4 # %a15 = current block base
- ld.w %d3,[%a13+]4 # %d3 = current block length
- jeq %d3,-1,__clear_table_done # length == -1 => end of table
- sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
- and %d1,%d3,7 # %d1 = length % 8 (rem. bytes)
- jz %d0,__clear_word # block size < 8 => clear word
- addi %d0,%d0,-1 # else doublewords -= 1
- mov.a %a2,%d0 # %a2 = loop counter
- __clear_dword:
- st.d [%a15+]8,%e14 # clear one doubleword
- loop %a2,__clear_dword
- __clear_word:
- jz %d1,__clear_table_next
- sh %d0,%d1,-2 # %d0 = length / 4 (words)
- and %d1,%d1,3 # %d1 = length % 4 (rem. bytes)
- jz %d0,__clear_hword # block size < 4 => clear hword
- st.w [%a15+]4,%d15 # clear one word
- __clear_hword:
- jz %d1,__clear_table_next
- sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
- and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
- jz %d0,__clear_byte # block size < 2 => clear byte
- st.h [%a15+]2,%d15 # clear one halfword
- __clear_byte:
- jz %d1,__clear_table_next
- st.b [%a15],%d15 # clear one byte
- j __clear_table_next # handle next clear table entry
- __clear_table_done:
- ji %a11
- /*
- * handle copy table (support for romable code)
- */
- .global __copy_table_func
- .type __copy_table_func,@function
- __copy_table_func:
- movh.a %a13,hi:__copy_table # %a13 = &first table entry
- lea %a13,[%a13]lo:__copy_table
- __copy_table_next:
- ld.a %a15,[%a13+]4 # %a15 = src address
- ld.a %a14,[%a13+]4 # %a14 = dst address
- ld.w %d3,[%a13+]4 # %d3 = block length
- jeq %d3,-1,__copy_table_done # length == -1 => end of table
- sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
- and %d1,%d3,7 # %d1 = lenght % 8 (rem. bytes)
- jz %d0,__copy_word # block size < 8 => copy word
- addi %d0,%d0,-1 # else doublewords -= 1
- mov.a %a2,%d0 # %a2 = loop counter
- __copy_dword:
- ld.d %e14,[%a15+]8 # copy one doubleword
- st.d [%a14+]8,%e14
- loop %a2,__copy_dword
- __copy_word:
- jz %d1,__copy_table_next
- sh %d0,%d1,-2 # %d0 = length / 4 (words)
- and %d1,%d1,3 # %d1 = lenght % 4 (rem. bytes)
- jz %d0,__copy_hword # block size < 4 => copy hword
- ld.w %d14,[%a15+]4 # copy one word
- st.w [%a14+]4,%d14
- __copy_hword:
- jz %d1,__copy_table_next
- sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
- and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
- jz %d0,__copy_byte # block size < 2 => copy byte
- ld.h %d14,[%a15+]2 # copy one halfword
- st.h [%a14+]2,%d14
- __copy_byte:
- jz %d1,__copy_table_next
- ld.b %d14,[%a15]0 # copy one byte
- st.b [%a14],%d14
- j __copy_table_next # handle next copy table entry
- __copy_table_done:
- ji %a11
- /*============================================================================*
- * Exception handlers (exceptions in startup code)
- *
- * This is a minimal trap vector table, which consists of eight
- * entries, each consisting of eight words (32 bytes).
- *============================================================================*/
- #; .section .traptab, "ax", @progbits
- .macro trapentry from=0, to=7
- debug
- mov.u %d14, \from << 8
- add %d14,%d14,%d15
- mov.a %a14,%d14
- addih.a %a14,%a14,0xdead
- j _exit
- 0:
- j 0b
- nop
- rfe
- .align 5
- .if \to-\from
- trapentry "(\from+1)",\to
- .endif
- .endm
- .align 8
- .global first_trap_table
- first_trap_table:
- trapentry 0, 7
|