1/* Copyright (C) 2000-2021 Free Software Foundation, Inc. 2 This file was pretty much copied from newlib. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it 7under the terms of the GNU General Public License as published by the 8Free Software Foundation; either version 3, or (at your option) any 9later version. 10 11GCC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14General Public License for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25#include "crt.h" 26 27#ifdef MMU_SUPPORT 28 /* Section used for exception/timer interrupt stack area */ 29 .section .data.vbr.stack,"aw" 30 .align 4 31 .global __ST_VBR 32__ST_VBR: 33 .zero 1024 * 2 /* ; 2k for VBR handlers */ 34/* Label at the highest stack address where the stack grows from */ 35__timer_stack: 36#endif /* MMU_SUPPORT */ 37 38 /* ;---------------------------------------- 39 Normal newlib crt1.S */ 40 41 ! make a place to keep any previous value of the vbr register 42 ! this will only have a value if it has been set by redboot (for example) 43 .section .bss 44old_vbr: 45 .long 0 46#ifdef PROFILE 47profiling_enabled: 48 .long 0 49#endif 50 51 52 .section .text 53 .global start 54 .import ___rtos_profiler_start_timer 55 .weak ___rtos_profiler_start_timer 56start: 57 mov.l stack_k,r15 58 59#if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2E__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__) 60#define VBR_SETUP 61 ! before zeroing the bss ... 62 ! if the vbr is already set to vbr_start then the program has been restarted 63 ! (i.e. it is not the first time the program has been run since reset) 64 ! reset the vbr to its old value before old_vbr (in bss) is wiped 65 ! this ensures that the later code does not create a circular vbr chain 66 stc vbr, r1 67 mov.l vbr_start_k, r2 68 cmp/eq r1, r2 69 bf 0f 70 ! reset the old vbr value 71 mov.l old_vbr_k, r1 72 mov.l @r1, r2 73 ldc r2, vbr 740: 75#endif /* VBR_SETUP */ 76 77 ! zero out bss 78 mov.l edata_k,r0 79 mov.l end_k,r1 80 mov #0,r2 81start_l: 82 mov.l r2,@r0 83 add #4,r0 84 cmp/ge r0,r1 85 bt start_l 86 87#if defined (__SH_FPU_ANY__) 88 mov.l set_fpscr_k, r1 89 mov #4,r4 90 jsr @r1 91 shll16 r4 ! Set DN bit (flush denormal inputs to zero) 92 lds r3,fpscr ! Switch to default precision 93#endif /* defined (__SH_FPU_ANY__) */ 94 95#ifdef VBR_SETUP 96 ! save the existing contents of the vbr 97 ! there will only be a prior value when using something like redboot 98 ! otherwise it will be zero 99 stc vbr, r1 100 mov.l old_vbr_k, r2 101 mov.l r1, @r2 102 ! setup vbr 103 mov.l vbr_start_k, r1 104 ldc r1,vbr 105#endif /* VBR_SETUP */ 106 107 ! if an rtos is exporting a timer start fn, 108 ! then pick up an SR which does not enable ints 109 ! (the rtos will take care of this) 110 mov.l rtos_start_fn, r0 111 mov.l sr_initial_bare, r1 112 tst r0, r0 113 bt set_sr 114 115 mov.l sr_initial_rtos, r1 116 117set_sr: 118 ! Set status register (sr) 119 ldc r1, sr 120 121 ! arrange for exit to call fini 122 mov.l atexit_k,r0 123 mov.l fini_k,r4 124 jsr @r0 125 nop 126 127#ifdef PROFILE 128 ! arrange for exit to call _mcleanup (via stop_profiling) 129 mova stop_profiling,r0 130 mov.l atexit_k,r1 131 jsr @r1 132 mov r0, r4 133 134 ! Call profiler startup code 135 mov.l monstartup_k, r0 136 mov.l start_k, r4 137 mov.l etext_k, r5 138 jsr @r0 139 nop 140 141 ! enable profiling trap 142 ! until now any trap 33s will have been ignored 143 ! This means that all library functions called before this point 144 ! (directly or indirectly) may have the profiling trap at the start. 145 ! Therefore, only mcount itself may not have the extra header. 146 mov.l profiling_enabled_k2, r0 147 mov #1, r1 148 mov.l r1, @r0 149#endif /* PROFILE */ 150 151 ! call init 152 mov.l init_k,r0 153 jsr @r0 154 nop 155 156 ! call the mainline 157 mov.l main_k,r0 158 jsr @r0 159 nop 160 161 ! call exit 162 mov r0,r4 163 mov.l exit_k,r0 164 jsr @r0 165 nop 166 167 .balign 4 168#ifdef PROFILE 169stop_profiling: 170 # stop mcount counting 171 mov.l profiling_enabled_k2, r0 172 mov #0, r1 173 mov.l r1, @r0 174 175 # call mcleanup 176 mov.l mcleanup_k, r0 177 jmp @r0 178 nop 179 180 .balign 4 181mcleanup_k: 182 .long __mcleanup 183monstartup_k: 184 .long ___monstartup 185profiling_enabled_k2: 186 .long profiling_enabled 187start_k: 188 .long _start 189etext_k: 190 .long __etext 191#endif /* PROFILE */ 192 193 .align 2 194#if defined (__SH_FPU_ANY__) 195set_fpscr_k: 196 .long ___set_fpscr 197#endif /* defined (__SH_FPU_ANY__) */ 198 199stack_k: 200 .long _stack 201edata_k: 202 .long _edata 203end_k: 204 .long _end 205main_k: 206 .long ___setup_argv_and_call_main 207exit_k: 208 .long _exit 209atexit_k: 210 .long _atexit 211init_k: 212 .long GLOBAL(_init) 213fini_k: 214 .long GLOBAL(_fini) 215#ifdef VBR_SETUP 216old_vbr_k: 217 .long old_vbr 218vbr_start_k: 219 .long vbr_start 220#endif /* VBR_SETUP */ 221 222sr_initial_rtos: 223 ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work. 224 ! Whether profiling or not, keep interrupts masked, 225 ! the RTOS will enable these if required. 226 .long 0x600000f1 227 228rtos_start_fn: 229 .long ___rtos_profiler_start_timer 230 231#ifdef PROFILE 232sr_initial_bare: 233 ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work. 234 ! For bare machine, we need to enable interrupts to get profiling working 235 .long 0x60000001 236#else 237 238sr_initial_bare: 239 ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work. 240 ! Keep interrupts disabled - the application will enable as required. 241 .long 0x600000f1 242#endif 243 244 ! supplied for backward compatibility only, in case of linking 245 ! code whose main() was compiled with an older version of GCC. 246 .global ___main 247___main: 248 rts 249 nop 250#ifdef VBR_SETUP 251! Exception handlers 252 .section .text.vbr, "ax" 253vbr_start: 254 255 .org 0x100 256vbr_100: 257#ifdef PROFILE 258 ! Note on register usage. 259 ! we use r0..r3 as scratch in this code. If we are here due to a trapa for profiling 260 ! then this is OK as we are just before executing any function code. 261 ! The other r4..r7 we save explicityl on the stack 262 ! Remaining registers are saved by normal ABI conventions and we assert we do not 263 ! use floating point registers. 264 mov.l expevt_k1, r1 265 mov.l @r1, r1 266 mov.l event_mask, r0 267 and r0,r1 268 mov.l trapcode_k, r2 269 cmp/eq r1,r2 270 bt 1f 271 bra handler_100 ! if not a trapa, go to default handler 272 nop 2731: 274 mov.l trapa_k, r0 275 mov.l @r0, r0 276 shlr2 r0 ! trapa code is shifted by 2. 277 cmp/eq #33, r0 278 bt 2f 279 bra handler_100 280 nop 2812: 282 283 ! If here then it looks like we have trap #33 284 ! Now we need to call mcount with the following convention 285 ! Save and restore r4..r7 286 mov.l r4,@-r15 287 mov.l r5,@-r15 288 mov.l r6,@-r15 289 mov.l r7,@-r15 290 sts.l pr,@-r15 291 292 ! r4 is frompc. 293 ! r5 is selfpc 294 ! r0 is the branch back address. 295 ! The code sequence emitted by gcc for the profiling trap is 296 ! .align 2 297 ! trapa #33 298 ! .align 2 299 ! .long lab Where lab is planted by the compiler. This is the address 300 ! of a datum that needs to be incremented. 301 sts pr, r4 ! frompc 302 stc spc, r5 ! selfpc 303 mov #2, r2 304 not r2, r2 ! pattern to align to 4 305 and r2, r5 ! r5 now has aligned address 306! add #4, r5 ! r5 now has address of address 307 mov r5, r2 ! Remember it. 308! mov.l @r5, r5 ! r5 has value of lable (lab in above example) 309 add #8, r2 310 ldc r2, spc ! our return address avoiding address word 311 312 ! only call mcount if profiling is enabled 313 mov.l profiling_enabled_k, r0 314 mov.l @r0, r0 315 cmp/eq #0, r0 316 bt 3f 317 ! call mcount 318 mov.l mcount_k, r2 319 jsr @r2 320 nop 3213: 322 lds.l @r15+,pr 323 mov.l @r15+,r7 324 mov.l @r15+,r6 325 mov.l @r15+,r5 326 mov.l @r15+,r4 327 rte 328 nop 329 .balign 4 330event_mask: 331 .long 0xfff 332trapcode_k: 333 .long 0x160 334expevt_k1: 335 .long 0xff000024 ! Address of expevt 336trapa_k: 337 .long 0xff000020 338mcount_k: 339 .long __call_mcount 340profiling_enabled_k: 341 .long profiling_enabled 342#endif 343 ! Non profiling case. 344handler_100: 345 mov.l 2f, r0 ! load the old vbr setting (if any) 346 mov.l @r0, r0 347 cmp/eq #0, r0 348 bf 1f 349 ! no previous vbr - jump to own generic handler 350 bra handler 351 nop 3521: ! there was a previous handler - chain them 353 add #0x7f, r0 ! 0x7f 354 add #0x7f, r0 ! 0xfe 355 add #0x2, r0 ! add 0x100 without corrupting another register 356 jmp @r0 357 nop 358 .balign 4 3592: 360 .long old_vbr 361 362 .org 0x400 363vbr_400: ! Should be at vbr+0x400 364 mov.l 2f, r0 ! load the old vbr setting (if any) 365 mov.l @r0, r0 366 cmp/eq #0, r0 367 ! no previous vbr - jump to own generic handler 368 bt handler 369 ! there was a previous handler - chain them 370 rotcr r0 371 rotcr r0 372 add #0x7f, r0 ! 0x1fc 373 add #0x7f, r0 ! 0x3f8 374 add #0x02, r0 ! 0x400 375 rotcl r0 376 rotcl r0 ! Add 0x400 without corrupting another register 377 jmp @r0 378 nop 379 .balign 4 3802: 381 .long old_vbr 382handler: 383 /* If the trap handler is there call it */ 384 mov.l superh_trap_handler_k, r0 385 cmp/eq #0, r0 ! True if zero. 386 bf 3f 387 bra chandler 388 nop 3893: 390 ! Here handler available, call it. 391 /* Now call the trap handler with as much of the context unchanged as possible. 392 Move trapping address into PR to make it look like the trap point */ 393 stc spc, r1 394 lds r1, pr 395 mov.l expevt_k, r4 396 mov.l @r4, r4 ! r4 is value of expevt, first parameter. 397 mov r1, r5 ! Remember trapping pc. 398 mov r1, r6 ! Remember trapping pc. 399 mov.l chandler_k, r1 400 mov.l superh_trap_handler_k, r2 401 ! jmp to trap handler to avoid disturbing pr. 402 jmp @r2 403 nop 404 405 .org 0x600 406vbr_600: 407#ifdef PROFILE 408 ! Should be at vbr+0x600 409 ! Now we are in the land of interrupts so need to save more state. 410 ! Save register state 411 mov.l interrupt_stack_k, r15 ! r15 has been saved to sgr. 412 mov.l r0,@-r15 413 mov.l r1,@-r15 414 mov.l r2,@-r15 415 mov.l r3,@-r15 416 mov.l r4,@-r15 417 mov.l r5,@-r15 418 mov.l r6,@-r15 419 mov.l r7,@-r15 420 sts.l pr,@-r15 421 sts.l mach,@-r15 422 sts.l macl,@-r15 423#if defined(__SH_FPU_ANY__) 424 ! Save fpul and fpscr, save fr0-fr7 in 64 bit mode 425 ! and set the pervading precision for the timer_handler 426 mov #0,r0 427 sts.l fpul,@-r15 428 sts.l fpscr,@-r15 429 lds r0,fpscr ! Clear fpscr 430 fmov fr0,@-r15 431 fmov fr1,@-r15 432 fmov fr2,@-r15 433 fmov fr3,@-r15 434 mov.l pervading_precision_k,r0 435 fmov fr4,@-r15 436 fmov fr5,@-r15 437 mov.l @r0,r0 438 fmov fr6,@-r15 439 fmov fr7,@-r15 440 lds r0,fpscr 441#endif /* __SH_FPU_ANY__ */ 442 ! Pass interrupted pc to timer_handler as first parameter (r4). 443 stc spc, r4 444 mov.l timer_handler_k, r0 445 jsr @r0 446 nop 447#if defined(__SH_FPU_ANY__) 448 mov #0,r0 449 lds r0,fpscr ! Clear the fpscr 450 fmov @r15+,fr7 451 fmov @r15+,fr6 452 fmov @r15+,fr5 453 fmov @r15+,fr4 454 fmov @r15+,fr3 455 fmov @r15+,fr2 456 fmov @r15+,fr1 457 fmov @r15+,fr0 458 lds.l @r15+,fpscr 459 lds.l @r15+,fpul 460#endif /* __SH_FPU_ANY__ */ 461 lds.l @r15+,macl 462 lds.l @r15+,mach 463 lds.l @r15+,pr 464 mov.l @r15+,r7 465 mov.l @r15+,r6 466 mov.l @r15+,r5 467 mov.l @r15+,r4 468 mov.l @r15+,r3 469 mov.l @r15+,r2 470 mov.l @r15+,r1 471 mov.l @r15+,r0 472 stc sgr, r15 ! Restore r15, destroyed by this sequence. 473 rte 474 nop 475#if defined(__SH_FPU_ANY__) 476 .balign 4 477pervading_precision_k: 478 .long GLOBAL(__fpscr_values)+4 479#endif 480#else 481 mov.l 2f, r0 ! Load the old vbr setting (if any). 482 mov.l @r0, r0 483 cmp/eq #0, r0 484 ! no previous vbr - jump to own handler 485 bt chandler 486 ! there was a previous handler - chain them 487 rotcr r0 488 rotcr r0 489 add #0x7f, r0 ! 0x1fc 490 add #0x7f, r0 ! 0x3f8 491 add #0x7f, r0 ! 0x5f4 492 add #0x03, r0 ! 0x600 493 rotcl r0 494 rotcl r0 ! Add 0x600 without corrupting another register 495 jmp @r0 496 nop 497 .balign 4 4982: 499 .long old_vbr 500#endif /* PROFILE code */ 501chandler: 502 mov.l expevt_k, r4 503 mov.l @r4, r4 ! r4 is value of expevt hence making this the return code 504 mov.l handler_exit_k,r0 505 jsr @r0 506 nop 507 ! We should never return from _exit but in case we do we would enter the 508 ! the following tight loop 509limbo: 510 bra limbo 511 nop 512 .balign 4 513#ifdef PROFILE 514interrupt_stack_k: 515 .long __timer_stack ! The high end of the stack 516timer_handler_k: 517 .long __profil_counter 518#endif 519expevt_k: 520 .long 0xff000024 ! Address of expevt 521chandler_k: 522 .long chandler 523superh_trap_handler_k: 524 .long __superh_trap_handler 525handler_exit_k: 526 .long _exit 527 .align 2 528! Simulated compile of trap handler. 529 .section .debug_abbrev,"",@progbits 530.Ldebug_abbrev0: 531 .section .debug_info,"",@progbits 532.Ldebug_info0: 533 .section .debug_line,"",@progbits 534.Ldebug_line0: 535 .text 536.Ltext0: 537 .align 5 538 .type __superh_trap_handler,@function 539__superh_trap_handler: 540.LFB1: 541 mov.l r14,@-r15 542.LCFI0: 543 add #-4,r15 544.LCFI1: 545 mov r15,r14 546.LCFI2: 547 mov.l r4,@r14 548 lds r1, pr 549 add #4,r14 550 mov r14,r15 551 mov.l @r15+,r14 552 rts 553 nop 554.LFE1: 555.Lfe1: 556 .size __superh_trap_handler,.Lfe1-__superh_trap_handler 557 .section .debug_frame,"",@progbits 558.Lframe0: 559 .ualong .LECIE0-.LSCIE0 560.LSCIE0: 561 .ualong 0xffffffff 562 .byte 0x1 563 .string "" 564 .uleb128 0x1 565 .sleb128 -4 566 .byte 0x11 567 .byte 0xc 568 .uleb128 0xf 569 .uleb128 0x0 570 .align 2 571.LECIE0: 572.LSFDE0: 573 .ualong .LEFDE0-.LASFDE0 574.LASFDE0: 575 .ualong .Lframe0 576 .ualong .LFB1 577 .ualong .LFE1-.LFB1 578 .byte 0x4 579 .ualong .LCFI0-.LFB1 580 .byte 0xe 581 .uleb128 0x4 582 .byte 0x4 583 .ualong .LCFI1-.LCFI0 584 .byte 0xe 585 .uleb128 0x8 586 .byte 0x8e 587 .uleb128 0x1 588 .byte 0x4 589 .ualong .LCFI2-.LCFI1 590 .byte 0xd 591 .uleb128 0xe 592 .align 2 593.LEFDE0: 594 .text 595.Letext0: 596 .section .debug_info 597 .ualong 0xb3 598 .uaword 0x2 599 .ualong .Ldebug_abbrev0 600 .byte 0x4 601 .uleb128 0x1 602 .ualong .Ldebug_line0 603 .ualong .Letext0 604 .ualong .Ltext0 605 .string "trap_handler.c" 606 .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" 607 .string "GNU C 3.2 20020529 (experimental)" 608 .byte 0x1 609 .uleb128 0x2 610 .ualong 0xa6 611 .byte 0x1 612 .string "_superh_trap_handler" 613 .byte 0x1 614 .byte 0x2 615 .byte 0x1 616 .ualong .LFB1 617 .ualong .LFE1 618 .byte 0x1 619 .byte 0x5e 620 .uleb128 0x3 621 .string "trap_reason" 622 .byte 0x1 623 .byte 0x1 624 .ualong 0xa6 625 .byte 0x2 626 .byte 0x91 627 .sleb128 0 628 .byte 0x0 629 .uleb128 0x4 630 .string "unsigned int" 631 .byte 0x4 632 .byte 0x7 633 .byte 0x0 634 .section .debug_abbrev 635 .uleb128 0x1 636 .uleb128 0x11 637 .byte 0x1 638 .uleb128 0x10 639 .uleb128 0x6 640 .uleb128 0x12 641 .uleb128 0x1 642 .uleb128 0x11 643 .uleb128 0x1 644 .uleb128 0x3 645 .uleb128 0x8 646 .uleb128 0x1b 647 .uleb128 0x8 648 .uleb128 0x25 649 .uleb128 0x8 650 .uleb128 0x13 651 .uleb128 0xb 652 .byte 0x0 653 .byte 0x0 654 .uleb128 0x2 655 .uleb128 0x2e 656 .byte 0x1 657 .uleb128 0x1 658 .uleb128 0x13 659 .uleb128 0x3f 660 .uleb128 0xc 661 .uleb128 0x3 662 .uleb128 0x8 663 .uleb128 0x3a 664 .uleb128 0xb 665 .uleb128 0x3b 666 .uleb128 0xb 667 .uleb128 0x27 668 .uleb128 0xc 669 .uleb128 0x11 670 .uleb128 0x1 671 .uleb128 0x12 672 .uleb128 0x1 673 .uleb128 0x40 674 .uleb128 0xa 675 .byte 0x0 676 .byte 0x0 677 .uleb128 0x3 678 .uleb128 0x5 679 .byte 0x0 680 .uleb128 0x3 681 .uleb128 0x8 682 .uleb128 0x3a 683 .uleb128 0xb 684 .uleb128 0x3b 685 .uleb128 0xb 686 .uleb128 0x49 687 .uleb128 0x13 688 .uleb128 0x2 689 .uleb128 0xa 690 .byte 0x0 691 .byte 0x0 692 .uleb128 0x4 693 .uleb128 0x24 694 .byte 0x0 695 .uleb128 0x3 696 .uleb128 0x8 697 .uleb128 0xb 698 .uleb128 0xb 699 .uleb128 0x3e 700 .uleb128 0xb 701 .byte 0x0 702 .byte 0x0 703 .byte 0x0 704 .section .debug_pubnames,"",@progbits 705 .ualong 0x27 706 .uaword 0x2 707 .ualong .Ldebug_info0 708 .ualong 0xb7 709 .ualong 0x67 710 .string "_superh_trap_handler" 711 .ualong 0x0 712 .section .debug_aranges,"",@progbits 713 .ualong 0x1c 714 .uaword 0x2 715 .ualong .Ldebug_info0 716 .byte 0x4 717 .byte 0x0 718 .uaword 0x0 719 .uaword 0x0 720 .ualong .Ltext0 721 .ualong .Letext0-.Ltext0 722 .ualong 0x0 723 .ualong 0x0 724#endif /* VBR_SETUP */ 725