Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / sys / arm / crt0.S
blobdae0f0465be8dcbddecaad75d19a723c5024754f
1 #include "newlib.h"
2 #include "arm.h"
3 #include "swi.h"
5 /* ANSI concatenation macros.  */
6 #define CONCAT(a, b) CONCAT2(a, b)
7 #define CONCAT2(a, b) a ## b
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
15 #ifdef _HAVE_INITFINI_ARRAY
16 #define _init   __libc_init_array
17 #define _fini   __libc_fini_array
18 #endif
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
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         .type \name, %function
52         .thumb_func
53 \name:
54 .endm
55 #else
56         .code 32
57 .macro FUNC_START name
58         .global \name
59         .type \name, %function
60 \name:
61 .endm
62 #endif
64 /* Annotation for EABI unwinding tables.  */
65 .macro FN_EH_START
66 #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
67         .fnstart
68 #endif
69 .endm
71 .macro FN_EH_END
72 #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
73         /* Protect against unhandled exceptions.  */
74         .cantunwind
75         .fnend
76 #endif
77 .endm
79 .macro indirect_call reg
80 #ifdef HAVE_CALL_INDIRECT
81         blx \reg
82 #else
83         mov     lr, pc
84         mov     pc, \reg
85 #endif
86 .endm
88 /* For armv4t and newer, toolchains will transparently convert
89    'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
90    for anything older than armv4t, but this should handle that
91    corner case in case anyone needs it anyway.  */
92 .macro  FN_RETURN
93 #if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
94         mov     pc, lr
95 #else
96         bx      lr
97 #endif
98 .endm
102 /******************************************************************************
103 * User mode only:           This routine makes default target specific Stack
104 *   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
105 *   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
106 *   | SYS |               and setups a default Stack Limit in-case the code has
107 *   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
108 *   |     |               System (User) modes.
109 *   |     |
110 *   +-----+ <- initial SP,
111 *           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
112 *           and SL_usr     currently no support for checking that the heap and
113 *                          stack have not collided, or that this default 64k is
114 * All modes:               is enough for the program being executed. However,
115 *   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
116 *   |     |    SL_usr      immediately cause an overflow event.
117 *   | SYS |
118 *   | USR | -=0x10000        We go through all execution modes and set up SP
119 *   |     |                for each of them.
120 *   +-----+ <- SP_sys,
121 *   |     |    SP_usr      Notes:
122 *   | SVC | -= 0x8000       - This code will not work as intended if the system
123 *   |     |                   starts in secure mode. In particular the methods
124 *   +-----+ <- SP_svc         of getting in and out of secure state are not as
125 *   |     |                   simple as writing to the CPSR mode bits.
126 *   | IRQ | -= 0x2000       - Mode switch via CPSR is not allowed once in
127 *   |     |                   non-privileged mode or in hypervisor mode, so we
128 * ^ +-----+ <- SP_und         take care not to enter "User" or "Hypervisor" mode
129 * s |     |                   to set up its SP, and also skip most operations if
130 * t | UND | -= 0x1000         already in these modes.
131 * a |     |                Input parameters:
132 * c +-----+ <- SP_und       - sp - Initialized SP
133 * k |     |                 - r2 - May contain SL value from semihosting
134 *   | ABT | -= 0x1000              SYS_HEAPINFO call
135 * g |     |                Scratch registers:
136 * r +-----+ <- SP_abt,      - r1 - new value of CPSR
137 * o |     |    SL_fiq       - r2 - intermediate value (in standalone mode)
138 * w | FIQ | -= 0x1000       - r3 - new SP value
139 * t |     |                 - r4 - save/restore CPSR on entry/exit
140 * h +-----+ <- initial SP,
141 *           becomes SP_fiq   Declared as "weak" so that user can write and use
142 *                          his own implementation if current doesn't fit.
144 ******************************************************************************/
145         .align  0
146         FUNC_START      _stack_init
147         .weak FUNCTION (_stack_init)
148         FN_EH_START
150         /* M profile doesn't have CPSR register.  */
151 #if (__ARM_ARCH_PROFILE != 'M')
152         /* Following code is compatible for both ARM and Thumb ISA.  */
153         mrs     r4, CPSR
154         mov     r3, sp /* Save input SP value.  */
155         ands    r1, r4, #(CPSR_M_MASK)
156         beq     .Lskip_cpu_modes
157         cmp     r1, #(CPSR_M_HYP)
158         beq     .Lskip_cpu_modes
160         /* FIQ mode, interrupts disabled.  */
161         mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
162         msr     CPSR_c, r1
163         mov     sp, r3
164         sub     sl, sp, #0x1000 /* FIQ mode has its own SL.  */
166         /* Abort mode, interrupts disabled.  */
167         mov     r3, sl
168         mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
169         msr     CPSR_c, r1
170         mov     sp, r3
171         sub     r3, r3, #0x1000
173         /* Undefined mode, interrupts disabled.  */
174         mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
175         msr     CPSR_c, r1
176         mov     sp, r3
177         sub     r3, r3, #0x1000
179         /* IRQ mode, interrupts disabled.  */
180         mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
181         msr     CPSR_c, r1
182         mov     sp, r3
183         sub     r3, r3, #0x2000
185         /* Supervisory mode, interrupts disabled.  */
186         mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
187         msr     CPSR_c, r1
188         mov     sp, r3
190         sub     r3, r3, #0x8000 /* Min size 32k.  */
191         bic     r3, r3, #0x00FF /* Align with current 64k block.  */
192         bic     r3, r3, #0xFF00
194 # if __ARM_ARCH >= 4
195         /* System (shares regs with User) mode, interrupts disabled.  */
196         mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
197         msr     CPSR_c, r1
198         mov     sp, r3
199 # else
200         /* Keep this for ARMv3, but GCC actually dropped it.  */
201         /* Move value into user mode SP without changing modes,  */
202         /* via '^' form of ldm.  */
203         str     r3, [r3, #-4]
204         ldmdb   r3, {sp}^
205 # endif
207         /* Back to original mode, presumably SVC, with diabled FIQ/IRQ.  */
208         orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
209         msr     CPSR_c, r4
211 .Lskip_cpu_modes:
212 #endif
214         /* Set SL register.  */
215 #if defined (ARM_RDI_MONITOR) /* semihosting */
216         cmp     r2, #0
217         beq     .Lsl_forced_zero
218         /* Allow slop for stack overflow handling and small frames.  */
219 # ifdef THUMB1_ONLY
220         adds    r2, #128
221         adds    r2, #128
222         mov     sl, r2
223 # else
224         add     sl, r2, #256
225 # endif
226 .Lsl_forced_zero:
228 #else /* standalone */
229         /* r3 contains SP for System/User mode. Set SL = SP - 0x10000.  */
230         #ifdef THUMB1_ONLY
231         movs    r2, #64
232         lsls    r2, r2, #10
233         subs    r2, r3, r2
234         mov     sl, r2
235         #else
236         /* Still assumes 256bytes below SL.  */
237         sub     sl, r3, #64 << 10
238         #endif
239 #endif
241         FN_RETURN
242         FN_EH_END
245 /*******************************************************************************
246 * Main library startup code.
247 *******************************************************************************/
248         .align  0
249         FUNC_START      _mainCRTStartup
250         FUNC_START      _start
251         FN_EH_START
253 /* Start by setting up a stack.  */
254 #ifdef ARM_RDP_MONITOR
255         /*  Issue Demon SWI to read stack info.  */
256         swi     SWI_GetEnv      /*  Returns command line in r0.  */
257         mov     sp,r1           /*  and the highest memory address in r1.  */
259         /*  Stack limit is at end of data.  */
260         /*  Allow slop for stack overflow handling and small frames.  */
261 #ifdef THUMB1_ONLY
262         ldr     r0, .LC2
263         adds    r0, #128
264         adds    r0, #128
265         mov     sl, r0
266 #else
267         ldr     sl, .LC2
268         add     sl, sl, #256
269 #endif
270 #else
271 #ifdef ARM_RDI_MONITOR
272         /*  Issue Angel SWI to read stack info.  */
273         movs    r0, #AngelSWI_Reason_HeapInfo
274         adr     r1, .LC0        /*  Point at ptr to 4 words to receive data.  */
275 #ifdef THUMB_VXM
276         bkpt    AngelSWI
277 #elif defined(__thumb2__)
278         /*  We are in thumb mode for startup on armv7 architectures.  */
279         AngelSWIAsm     AngelSWI
280 #else
281         /*  We are always in ARM mode for startup on pre armv7 archs.  */
282         AngelSWIAsm     AngelSWI_ARM
283 #endif
284         ldr     r0, .LC0        /*  Point at values read.  */
286         /* Set __heap_limit.  */
287         ldr     r1, [r0, #4]
288         cmp     r1, #0
289         beq     .LC33
290         ldr     r2, =__heap_limit
291         str     r1, [r2]
292 .LC33:
293         ldr     r1, [r0, #0]
294         cmp     r1, #0
295         bne     .LC32
296         /* If the heap base value [r0, #0] is 0 then the heap base is actually 
297            at the end of program data (i.e. __end__). See:
298            http://infocenter.arm.com/help/topic/com.arm.doc.dui0471-/Bacbefaa.html
299            for more information.  */
300         ldr     r1, .LC31
301         str     r1, [r0, #0]
302 .LC32:  
303         ldr     r1, [r0, #8]
304         ldr     r2, [r0, #12]
305         /*  We skip setting SP/SL if 0 returned from semihosting.
306             - According to semihosting docs, if 0 returned from semihosting,
307               the system was unable to calculate the real value, so it's ok
308               to skip setting SP/SL to 0 here.
309             - Considering M-profile processors, We might want to initialize
310               SP by the first entry of vector table and return 0 to SYS_HEAPINFO
311               semihosting call, which will be skipped here.
312             - Considering R-profile processors there is no automatic SP init by hardware
313               so we need to initialize it by default value.  */
314         ldr     r3, .Lstack
315         cmp     r1, #0
316         beq     .LC26
317         mov     r3, r1
318 .LC26:
319         mov     sp, r3
321         /* r2 (SL value) will be used in _stack_init.  */
322         bl FUNCTION (_stack_init)
325 #else /* standalone */
326         /*  Set up the stack pointer to a fixed value. */
327         /*  Changes by toralf:
328             - Allow linker script to provide stack via __stack symbol - see
329               defintion of .Lstack
330             - Provide "hooks" that may be used by the application to add
331               custom init code - see .Lhwinit and .Lswinit.  */
333         ldr     r3, .Lstack
334         cmp     r3, #0
335 #ifdef __thumb2__
336         it      eq
337 #endif  
338 #ifdef THUMB1_ONLY
339         bne     .LC28
340         ldr     r3, .LC0
341 .LC28:
342 #else
343         ldreq   r3, .LC0
344 #endif
345         /* Note: This 'mov' is essential when starting in User, and ensures we
346                  always get *some* SP value for the initial mode, even if we
347                  have somehow missed it below (in which case it gets the same
348                  value as FIQ - not ideal, but better than nothing).  */
349         mov     sp, r3
351         /* We don't care of r2 value in standalone.  */
352         bl FUNCTION (_stack_init)
354 #endif
355 #endif
356         /* Zero the memory in the .bss section.  */
357         movs    a2, #0                  /* Second arg: fill value.  */
358         mov     fp, a2                  /* Null frame pointer.  */
359         mov     r7, a2                  /* Null frame pointer for Thumb.  */
360         
361         ldr     a1, .LC1                /* First arg: start of memory block.  */
362         ldr     a3, .LC2        
363         subs    a3, a3, a1              /* Third arg: length of block.  */
364         
366 #if __thumb__ && !defined(PREFER_THUMB)
367         /* Enter Thumb mode...  */
368         add     a4, pc, #1      /* Get the address of the Thumb block.  */
369         bx      a4              /* Go there and start Thumb decoding.  */
371         .code 16
372         .global __change_mode
373         .thumb_func
374 __change_mode:  
375 #endif
376         
377         bl      FUNCTION (memset)
378 #if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
379 /* Changes by toralf: Taken from libgloss/m68k/crt0.S
380    initialize target specific stuff. Only execute these
381    functions it they exist.  */
382         ldr     r3, .Lhwinit
383         cmp     r3, #0
384         beq     .LC24
385         indirect_call r3
386 .LC24:  
387         ldr     r3, .Lswinit
388         cmp     r3, #0
389         beq     .LC25
390         indirect_call r3
392 .LC25:  
393         movs    r0, #0          /* No arguments.  */
394         movs    r1, #0          /* No argv either.  */
395 #else
396         /* Need to set up standard file handles.  */
397         bl      FUNCTION (initialise_monitor_handles)
398         
399 #ifdef ARM_RDP_MONITOR
400         swi     SWI_GetEnv      /* Sets r0 to point to the command line.  */
401         movs    r1, r0
402 #else
403         movs    r0, #AngelSWI_Reason_GetCmdLine
404         ldr     r1, .LC30       /* Space for command line.  */
405 #ifdef THUMB_VXM
406         bkpt    AngelSWI
407 #else
408         AngelSWIAsm     AngelSWI
409 #endif
410         ldr     r1, .LC30
411         ldr     r1, [r1]
412 #endif
413         /*  Parse string at r1.  */
414         movs    r0, #0          /* Count of arguments so far.  */
415         /* Push a NULL argument onto the end of the list.  */
416 #ifdef __thumb__
417         push    {r0}
418 #else
419         stmfd   sp!, {r0}
420 #endif
421 .LC10:
422 /*  Skip leading blanks.  */
423 #ifdef __thumb__
424         ldrb    r3, [r1]
425         adds    r1, #1
426 #else
427         ldrb    r3, [r1], #1
428 #endif
429         cmp     r3, #0
430         beq     .LC12
431         cmp     r3, #' '
432         beq     .LC10
434 /* See whether we are scanning a string.  */
435         cmp     r3, #'\"'
436 #ifdef __thumb__
437         beq     .LC20
438         cmp     r3, #'\''
439         bne     .LC21
440 .LC20:
441         movs    r2, r3
442         b       .LC22
444 .LC21:
445         movs    r2, #' '        /* Terminator type.  */
446         subs    r1, r1, #1      /* Adjust back to point at start char.  */
447 .LC22:
448 #else
449         cmpne   r3, #'\''
450         moveq   r2, r3
451         movne   r2, #' '        /* Terminator type.  */
452         subne   r1, r1, #1      /* Adjust back to point at start char.  */
453 #endif
455 /*  Stack a pointer to the current argument.  */
456 #ifdef __thumb__
457         push    {r1}
458 #else
459         stmfd   sp!, {r1}
460 #endif
461         adds    r0, r0, #1
462 .LC11:
463 #ifdef __thumb__
464         ldrb    r3, [r1]
465         adds    r1, #1
466 #else
467         ldrb    r3, [r1], #1
468 #endif
469         cmp     r3, #0
470         beq     .LC12
471         cmp     r2, r3          /* Reached terminator ?  */
472         bne     .LC11
473         movs    r2, #0
474         subs    r3, r1, #1
475         strb    r2, [r3]        /* Terminate the arg string.  */
476         b       .LC10
478 .LC12:
479         mov     r1, sp          /* Point at stacked arg pointers.  */
480         /* We've now got the stacked args in order, reverse them.  */
481 #ifdef __thumb__
482         movs    r2, r0
483         lsls    r2, #2
484         add     r2, sp
485         mov     r3, sp
486 .LC15:  cmp     r2, r3
487         bls     .LC14
488         subs    r2, #4
489         ldr     r4, [r2]
490         ldr     r5, [r3]
491         str     r5, [r2]
492         str     r4, [r3]
493         adds    r3, #4
494         b       .LC15
495 .LC14:  
496         /* Ensure doubleword stack alignment.  */
497         mov     r4, sp
498         movs    r5, #7
499         bics    r4, r5
500         mov     sp, r4
501 #else
502         add     r2, sp, r0, LSL #2      /* End of args.  */
503         mov     r3, sp                  /* Start of args.  */
504 .LC13:  cmp     r2, r3
505         ldrhi   r4,[r2, #-4]            /* Reverse ends of list.  */
506         ldrhi   r5, [r3]
507         strhi   r5, [r2, #-4]!
508         strhi   r4, [r3], #4
509         bhi     .LC13
510         /* Ensure doubleword stack alignment.  */
511         bic     sp, sp, #7
512 #endif
513 #endif
515 #ifdef __USES_INITFINI__
516         /* Some arm/elf targets use the .init and .fini sections
517            to create constructors and destructors, and for these
518            targets we need to call the _init function and arrange
519            for _fini to be called at program exit.  */
520         movs    r4, r0
521         movs    r5, r1
522 #ifdef _LITE_EXIT
523         /* Make reference to atexit weak to avoid unconditionally pulling in
524            support code.  Refer to comments in __atexit.c for more details.  */
525         .weak   FUNCTION(atexit)
526         ldr     r0, .Latexit
527         cmp     r0, #0
528         beq     .Lweak_atexit
529 #endif
530         ldr     r0, .Lfini
531         bl      FUNCTION (atexit)
532 .Lweak_atexit:
533         bl      FUNCTION (_init)
534         movs    r0, r4
535         movs    r1, r5
536 #endif
537         bl      FUNCTION (main)
539         bl      FUNCTION (exit)         /* Should not return.  */
541 #if __thumb__ && !defined(PREFER_THUMB)
542         /* Come out of Thumb mode.  This code should be redundant.  */
543         mov     a4, pc
544         bx      a4
546         .code 32
547         .global change_back
548 change_back:
549         /* Halt the execution.  This code should never be executed.  */
550         /* With no debug monitor, this probably aborts (eventually).
551            With a Demon debug monitor, this halts cleanly.
552            With an Angel debug monitor, this will report 'Unknown SWI'.  */
553         swi     SWI_Exit
554 #endif
555         
556         FN_EH_END
558         /* For Thumb, constants must be after the code since only 
559            positive offsets are supported for PC relative addresses.  */
560         .align 0
561 .LC0:
562 #ifdef ARM_RDI_MONITOR
563         .word   HeapBase
564 #else
565 #ifndef ARM_RDP_MONITOR
566         /* Changes by toralf: Provide alternative "stack" variable whose value
567            may be defined externally; .Lstack will be used instead of .LC0 if
568            it points to a non-0 value. Also set up references to "hooks" that
569            may be used by the application to provide additional init code.  */
570 #ifdef __pe__
571         .word   0x800000
572 #else
573         .word   0x80000                 /* Top of RAM on the PIE board.  */
574 #endif
575 .Lhwinit:       
576         .word   FUNCTION (hardware_init_hook)
577 .Lswinit:
578         .word   FUNCTION (software_init_hook)
580         /* Set up defaults for the above variables in the form of weak symbols
581            - so that application will link correctly, and get value 0 in
582            runtime (meaning "ignore setting") for the variables, when the user
583            does not provide the symbols. (The linker uses a weak symbol if,
584            and only if, a normal version of the same symbol isn't provided
585            e.g. by a linker script or another object file.)  */
587         .weak FUNCTION (hardware_init_hook) 
588         .weak FUNCTION (software_init_hook)
589 #endif
590         
591 #endif
593 .Lstack:
594         .word   __stack
595         .weak   __stack
597 .LC1:
598         .word   __bss_start__
599 .LC2:
600         .word   __bss_end__
601 #ifdef __USES_INITFINI__
602 #ifdef _LITE_EXIT
603 .Latexit:
604         .word   FUNCTION(atexit)
606         /* Weak reference _fini in case of lite exit.  */
607         .weak   FUNCTION(_fini)
608 #endif
609 .Lfini:
610         .word   FUNCTION(_fini)
611 #endif
612 #ifdef ARM_RDI_MONITOR
613 .LC30:
614         .word   AngelSWIArgs
615 .LC31:
616         .word   __end__
618 /*  Workspace for Angel calls.  */
619         .data
620 /*  Data returned by monitor SWI.  */
621 .global __stack_base__
622 HeapBase:       .word   0
623 HeapLimit:      .word   0
624 __stack_base__: .word   0
625 StackLimit:     .word   0
626 CommandLine:    .space  256,0   /*  Maximum length of 255 chars handled.  */
627 AngelSWIArgs:
628         .word   CommandLine
629         .word   255
630 #endif
631         
632 #ifdef __pe__
633         .section .idata$3
634         .long   0,0,0,0,0,0,0,0
635 #endif