crt0-tc2x.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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. #ifndef __TRICORE_NAME__
  27. #error Please define __TRICOR_NAME__
  28. #endif
  29. #if __TRICORE_CORE__ == 0x161
  30. CORE_ID = 0xfe1c
  31. SCU_WDTCPU0CON0 = 0xf0036100
  32. SCU_WDTCPU0CON1 = 0xf0036104
  33. SCU_WDTSCON0 = 0xf00360F0
  34. SCU_WDTSCON1 = 0xf00360F4
  35. #elif __TRICORE_CORE__ == 0x162
  36. CORE_ID = 0xfe1c
  37. SCU_WDTCPU0CON0 = 0xf003624C
  38. SCU_WDTCPU0CON1 = 0xf0036250
  39. SCU_WDTSCON0 = 0xf00362A8
  40. SCU_WDTSCON1 = 0xf00362AC
  41. #else
  42. #error unsupported TriCore core
  43. #endif
  44. /* Define the Derivate Name as a hexvalue. This value
  45. * is built-in defined in tricore-c.c (from tricore-devices.c)
  46. * the derivate number as a hexvalue (e.g. TC1796 => 0x1796
  47. * This name will be used in the memory.x Memory description to
  48. * to confirm that the crt0.o and the memory.x will be get from
  49. * same directory
  50. */
  51. .global __TRICORE_DERIVATE_NAME__
  52. .type __TRICORE_DERIVATE_NAME__,@object
  53. .set __TRICORE_DERIVATE_NAME__,__TRICORE_NAME__
  54. .section ".startup_code", "ax", @progbits
  55. .global _start
  56. .type _start,@function
  57. #if __TRICORE_CORE__ == 0x161
  58. /* default BMI header (only TC2xxx devices) */
  59. .word 0x00000000
  60. .word 0xb3590070
  61. .word 0x00000000
  62. .word 0x00000000
  63. .word 0x00000000
  64. .word 0x00000000
  65. .word 0x791eb864
  66. .word 0x86e1479b
  67. #endif
  68. _start:
  69. .code32
  70. j _startaddr
  71. .align 2
  72. _startaddr:
  73. mfcr %d0,CORE_ID # core ID
  74. and %d1,%d0,7 # CORE_ID_MASK
  75. sh %d2,%d1,3 # <n> * 8
  76. sh %d1,%d1,2 # <n> * 4
  77. add %d2,%d2,%d1 # offset for SCU_WDTCPUnCON0 reg = <n> * 12
  78. movh.a %a2,hi:SCU_WDTCPU0CON0
  79. lea %a2,[%a2]lo:SCU_WDTCPU0CON0
  80. mov.a %a7,%d2
  81. add.a %a7,%a2,%a7 # addr of SCU_WDTCPUnCON0
  82. do_endinit_cpuN:
  83. ld.w %d1,[%a7]0 # %d1 = *SCU_WDTCPUnCON0
  84. jz.t %d1,1,endinit_done_cpuN # einit is cleared, set it
  85. mov.aa %a4,%a7
  86. jl asm_set_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
  87. endinit_done_cpuN:
  88. mfcr %d0,CORE_ID # core ID
  89. jz %d0,do_endinit_s # Safety WDT handled by CPU0
  90. j init_stack_pointers
  91. do_endinit_s:
  92. movh.a %a4,hi:SCU_WDTSCON0
  93. lea %a4,[%a4]lo:SCU_WDTSCON0
  94. ld.w %d1,[%a4]0 # %d1 = *SCU_WDTSCON0
  95. jz.t %d1,1,endinit_done_s # einit is cleared, set it
  96. jl asm_set_endinit_xx # %a4 is set to SCU_WDTSCON0
  97. endinit_done_s:
  98. movh.a %a4,hi:SCU_WDTCPU0CON0
  99. lea %a4,[%a4]lo:SCU_WDTCPU0CON0
  100. jl asm_clear_endinit_xx # %a4 is set to cpu0
  101. init_stack_pointers:
  102. /*
  103. * initialize user and interrupt stack pointers
  104. */
  105. movh.a %sp,hi:__USTACK # load %sp
  106. lea %sp,[%sp]lo:__USTACK
  107. movh %d0,hi:__ISTACK # load $isp
  108. addi %d0,%d0,lo:__ISTACK
  109. mtcr $isp,%d0
  110. isync
  111. #; install trap handlers
  112. movh %d0,hi:first_trap_table #; load $btv
  113. addi %d0,%d0,lo:first_trap_table
  114. mtcr $btv,%d0
  115. isync
  116. /*
  117. * initialize call depth counter
  118. */
  119. mfcr %d0,$psw
  120. or %d0,%d0,0x7f # disable call depth counting
  121. andn %d0,%d0,0x80 # clear CDE bit
  122. mtcr $psw,%d0
  123. isync
  124. /*
  125. * initialize access to system global registers
  126. */
  127. mfcr %d0,$psw
  128. or %d0,%d0,0x100 # set GW bit
  129. mtcr $psw,%d0
  130. isync
  131. /*
  132. * initialize SDA base pointers
  133. */
  134. .global _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
  135. .weak _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
  136. movh.a %a0,hi:_SMALL_DATA_ # %a0 addresses .sdata/.sbss
  137. lea %a0,[%a0]lo:_SMALL_DATA_
  138. movh.a %a1,hi:_SMALL_DATA2_ # %a1 addresses .sdata2/.sbss2
  139. lea %a1,[%a1]lo:_SMALL_DATA2_
  140. movh.a %a8,hi:_SMALL_DATA3_ # %a8 addresses .sdata3/.sbss3
  141. lea %a8,[%a8]lo:_SMALL_DATA3_
  142. movh.a %a9,hi:_SMALL_DATA4_ # %a9 addresses .sdata4/.sbss4
  143. lea %a9,[%a9]lo:_SMALL_DATA4_
  144. /*
  145. * reset access to system global registers
  146. */
  147. mfcr %d0,$psw
  148. andn %d0,%d0,0x100 # clear GW bit
  149. mtcr $psw,%d0
  150. isync
  151. mov.aa %a4,%a7
  152. jl asm_set_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
  153. # disable wdt cpuN
  154. mov.aa %a4,%a7
  155. jl asm_clear_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
  156. ld.w %d0,[%a4]4
  157. or %d0,%d0,8
  158. st.w [%a4]4,%d0 # *SCU_WDTCPUnCON1 |= SCU_WDTCPUNCON1_DR
  159. jl asm_set_endinit_xx # %a4 is set to SCU_WDTCPUnCON0
  160. mfcr %d0,CORE_ID # core ID
  161. jz %d0,disable_safety_wdt
  162. j jump_to_remapped
  163. disable_safety_wdt:
  164. # disable safety watchdog
  165. movh.a %a4,hi:SCU_WDTSCON0
  166. lea %a4,[%a4]lo:SCU_WDTSCON0
  167. jl asm_clear_endinit_xx # %a4 is set to SCU_WDTSCON0
  168. movh.a %a5,hi:SCU_WDTSCON1
  169. lea %a5,[%a5]lo:SCU_WDTSCON1
  170. ld.w %d0,[%a4]4
  171. or %d0,%d0,8
  172. st.w [%a4]4,%d0 # *SCU_WDTSCON1 |= SCU_WDTSCON1_DR
  173. jl asm_set_endinit_xx # %a4 is set to SCU_WDTSCON0
  174. /*
  175. * initialize target environment (PLLCLC, BUSCONx, ADDSELx etc)
  176. *
  177. * nothing to do here because there is no EBU
  178. */
  179. jump_to_remapped:
  180. #; force PC to remapped ROM address
  181. movh.a %a15,hi:__remapped
  182. lea %a15,[%a15]lo:__remapped
  183. nop
  184. ji %a15
  185. __remapped:
  186. /*
  187. * initialize context save areas
  188. */
  189. jl __init_csa
  190. /*
  191. * handle clear table (i.e., fill BSS with zeros)
  192. */
  193. jl __clear_table_func
  194. /*
  195. * handle copy table (support for romable code)
  196. */
  197. jl __copy_table_func
  198. /*
  199. * call the initializer, constructors etc.
  200. */
  201. call _init
  202. /*
  203. * _exit (main (0, NULL));
  204. */
  205. mov %d4,0 # argc = 0
  206. sub.a %sp,8
  207. st.w [%sp]0,%d4
  208. st.w [%sp]4,%d4
  209. mov.aa %a4,%sp # argv
  210. call main # int retval = main (0, NULL);
  211. mov %d4,%d2
  212. lea %sp,[%sp]8 # remove argv[0]
  213. mov.u %d1,0x900d # set exit code i(A14) for the simulator to
  214. mov %d15,%d2 # 0x900d if the exit status is 0
  215. movh %d3,0xffff
  216. or %d2,%d2,%d3
  217. cmov %d1,%d15,%d2
  218. mov.a %a14,%d1
  219. j _exit # _exit (retval);
  220. debug # should never come here
  221. # %a4 contains wdtcon0
  222. asm_clear_endinit_xx:
  223. ld.w %d15,[%a4]0
  224. andn %d4, %d15,1
  225. andn %d15,%d15,14
  226. or %d15,%d15,241
  227. st.w [%a4]0,%d15
  228. dsync
  229. andn %d4,%d4,12
  230. or %d4,%d4,242
  231. st.w [%a4]0,%d4
  232. ld.w %d15,[%a4]0 # read back new value ==> synchronise LFI
  233. ji %a11
  234. asm_set_endinit_xx:
  235. ld.w %d15,[%a4]0
  236. or %d4,%d15,1
  237. andn %d15,%d15,14
  238. or %d15,%d15,241
  239. st.w [%a4]0,%d15
  240. dsync
  241. andn %d4,%d4,12
  242. or %d4,%d4,242
  243. st.w [%a4]0,%d4
  244. ld.w %d15,[%a4]0 # read back new value ==> synchronise LFI
  245. ji %a11
  246. /*
  247. * initialize context save areas (CSAs), PCXI, LCX and FCX
  248. */
  249. .global __init_csa
  250. .type __init_csa,function
  251. __init_csa:
  252. movh %d0,0
  253. mtcr $pcxi,%d0
  254. isync
  255. movh %d0,hi:__CSA_BEGIN #; %d0 = begin of CSA
  256. addi %d0,%d0,lo:__CSA_BEGIN
  257. addi %d0,%d0,63 #; force alignment (2^6)
  258. andn %d0,%d0,63
  259. movh %d2,hi:__CSA_END #; %d2 = end of CSA
  260. addi %d2,%d2,lo:__CSA_END
  261. andn %d2,%d2,63 #; force alignment (2^6)
  262. sub %d2,%d2,%d0
  263. sh %d2,%d2,-6 #; %d2 = number of CSAs
  264. mov.a %a3,%d0 #; %a3 = address of first CSA
  265. extr.u %d0,%d0,28,4 #; %d0 = segment << 16
  266. sh %d0,%d0,16
  267. lea %a4,0 #; %a4 = previous CSA = 0
  268. st.a [%a3],%a4 #; store it in 1st CSA
  269. mov.aa %a4,%a3 #; %a4 = current CSA
  270. lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
  271. mov.d %d1,%a3
  272. extr.u %d1,%d1,6,16 #; get CSA index
  273. or %d1,%d1,%d0 #; add segment number
  274. mtcr $lcx,%d1 #; initialize LCX
  275. add %d2,%d2,-2 #; CSAs to initialize -= 2
  276. mov.a %a5,%d2 #; %a5 = loop counter
  277. csa_loop:
  278. mov.d %d1,%a4 #; %d1 = current CSA address
  279. extr.u %d1,%d1,6,16 #; get CSA index
  280. or %d1,%d1,%d0 #; add segment number
  281. st.w [%a3],%d1 #; store "nextCSA" pointer
  282. mov.aa %a4,%a3 #; %a4 = current CSA address
  283. lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
  284. loop %a5,csa_loop #; repeat until done
  285. mov.d %d1,%a4 #; %d1 = current CSA address
  286. extr.u %d1,%d1,6,16 #; get CSA index
  287. or %d1,%d1,%d0 #; add segment number
  288. mtcr $fcx,%d1 #; initialize FCX
  289. isync
  290. ji %a11
  291. /*
  292. * handle clear table (i.e., fill BSS with zeros)
  293. */
  294. .global __clear_table_func
  295. .type __clear_table_func,@function
  296. __clear_table_func:
  297. mov %d14,0 # %e14 = 0
  298. mov %d15,0
  299. movh.a %a13,hi:__clear_table # %a13 = &first table entry
  300. lea %a13,[%a13]lo:__clear_table
  301. __clear_table_next:
  302. ld.a %a15,[%a13+]4 # %a15 = current block base
  303. ld.w %d3,[%a13+]4 # %d3 = current block length
  304. jeq %d3,-1,__clear_table_done # length == -1 => end of table
  305. sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
  306. and %d1,%d3,7 # %d1 = length % 8 (rem. bytes)
  307. jz %d0,__clear_word # block size < 8 => clear word
  308. addi %d0,%d0,-1 # else doublewords -= 1
  309. mov.a %a2,%d0 # %a2 = loop counter
  310. __clear_dword:
  311. st.d [%a15+]8,%e14 # clear one doubleword
  312. loop %a2,__clear_dword
  313. __clear_word:
  314. jz %d1,__clear_table_next
  315. sh %d0,%d1,-2 # %d0 = length / 4 (words)
  316. and %d1,%d1,3 # %d1 = length % 4 (rem. bytes)
  317. jz %d0,__clear_hword # block size < 4 => clear hword
  318. st.w [%a15+]4,%d15 # clear one word
  319. __clear_hword:
  320. jz %d1,__clear_table_next
  321. sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
  322. and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
  323. jz %d0,__clear_byte # block size < 2 => clear byte
  324. st.h [%a15+]2,%d15 # clear one halfword
  325. __clear_byte:
  326. jz %d1,__clear_table_next
  327. st.b [%a15],%d15 # clear one byte
  328. j __clear_table_next # handle next clear table entry
  329. __clear_table_done:
  330. ji %a11
  331. /*
  332. * handle copy table (support for romable code)
  333. */
  334. .global __copy_table_func
  335. .type __copy_table_func,@function
  336. __copy_table_func:
  337. movh.a %a13,hi:__copy_table # %a13 = &first table entry
  338. lea %a13,[%a13]lo:__copy_table
  339. __copy_table_next:
  340. ld.a %a15,[%a13+]4 # %a15 = src address
  341. ld.a %a14,[%a13+]4 # %a14 = dst address
  342. ld.w %d3,[%a13+]4 # %d3 = block length
  343. jeq %d3,-1,__copy_table_done # length == -1 => end of table
  344. sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
  345. and %d1,%d3,7 # %d1 = lenght % 8 (rem. bytes)
  346. jz %d0,__copy_word # block size < 8 => copy word
  347. addi %d0,%d0,-1 # else doublewords -= 1
  348. mov.a %a2,%d0 # %a2 = loop counter
  349. __copy_dword:
  350. ld.d %e14,[%a15+]8 # copy one doubleword
  351. st.d [%a14+]8,%e14
  352. loop %a2,__copy_dword
  353. __copy_word:
  354. jz %d1,__copy_table_next
  355. sh %d0,%d1,-2 # %d0 = length / 4 (words)
  356. and %d1,%d1,3 # %d1 = lenght % 4 (rem. bytes)
  357. jz %d0,__copy_hword # block size < 4 => copy hword
  358. ld.w %d14,[%a15+]4 # copy one word
  359. st.w [%a14+]4,%d14
  360. __copy_hword:
  361. jz %d1,__copy_table_next
  362. sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
  363. and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
  364. jz %d0,__copy_byte # block size < 2 => copy byte
  365. ld.h %d14,[%a15+]2 # copy one halfword
  366. st.h [%a14+]2,%d14
  367. __copy_byte:
  368. jz %d1,__copy_table_next
  369. ld.b %d14,[%a15]0 # copy one byte
  370. st.b [%a14],%d14
  371. j __copy_table_next # handle next copy table entry
  372. __copy_table_done:
  373. ji %a11
  374. /*============================================================================*
  375. * Exception handlers (exceptions in startup code)
  376. *
  377. * This is a minimal trap vector table, which consists of eight
  378. * entries, each consisting of eight words (32 bytes).
  379. *============================================================================*/
  380. #; .section .traptab, "ax", @progbits
  381. .macro trapentry from=0, to=7
  382. debug
  383. mov.u %d14, \from << 8
  384. add %d14,%d14,%d15
  385. mov.a %a14,%d14
  386. addih.a %a14,%a14,0xdead
  387. j _exit
  388. 0:
  389. j 0b
  390. nop
  391. rfe
  392. .align 5
  393. .if \to-\from
  394. trapentry "(\from+1)",\to
  395. .endif
  396. .endm
  397. .align 8
  398. .global first_trap_table
  399. first_trap_table:
  400. trapentry 0, 7