source: trunk/libs/newlib/src/libgloss/arm/crt0.S @ 514

Last change on this file since 514 was 444, checked in by satin@…, 7 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 13.2 KB
RevLine 
[444]1#include "newlib.h"
2#include "arm.h"
3#include "swi.h"
4
5/* ANSI concatenation macros.  */
6#define CONCAT(a, b) CONCAT2(a, b)
7#define CONCAT2(a, b) a ## b
8
9#ifdef __USER_LABEL_PREFIX__
10#define FUNCTION( name ) CONCAT (__USER_LABEL_PREFIX__, name)
11#else
12#error __USER_LABEL_PREFIX is not defined
13#endif
14
15#ifdef HAVE_INITFINI_ARRAY
16#define _init   __libc_init_array
17#define _fini   __libc_fini_array
18#endif
19
20#if defined(__ARM_EABI__) && defined(__thumb__) && !defined(__thumb2__)
21/* For Thumb1 we need to force the architecture to be sure that we get the
22   correct attributes on the object file; otherwise the assembler will get
23   confused and mark the object as being v6T2.  */
24#if defined(__ARM_ARCH_4T__)
25        .arch armv4t
26#elif defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__)
27        /* Nothing in this object requires higher than v5.  */
28        .arch armv5t
29#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
30        || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
31        || defined(__ARM_ARCH_6ZK__)
32        /* Nothing in this object requires higher than v6.  */
33        .arch armv6
34#elif defined(__ARM_ARCH_6M__)
35#ifdef ARM_RDP_MONITOR
36        /* Object file uses SVC, so mark as v6s-m.  */
37        .arch armv6s-m
38#else
39        .arch armv6-m
40#endif
41#endif
42#endif
43
44/* .text is used instead of .section .text so it works with arm-aout too.  */
45        .text
46        .syntax unified
47#ifdef PREFER_THUMB
48        .thumb
49.macro FUNC_START name
50        .global \name
51        .thumb_func
52\name:
53.endm
54#else
55        .code 32
56.macro FUNC_START name
57        .global \name
58\name:
59.endm
60#endif
61
62.macro indirect_call reg
63#ifdef HAVE_CALL_INDIRECT
64        blx \reg
65#else
66        mov     lr, pc
67        mov     pc, \reg
68#endif
69.endm
70
71        .align  0
72
73        FUNC_START      _mainCRTStartup
74        FUNC_START      _start
75#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
76        /* Annotation for EABI unwinding tables.  */
77        .fnstart
78#endif
79
80        /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
81        has been defined since 4.2 onwards, which is when v7-a support was added
82        and hence 'A' profile support was added in the compiler.  Allow for this
83        file to be built with older compilers.  We only call this for A profile
84        cores.  */
85#if defined (__ARM_ARCH_7A__) || (__ARM_ARCH_PROFILE == 'A')
86/*  The init hook does not use the stack and is called before the stack has been set up.  */
87#ifdef ARM_RDI_MONITOR
88        bl      _rdimon_hw_init_hook
89        .weak   FUNCTION (_rdimon_hw_init_hook)
90#endif
91#endif
92
93/* Start by setting up a stack */
94#ifdef ARM_RDP_MONITOR
95        /*  Issue Demon SWI to read stack info */
96        swi     SWI_GetEnv      /*  Returns command line in r0 */
97        mov     sp,r1           /*  and the highest memory address in r1 */
98
99        /*  stack limit is at end of data */
100        /*  allow slop for stack overflow handling and small frames */
101#ifdef THUMB1_ONLY
102        ldr     r0, .LC2
103        adds    r0, #128
104        adds    r0, #128
105        mov     sl, r0
106#else
107        ldr     sl, .LC2
108        add     sl, sl, #256
109#endif
110#else
111#ifdef ARM_RDI_MONITOR
112        /*  Issue Angel SWI to read stack info */
113        movs    r0, #AngelSWI_Reason_HeapInfo
114        adr     r1, .LC0        /*  point at ptr to 4 words to receive data */
115#ifdef THUMB_VXM
116        bkpt    AngelSWI
117#elif defined(__thumb2__)
118        /*  We are in thumb mode for startup on armv7 architectures. */
119        AngelSWIAsm     AngelSWI
120#else
121        /*  We are always in ARM mode for startup on pre armv7 archs. */
122        AngelSWIAsm     AngelSWI_ARM
123#endif
124        ldr     r0, .LC0        /*  point at values read */
125
126        /* Set __heap_limit.  */
127        ldr     r1, [r0, #4]
128        cmp     r1, #0
129        beq     .LC33
130        ldr     r2, =__heap_limit
131        str     r1, [r2]
132.LC33:
133        ldr     r1, [r0, #0]
134        cmp     r1, #0
135        bne     .LC32
136        /* If the heap base value [r0, #0] is 0 then the heap base is actually
137           at the end of program data (i.e. __end__). See:
138           http://infocenter.arm.com/help/topic/com.arm.doc.dui0471-/Bacbefaa.html
139           for more information.  */
140        ldr     r1, .LC31
141        str     r1, [r0, #0]
142.LC32: 
143        ldr     r1, [r0, #8]
144        ldr     r2, [r0, #12]
145        /*  We skip setting sp/sl if 0 returned from semihosting.
146            - According to semihosting docs, if 0 returned from semihosting,
147              the system was unable to calculate the real value, so it's ok
148              to skip setting sp/sl to 0 here.
149            - Considering M-profile processors, We might want to initialize
150              sp by the first entry of vector table and return 0 to SYS_HEAPINFO
151              semihosting call, which will be skipped here. */
152        cmp     r1, #0
153        beq     .LC26
154        mov     sp, r1
155.LC26:
156        cmp     r2, #0
157        beq     .LC27
158        /*  allow slop for stack overflow handling and small frames */
159#ifdef THUMB1_ONLY
160        adds    r2, #128
161        adds    r2, #128
162        mov     sl, r2
163#else
164        add     sl, r2, #256
165#endif
166.LC27:
167#else
168        /*  Set up the stack pointer to a fixed value */
169        /*  Changes by toralf:
170            - Allow linker script to provide stack via __stack symbol - see
171              defintion of .Lstack
172            - Provide "hooks" that may be used by the application to add
173              custom init code - see .Lhwinit and .Lswinit     
174            - Go through all execution modes and set up stack for each of them.
175              Loosely based on init.s from ARM/Motorola example code.
176              Note: Mode switch via CPSR is not allowed once in non-privileged
177                    mode, so we take care not to enter "User" to set up its sp,
178                    and also skip most operations if already in that mode. */
179
180        ldr     r3, .Lstack
181        cmp     r3, #0
182#ifdef __thumb2__
183        it      eq
184#endif 
185#ifdef THUMB1_ONLY
186        bne     .LC28
187        ldr     r3, .LC0
188.LC28:
189#else
190        ldreq   r3, .LC0
191#endif
192        /* Note: This 'mov' is essential when starting in User, and ensures we
193                 always get *some* sp value for the initial mode, even if we
194                 have somehow missed it below (in which case it gets the same
195                 value as FIQ - not ideal, but better than nothing.) */
196        mov     sp, r3
197#ifdef PREFER_THUMB
198        /* XXX Fill in stack assignments for interrupt modes.  */
199#else
200        mrs     r2, CPSR
201        tst     r2, #0x0F       /* Test mode bits - in User of all are 0 */
202        beq     .LC23           /* "eq" means r2 AND #0x0F is 0 */
203        msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled */
204        mov     sp, r3
205        sub     sl, sp, #0x1000 /* This mode also has its own sl (see below) */
206       
207        mov     r3, sl 
208        msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled */
209        mov     sp, r3
210        sub     r3, r3, #0x1000
211
212        msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled */
213        mov     sp, r3
214        sub     r3, r3, #0x1000
215
216        msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled */
217        mov     sp, r3
218        sub     r3, r3, #0x2000
219               
220        msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled */
221
222        mov     sp, r3
223        sub     r3, r3, #0x8000 /* Min size 32k */
224        bic     r3, r3, #0x00FF /* Align with current 64k block */
225        bic     r3, r3, #0xFF00
226
227        str     r3, [r3, #-4]   /* Move value into user mode sp without */
228        ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm */
229        orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
230        msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1 */
231#endif 
232.LC23:
233        /* Setup a default stack-limit in-case the code has been
234           compiled with "-mapcs-stack-check".  Hard-wiring this value
235           is not ideal, since there is currently no support for
236           checking that the heap and stack have not collided, or that
237           this default 64k is enough for the program being executed.
238           However, it ensures that this simple crt0 world will not
239           immediately cause an overflow event:  */
240#ifdef THUMB1_ONLY
241        movs    r2, #64
242        lsls    r2, r2, #10
243        subs    r2, r3, r2
244        mov     sl, r2
245#else
246        sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl */
247#endif
248#endif
249#endif
250        /* Zero the memory in the .bss section.  */
251        movs    a2, #0                  /* Second arg: fill value */
252        mov     fp, a2                  /* Null frame pointer */
253        mov     r7, a2                  /* Null frame pointer for Thumb */
254       
255        ldr     a1, .LC1                /* First arg: start of memory block */
256        ldr     a3, .LC2       
257        subs    a3, a3, a1              /* Third arg: length of block */
258       
259
260#if __thumb__ && !defined(PREFER_THUMB)
261        /* Enter Thumb mode.... */
262        add     a4, pc, #1      /* Get the address of the Thumb block */
263        bx      a4              /* Go there and start Thumb decoding  */
264
265        .code 16
266        .global __change_mode
267        .thumb_func
268__change_mode: 
269#endif
270       
271        bl      FUNCTION (memset)
272#if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
273/* Changes by toralf: Taken from libgloss/m68k/crt0.S
274 * initialize target specific stuff. Only execute these
275 * functions it they exist.
276 */
277        ldr     r3, .Lhwinit
278        cmp     r3, #0
279        beq     .LC24
280        indirect_call r3
281.LC24: 
282        ldr     r3, .Lswinit
283        cmp     r3, #0
284        beq     .LC25
285        indirect_call r3
286
287.LC25: 
288        movs    r0, #0          /*  no arguments  */
289        movs    r1, #0          /*  no argv either */
290#else
291        /* Need to set up standard file handles */
292        bl      FUNCTION (initialise_monitor_handles)
293       
294#ifdef ARM_RDP_MONITOR
295        swi     SWI_GetEnv      /*  sets r0 to point to the command line */
296        movs    r1, r0
297#else
298        movs    r0, #AngelSWI_Reason_GetCmdLine
299        ldr     r1, .LC30       /*  Space for command line */
300        AngelSWIAsm     AngelSWI
301        ldr     r1, .LC30
302        ldr     r1, [r1]
303#endif
304        /*  Parse string at r1 */
305        movs    r0, #0          /*  count of arguments so far */
306        /* Push a NULL argument onto the end of the list.  */
307#ifdef __thumb__
308        push    {r0}
309#else
310        stmfd   sp!, {r0}
311#endif
312.LC10:
313/*  Skip leading blanks */
314#ifdef __thumb__
315        ldrb    r3, [r1]
316        adds    r1, #1
317#else
318        ldrb    r3, [r1], #1
319#endif
320        cmp     r3, #0
321        beq     .LC12
322        cmp     r3, #' '
323        beq     .LC10
324
325/*  See whether we are scanning a string */
326        cmp     r3, #'"'
327#ifdef __thumb__
328        beq     .LC20
329        cmp     r3, #'\''
330        bne     .LC21
331.LC20:
332        movs    r2, r3
333        b       .LC22
334
335.LC21:
336        movs    r2, #' '        /*  terminator type */
337        subs    r1, r1, #1      /*  adjust back to point at start char */
338.LC22:
339#else
340        cmpne   r3, #'\''
341        moveq   r2, r3
342        movne   r2, #' '        /*  terminator type */
343        subne   r1, r1, #1      /*  adjust back to point at start char */
344#endif
345
346/*  Stack a pointer to the current argument */
347#ifdef __thumb__
348        push    {r1}
349#else
350        stmfd   sp!, {r1}
351#endif
352        adds    r0, r0, #1
353.LC11:
354#ifdef __thumb__
355        ldrb    r3, [r1]
356        adds    r1, #1
357#else
358        ldrb    r3, [r1], #1
359#endif
360        cmp     r3, #0
361        beq     .LC12
362        cmp     r2, r3          /*  reached terminator? */
363        bne     .LC11
364        movs    r2, #0
365        subs    r3, r1, #1
366        strb    r2, [r3]        /*  terminate the arg string */
367        b       .LC10
368
369.LC12:
370        mov     r1, sp          /*  point at stacked arg pointers */
371        /* We've now got the stacked args in order reverse the */
372#ifdef __thumb__
373        movs    r2, r0
374        lsls    r2, #2
375        add     r2, sp
376        mov     r3, sp
377.LC15:  cmp     r2, r3
378        bls     .LC14
379        subs    r2, #4
380        ldr     r4, [r2]
381        ldr     r5, [r3]
382        str     r5, [r2]
383        str     r4, [r3]
384        adds    r3, #4
385        b       .LC15
386.LC14: 
387        /* Ensure doubleword stack alignment.  */
388        mov     r4, sp
389        movs    r5, #7
390        bics    r4, r5
391        mov     sp, r4
392#else
393        add     r2, sp, r0, LSL #2      /* End of args */
394        mov     r3, sp                  /* Start of args */
395.LC13:  cmp     r2, r3
396        ldrhi   r4,[r2, #-4]            /* Reverse ends of list */
397        ldrhi   r5, [r3]
398        strhi   r5, [r2, #-4]!
399        strhi   r4, [r3], #4
400        bhi     .LC13
401        /* Ensure doubleword stack alignment.  */
402        bic     sp, sp, #7
403#endif
404#endif
405
406#ifdef __USES_INITFINI__
407        /* Some arm/elf targets use the .init and .fini sections
408           to create constructors and destructors, and for these
409           targets we need to call the _init function and arrange
410           for _fini to be called at program exit.  */
411        movs    r4, r0
412        movs    r5, r1
413#ifdef _LITE_EXIT
414        /* Make reference to atexit weak to avoid unconditionally pulling in
415           support code.  Refer to comments in __atexit.c for more details.  */
416        .weak   FUNCTION(atexit)
417        ldr     r0, .Latexit
418        cmp     r0, #0
419        beq     .Lweak_atexit
420#endif
421        ldr     r0, .Lfini
422        bl      FUNCTION (atexit)
423.Lweak_atexit:
424        bl      FUNCTION (_init)
425        movs    r0, r4
426        movs    r1, r5
427#endif
428        bl      FUNCTION (main)
429
430        bl      FUNCTION (exit)         /* Should not return.  */
431
432#if __thumb__ && !defined(PREFER_THUMB)
433        /* Come out of Thumb mode.  This code should be redundant.  */
434
435        mov     a4, pc
436        bx      a4
437
438        .code 32
439        .global change_back
440change_back:
441        /* Halt the execution.  This code should never be executed.  */
442        /* With no debug monitor, this probably aborts (eventually).
443           With a Demon debug monitor, this halts cleanly.
444           With an Angel debug monitor, this will report 'Unknown SWI'.  */
445        swi     SWI_Exit
446#endif
447       
448        /* For Thumb, constants must be after the code since only
449           positive offsets are supported for PC relative addresses.  */
450       
451        .align 0
452.LC0:
453#ifdef ARM_RDI_MONITOR
454        .word   HeapBase
455#else
456#ifndef ARM_RDP_MONITOR
457        /* Changes by toralf: Provide alternative "stack" variable whose value
458           may be defined externally; .Lstack will be used instead of .LC0 if
459           it points to a non-0 value. Also set up references to "hooks" that
460           may be used by the application to provide additional init code. */
461       
462#ifdef __pe__
463        .word   0x800000
464#else
465        .word   0x80000                 /* Top of RAM on the PIE board.  */
466#endif
467.Lstack:       
468        .word   __stack
469.Lhwinit:       
470        .word   FUNCTION (hardware_init_hook)
471.Lswinit:
472        .word   FUNCTION (software_init_hook)
473
474        /* Set up defaults for the above variables in the form of weak symbols
475           - so that application will link correctly, and get value 0 in
476           runtime (meaning "ignore setting") for the variables, when the user
477           does not provide the symbols. (The linker uses a weak symbol if,
478           and only if, a normal version of the same symbol isn't provided
479           e.g. by a linker script or another object file.) */ 
480
481        .weak __stack
482        .weak FUNCTION (hardware_init_hook)
483        .weak FUNCTION (software_init_hook)
484#endif
485       
486#endif
487#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
488        /* Protect against unhandled exceptions.  */
489        .cantunwind
490        .fnend
491#endif
492.LC1:
493        .word   __bss_start__
494.LC2:
495        .word   __bss_end__
496#ifdef __USES_INITFINI__
497#ifdef _LITE_EXIT
498.Latexit:
499        .word   FUNCTION(atexit)
500
501        /* Weak reference _fini in case of lite exit.  */
502        .weak   FUNCTION(_fini)
503#endif
504.Lfini:
505        .word   FUNCTION(_fini)
506#endif
507#ifdef ARM_RDI_MONITOR
508.LC30:
509        .word   AngelSWIArgs
510.LC31:
511        .word   __end__
512
513/*  Workspace for Angel calls.  */
514        .data
515/*  Data returned by monitor SWI.  */
516.global __stack_base__
517HeapBase:       .word   0
518HeapLimit:      .word   0
519__stack_base__: .word   0
520StackLimit:     .word   0
521CommandLine:    .space  256,0   /*  Maximum length of 255 chars handled.  */
522AngelSWIArgs:
523        .word   CommandLine
524        .word   255
525#endif
526       
527#ifdef __pe__
528        .section .idata$3
529        .long   0,0,0,0,0,0,0,0
530#endif
Note: See TracBrowser for help on using the repository browser.