source: trunk/libs/newlib/src/libgloss/aarch64/crt0.S @ 667

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

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

File size: 8.3 KB
Line 
1/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.  All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions
5 are met:
6 1. Redistributions of source code must retain the above copyright
7    notice, this list of conditions and the following disclaimer.
8 2. Redistributions in binary form must reproduce the above copyright
9    notice, this list of conditions and the following disclaimer in the
10    documentation and/or other materials provided with the distribution.
11 3. The name of the company may not be used to endorse or promote
12    products derived from this software without specific prior written
13    permission.
14
15 THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
25
26#include "newlib.h"
27#include "svc.h"
28
29/* ANSI concatenation macros.  */
30#define CONCAT(a, b) CONCAT2(a, b)
31#define CONCAT2(a, b) a ## b
32
33#ifdef __USER_LABEL_PREFIX__
34#define FUNCTION( name ) CONCAT (__USER_LABEL_PREFIX__, name)
35#else
36#error __USER_LABEL_PREFIX is not defined
37#endif
38
39#ifdef HAVE_INITFINI_ARRAY
40#define _init   __libc_init_array
41#define _fini   __libc_fini_array
42#endif
43
44/* In ELF64, the large addressing model is used and R_AARCH64_ABS64
45   reloc is generated to relocate a 64-bit address.  Since 64-bit
46   relocation is not available in ELF32, in order to have
47   a single code path for both ELF64 and ELF32 classes, we synthesize
48   a 64-bit relocation by using R_AARCH64_P32_ABS32 on one of the two
49   .word directives, depending on the endianness.  */
50
51.macro GEN_DWORD name
52#if defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
53        .word \name
54        .word 0
55#elif defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
56        .word 0
57        .word \name
58#else
59        .dword \name
60#endif
61.endm
62
63/* Help tackle the pointer size difference between ELF64 and ELF32.  */
64#ifdef __ILP32__
65#define PTR_REG(n)      w##n
66#define PTR_SIZE        4
67#define PTR_LOG_SIZE    2
68#else
69#define PTR_REG(n)      x##n
70#define PTR_SIZE        8
71#define PTR_LOG_SIZE    3
72#endif
73
74        .text
75.macro FUNC_START name
76        .global \name
77\name:
78.endm
79
80        .align  2
81
82        FUNC_START      _mainCRTStartup
83        FUNC_START      _start
84
85/* Start by setting up a stack */
86#ifdef ARM_RDI_MONITOR
87        /*  Issue Angel SVC to read memory info.
88
89            ptr to ptr to 4 words to receive data.  */
90        adr     x1, .LC0
91        mov     w0, #AngelSVC_Reason_HeapInfo
92        AngelSVCAsm AngelSVC
93
94        /* Initialise the stack pointer */
95
96        /* We currently choose to use the heap_limit field rather than
97           stack_base because the AEM validation model
98           returns sane values in the heap fields, but 0 in the stack
99           fields.  Note on the VE AEM model it is necessary to pass
100           command line options to the AEM in order to define the values
101           exposed here in the HeapInfo Angel call.  */
102        ldr     x0, .LC0                /* point at returned values */
103        ldr     x1, [x0, #8]            /* get heap_limit */
104
105        /* Set __heap_limit.  */
106#ifdef __ILP32__
107        /* Sanity check on the __heap_limit.  */
108        tst     x1, #0xffffffff00000000
109        bne     .Linsanepar
110#endif
111        cmp     x1, xzr
112        beq     .LC4
113        adrp    x2, __heap_limit
114        add     x2, x2, #:lo12:__heap_limit
115        str     x1, [x2]
116.LC4:
117
118        ldr     x1, [x0]                /* get heap_base */
119#ifdef __ILP32__
120        /* Sanity check on the heap base.  */
121        tst     x1, #0xffffffff00000000
122        bne     .Linsanepar
123#endif
124        cmp     x1, xzr
125        bne     .LC5
126        /* If the heap base value [x0, #0] is 0 then the heap base is actually
127           at the end of program data (i.e. __end__) */
128        ldr     x1, .LC3
129        str     x1, [x0, #0]
130.LC5:
131        ldr     x1, [x0, #16] /* get stack_base */
132
133#ifdef __ILP32__
134        /* Sanity check on the stack_base.  */
135        tst     x1, #0xffffffff00000000
136        bne     .Linsanepar
137#endif
138        cmp     x1, xzr
139        bne     .LC6
140#endif
141        ldr     x1, .Lstack /*  Set up the stack pointer to a fixed value */
142.LC6:
143
144        /* Ensure quad-word stack alignment.  */
145        and     x0, x1, #~15
146        mov     sp, x0
147
148        /* Setup an initial dummy frame with saved fp=0 and saved lr=0 */
149        mov     x29, 0
150        stp     x29, x29, [sp, #-16]!
151        mov     x29, sp
152
153       /* Initialize exception vector table, flatmap, etc.  */
154        bl      FUNCTION (_cpu_init_hook)
155
156        /* Zero the memory in the .bss section.  */
157        ldr     x0, .LC1                /* First arg: start of memory block */
158        mov     w1, #0                  /* Second arg: fill value */
159        ldr     x2, .LC2
160        sub     x2, x2, x0              /* Third arg: length of block */
161        bl      FUNCTION (memset)
162
163#ifdef ARM_RDI_MONITOR
164        /* Need to set up standard file handles */
165        bl      FUNCTION (initialise_monitor_handles)
166#endif
167
168        /* .init and .fini sections are used to create constructors
169           and destructors.  Here we call the _init function and arrange
170           for _fini to be called at program exit.  */
171        ldr     x0, .Lfini
172        bl      FUNCTION (atexit)
173
174        bl      FUNCTION (_init)
175
176#ifdef ARM_RDI_MONITOR
177        /* Fetch and parse the command line.  */
178        ldr     x1, .Lcmdline           /* Command line descriptor.  */
179        mov     w0, #AngelSVC_Reason_GetCmdLine
180        AngelSVCAsm AngelSVC
181        ldr     x8, .Lcmdline
182        ldr     x8, [x8]
183
184        mov     x0, #0          /* argc */
185        mov     x1, sp          /* argv */
186        ldr     x2, .Lenvp      /* envp */
187
188        /* Put NULL at end of argv array.  */
189        str     PTR_REG (0), [x1, #-PTR_SIZE]!
190
191        /* Skip leading blanks.  */
192.Lnext: ldrb    w3, [x8], #1
193        cbz     w3, .Lendstr
194        cmp     w3, #' '
195        b.eq    .Lnext
196
197        mov     w4, #' '        /* Terminator is space.  */
198
199        /* See whether we are scanning a quoted string by checking for
200           opening quote (" or ').  */
201        subs    w9, w3, #'\"'
202        sub     x8, x8, #1      /* Backup if no match.  */
203        ccmp    w9, #('\'' - '\"'), 0x4 /* FLG_Z */, ne
204        csel    w4, w3, w4, eq  /* Terminator = quote if match.  */
205        cinc    x8, x8, eq
206
207        /* Push arg pointer to argv, and bump argc.  */
208        str     PTR_REG (8), [x1, #-PTR_SIZE]!
209        add     x0, x0, #1
210
211        /* Find end of arg string.  */
2121:      ldrb    w3, [x8], #1
213        cbz     w3, .Lendstr
214        cmp     w4, w3          /* Reached terminator?  */
215        b.ne    1b
216
217        /* Terminate the arg string with NUL char.  */
218        mov     w4, #0
219        strb    w4, [x8, #-1]
220        b       .Lnext
221
222        /* Reverse argv array.  */
223.Lendstr:
224        add     x3, x1, #0                      /* sp = &argv[0] */
225        add     x4, x1, w0, uxtw #PTR_LOG_SIZE  /* ep = &argv[argc] */
226        cmp     x4, x3
227        b.lo    2f
2281:      ldr     PTR_REG (5), [x4, #-PTR_SIZE]   /* PTR_REG (5) = ep[-1] */
229        ldr     PTR_REG (6), [x3]               /* PTR_REG (6) = *sp */
230        str     PTR_REG (6), [x4, #-PTR_SIZE]!  /* *--ep = PTR_REG (6) */
231        str     PTR_REG (5), [x3], #PTR_SIZE    /* *sp++ = PTR_REG (5) */
232        cmp     x4, x3
233        b.hi    1b
2342:
235        /* Move sp to the 16B boundary below argv.  */
236        and     x4, x1, ~15
237        mov     sp, x4
238
239#else
240        mov     x0, #0  /* argc = 0 */
241        mov     x1, #0  /* argv = NULL */
242#endif
243
244        bl      FUNCTION (main)
245
246        b       FUNCTION (exit)         /* Cannot return.  */
247
248#if defined (ARM_RDI_MONITOR) && defined (__ILP32__)
249.Linsanepar:
250        /* Exit with 1 if the parameter is not within the 32-bit address
251           space.  */
252        mov     x1, ADP_Stopped_ApplicationExit & 0xff
253        movk    x1, ADP_Stopped_ApplicationExit >> 16, lsl #16
254        adrp    x0, HeapBase    /* Reuse to construct the parameter block.  */
255        add     x0, x0, #:lo12:HeapBase
256        str     x1, [x0]
257        mov     x1, 1
258        str     x1, [x0, #8]
259        mov     w1, #AngelSVC_Reason_ReportException
260        AngelSVCAsm AngelSVC
261        b       .
262#endif
263
264/* Function initializing exception vector table, flatmap, etc.
265   Declared as weak symbol so that user can override this definition
266   by linking in their own version of the function.  */
267        .weak FUNCTION (_cpu_init_hook)
268FUNCTION (_cpu_init_hook):
269        ret
270
271        .align 3
272#ifdef ARM_RDI_MONITOR
273.LC0:
274        GEN_DWORD HeapBase
275.LC3:
276        GEN_DWORD __end__
277#endif
278.Lstack:
279        GEN_DWORD __stack
280        .weak __stack
281
282.LC1:
283        GEN_DWORD __bss_start__
284.LC2:
285        GEN_DWORD __bss_end__
286.Lfini:
287        GEN_DWORD FUNCTION(_fini)
288#ifdef ARM_RDI_MONITOR
289.Lenvp:
290        GEN_DWORD env
291.Lcmdline:
292        GEN_DWORD AngelSVCArgs
293/*  Workspace for Angel calls.  */
294        .data
295        .align 3
296/*  Data returned by monitor SVC.  */
297#if defined(__ILP32__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
298        .set __stack_base__, StackBase + 4
299#else
300        .set __stack_base__, StackBase
301#endif
302        .global __stack_base__
303HeapBase:       .dword  0
304HeapLimit:      .dword  0
305StackBase:      .dword  0
306StackLimit:     .dword  0
307env:            .dword  0       /* Dummy environment array */
308CommandLine:    .space  256,0   /*  Maximum length of 255 chars handled.  */
309AngelSVCArgs:
310        GEN_DWORD CommandLine
311        .dword  255
312#endif
Note: See TracBrowser for help on using the repository browser.