[NDS32] Support Linux target for nds32.
[official-gcc.git] / libgcc / config / sh / crt1.S
blobe623d06d5eda47a1c5b3abf34dbb18e42e24d497
1 /* Copyright (C) 2000-2018 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
9 later version.
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/>.  */
25 #include "crt.h"
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 */
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
44 old_vbr:
45         .long 0
46 #ifdef PROFILE
47 profiling_enabled:
48         .long 0
49 #endif
52         .section .text
53         .global start
54         .import ___rtos_profiler_start_timer
55         .weak   ___rtos_profiler_start_timer
56 start:
57         mov.l   stack_k,r15
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
74 0:      
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
81 start_l:
82         mov.l   r2,@r0
83         add     #4,r0
84         cmp/ge  r0,r1
85         bt      start_l
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__) */
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 */
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
115         mov.l sr_initial_rtos, r1
117 set_sr:
118         ! Set status register (sr)
119         ldc     r1, sr
121         ! arrange for exit to call fini
122         mov.l   atexit_k,r0
123         mov.l   fini_k,r4
124         jsr     @r0
125         nop
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
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
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 */
151         ! call init
152         mov.l   init_k,r0
153         jsr     @r0
154         nop
156         ! call the mainline     
157         mov.l   main_k,r0
158         jsr     @r0
159         nop
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
169 stop_profiling:
170         # stop mcount counting
171         mov.l   profiling_enabled_k2, r0
172         mov     #0, r1
173         mov.l   r1, @r0
175         # call mcleanup
176         mov.l   mcleanup_k, r0
177         jmp     @r0
178         nop
179                 
180                 .balign 4
181 mcleanup_k:
182         .long __mcleanup
183 monstartup_k:
184         .long ___monstartup
185 profiling_enabled_k2:
186         .long profiling_enabled
187 start_k:
188         .long _start
189 etext_k:
190         .long __etext
191 #endif /* PROFILE */
193         .align 2
194 #if defined (__SH_FPU_ANY__)
195 set_fpscr_k:
196         .long   ___set_fpscr
197 #endif /*  defined (__SH_FPU_ANY__) */
199 stack_k:
200         .long   _stack  
201 edata_k:
202         .long   _edata
203 end_k:
204         .long   _end
205 main_k:
206         .long   ___setup_argv_and_call_main
207 exit_k:
208         .long   _exit
209 atexit_k:
210         .long   _atexit
211 init_k:
212         .long   GLOBAL(_init)
213 fini_k:
214         .long   GLOBAL(_fini)
215 #ifdef VBR_SETUP
216 old_vbr_k:
217         .long   old_vbr
218 vbr_start_k:
219         .long   vbr_start
220 #endif /* VBR_SETUP */
221         
222 sr_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 
228 rtos_start_fn:
229         .long ___rtos_profiler_start_timer
230         
231 #ifdef PROFILE
232 sr_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
238 sr_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
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"
253 vbr_start:
255         .org 0x100
256 vbr_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
273 1:      
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
281 2:      
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
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
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
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
330 event_mask:
331         .long 0xfff
332 trapcode_k:     
333         .long 0x160
334 expevt_k1:
335         .long 0xff000024 ! Address of expevt
336 trapa_k:        
337         .long 0xff000020
338 mcount_k:
339         .long __call_mcount
340 profiling_enabled_k:
341         .long profiling_enabled
342 #endif
343         ! Non profiling case.
344 handler_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     
352 1:      ! 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
359 2:      
360         .long old_vbr
362         .org 0x400
363 vbr_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
381         .long old_vbr
382 handler:
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
389 3:      
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
405         .org 0x600
406 vbr_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
477 pervading_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
499         .long old_vbr
500 #endif   /* PROFILE code */
501 chandler:
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
509 limbo:
510         bra limbo
511         nop
512         .balign 4
513 #ifdef PROFILE
514 interrupt_stack_k:
515         .long __timer_stack     ! The high end of the stack
516 timer_handler_k:
517         .long __profil_counter
518 #endif
519 expevt_k:
520         .long 0xff000024 ! Address of expevt
521 chandler_k:     
522         .long chandler  
523 superh_trap_handler_k:
524         .long   __superh_trap_handler
525 handler_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 */