1 /* Copyright (C) 2000-2016 Free Software Foundation, Inc.
2 This file was pretty much copied from newlib.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
28 /* Section used for exception/timer interrupt stack area */
29 .section .data.vbr.stack,"aw"
33 .zero 1024 * 2 /* ; 2k for VBR handlers */
34 /* Label at the highest stack address where the stack grows from */
36 #endif /* MMU_SUPPORT */
38 /* ;----------------------------------------
39 Normal newlib crt1.S */
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)
54 .import ___rtos_profiler_start_timer
55 .weak ___rtos_profiler_start_timer
59 #if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2E__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__)
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
70 ! reset the old vbr value
75 #endif /* VBR_SETUP */
87 #if defined (__SH_FPU_ANY__)
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__) */
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
103 mov.l vbr_start_k, r1
105 #endif /* VBR_SETUP */
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
115 mov.l sr_initial_rtos, r1
118 ! Set status register (sr)
121 ! arrange for exit to call fini
128 ! arrange for exit to call _mcleanup (via stop_profiling)
129 mova stop_profiling,r0
134 ! Call profiler startup code
135 mov.l monstartup_k, r0
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
170 # stop mcount counting
171 mov.l profiling_enabled_k2, r0
185 profiling_enabled_k2:
186 .long profiling_enabled
194 #if defined (__SH_FPU_ANY__)
197 #endif /* defined (__SH_FPU_ANY__) */
206 .long ___setup_argv_and_call_main
220 #endif /* VBR_SETUP */
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.
229 .long ___rtos_profiler_start_timer
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
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.
244 ! supplied for backward compatibility only, in case of linking
245 ! code whose main() was compiled with an older version of GCC.
252 .section .text.vbr, "ax"
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.
271 bra handler_100 ! if not a trapa, go to default handler
276 shlr2 r0 ! trapa code is shifted by 2.
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
294 ! r0 is the branch back address.
295 ! The code sequence emitted by gcc for the profiling trap is
299 ! .long lab Where lab is planted by the compiler. This is the address
300 ! of a datum that needs to be incremented.
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)
310 ldc r2, spc ! our return address avoiding address word
312 ! only call mcount if profiling is enabled
313 mov.l profiling_enabled_k, r0
335 .long 0xff000024 ! Address of expevt
341 .long profiling_enabled
343 ! Non profiling case.
345 mov.l 2f, r0 ! load the old vbr setting (if any)
349 ! no previous vbr - jump to own generic handler
352 1: ! there was a previous handler - chain them
355 add #0x2, r0 ! add 0x100 without corrupting another register
363 vbr_400: ! Should be at vbr+0x400
364 mov.l 2f, r0 ! load the old vbr setting (if any)
367 ! no previous vbr - jump to own generic handler
369 ! there was a previous handler - chain them
372 add #0x7f, r0 ! 0x1fc
373 add #0x7f, r0 ! 0x3f8
374 add #0x02, r0 ! 0x400
376 rotcl r0 ! Add 0x400 without corrupting another register
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.
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 */
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.
400 mov.l superh_trap_handler_k, r2
401 ! jmp to trap handler to avoid disturbing pr.
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.
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
429 lds r0,fpscr ! Clear fpscr
434 mov.l pervading_precision_k,r0
441 #endif /* __SH_FPU_ANY__ */
442 ! Pass interrupted pc to timer_handler as first parameter (r4).
444 mov.l timer_handler_k, r0
447 #if defined(__SH_FPU_ANY__)
449 lds r0,fpscr ! Clear the fpscr
460 #endif /* __SH_FPU_ANY__ */
472 stc sgr, r15 ! Restore r15, destroyed by this sequence.
475 #if defined(__SH_FPU_ANY__)
477 pervading_precision_k:
478 .long GLOBAL(__fpscr_values)+4
481 mov.l 2f, r0 ! Load the old vbr setting (if any).
484 ! no previous vbr - jump to own handler
486 ! there was a previous handler - chain them
489 add #0x7f, r0 ! 0x1fc
490 add #0x7f, r0 ! 0x3f8
491 add #0x7f, r0 ! 0x5f4
492 add #0x03, r0 ! 0x600
494 rotcl r0 ! Add 0x600 without corrupting another register
500 #endif /* PROFILE code */
503 mov.l @r4, r4 ! r4 is value of expevt hence making this the return code
504 mov.l handler_exit_k,r0
507 ! We should never return from _exit but in case we do we would enter the
508 ! the following tight loop
515 .long __timer_stack ! The high end of the stack
517 .long __profil_counter
520 .long 0xff000024 ! Address of expevt
523 superh_trap_handler_k:
524 .long __superh_trap_handler
528 ! Simulated compile of trap handler.
529 .section .debug_abbrev,"",@progbits
531 .section .debug_info,"",@progbits
533 .section .debug_line,"",@progbits
538 .type __superh_trap_handler,@function
539 __superh_trap_handler:
556 .size __superh_trap_handler,.Lfe1-__superh_trap_handler
557 .section .debug_frame,"",@progbits
559 .ualong .LECIE0-.LSCIE0
573 .ualong .LEFDE0-.LASFDE0
583 .ualong .LCFI1-.LCFI0
589 .ualong .LCFI2-.LCFI1
599 .ualong .Ldebug_abbrev0
602 .ualong .Ldebug_line0
605 .string "trap_handler.c"
606 .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
607 .string "GNU C 3.2 20020529 (experimental)"
612 .string "_superh_trap_handler"
621 .string "trap_reason"
630 .string "unsigned int"
634 .section .debug_abbrev
704 .section .debug_pubnames,"",@progbits
707 .ualong .Ldebug_info0
710 .string "_superh_trap_handler"
712 .section .debug_aranges,"",@progbits
715 .ualong .Ldebug_info0
721 .ualong .Letext0-.Ltext0
724 #endif /* VBR_SETUP */