204 lines
5.6 KiB
ArmAsm
204 lines
5.6 KiB
ArmAsm
|
/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. All rights reserved.
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or without
|
||
|
modification, are permitted provided that the following conditions
|
||
|
are met:
|
||
|
1. Redistributions of source code must retain the above copyright
|
||
|
notice, this list of conditions and the following disclaimer.
|
||
|
2. Redistributions in binary form must reproduce the above copyright
|
||
|
notice, this list of conditions and the following disclaimer in the
|
||
|
documentation and/or other materials provided with the distribution.
|
||
|
3. The name of the company may not be used to endorse or promote
|
||
|
products derived from this software without specific prior written
|
||
|
permission.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||
|
IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||
|
|
||
|
#include "newlib.h"
|
||
|
#include "svc.h"
|
||
|
|
||
|
/* ANSI concatenation macros. */
|
||
|
#define CONCAT(a, b) CONCAT2(a, b)
|
||
|
#define CONCAT2(a, b) a ## b
|
||
|
|
||
|
#ifdef __USER_LABEL_PREFIX__
|
||
|
#define FUNCTION( name ) CONCAT (__USER_LABEL_PREFIX__, name)
|
||
|
#else
|
||
|
#error __USER_LABEL_PREFIX is not defined
|
||
|
#endif
|
||
|
|
||
|
#ifdef HAVE_INITFINI_ARRAY
|
||
|
#define _init __libc_init_array
|
||
|
#define _fini __libc_fini_array
|
||
|
#endif
|
||
|
|
||
|
.text
|
||
|
.macro FUNC_START name
|
||
|
.global \name
|
||
|
\name:
|
||
|
.endm
|
||
|
|
||
|
.align 2
|
||
|
|
||
|
FUNC_START _mainCRTStartup
|
||
|
FUNC_START _start
|
||
|
FUNC_START start
|
||
|
|
||
|
/* Start by setting up a stack */
|
||
|
|
||
|
/* Issue Angel SVC to read memory info.
|
||
|
|
||
|
ptr to ptr to 4 words to receive data. */
|
||
|
adr x1, .LC0
|
||
|
mov w0, #AngelSVC_Reason_HeapInfo
|
||
|
AngelSVCAsm AngelSVC
|
||
|
|
||
|
/* Initialise the stack pointer */
|
||
|
|
||
|
/* We currently choose to use the heap_limit field rather than
|
||
|
stack_base because the AEM validation model
|
||
|
returns sane values in the heap fields, but 0 in the stack
|
||
|
fields. Note on the VE AEM model it is necessary to pass
|
||
|
command line options to the AEM in order to define the values
|
||
|
exposed here in the HeapInfo Angel call. */
|
||
|
ldr x0, .LC0 /* point at returned values */
|
||
|
ldr x0, [x0, #8] /* get heap_limit */
|
||
|
|
||
|
/* Ensure quad-word stack alignment. */
|
||
|
and x0, x0, #~15
|
||
|
mov sp, x0
|
||
|
|
||
|
/* Setup an initial dummy frame with saved fp=0 and saved lr=0 */
|
||
|
mov x29, 0
|
||
|
stp x29, x29, [sp, #-16]!
|
||
|
mov x29, sp
|
||
|
|
||
|
/* Initialize exception vector table, flatmap, etc. */
|
||
|
bl FUNCTION (_cpu_init_hook)
|
||
|
|
||
|
/* Zero the memory in the .bss section. */
|
||
|
ldr x0, .LC1 /* First arg: start of memory block */
|
||
|
mov w1, #0 /* Second arg: fill value */
|
||
|
ldr x2, .LC2
|
||
|
sub x2, x2, x0 /* Third arg: length of block */
|
||
|
bl FUNCTION (memset)
|
||
|
|
||
|
/* Need to set up standard file handles */
|
||
|
bl FUNCTION (initialise_monitor_handles)
|
||
|
|
||
|
/* .init and .fini sections are used to create constructors
|
||
|
and destructors. Here we call the _init function and arrange
|
||
|
for _fini to be called at program exit. */
|
||
|
ldr x0, .Lfini
|
||
|
bl FUNCTION (atexit)
|
||
|
|
||
|
bl FUNCTION (_init)
|
||
|
|
||
|
/* Fetch and parse the command line. */
|
||
|
adr x1, .Lcmdline /* Command line descriptor. */
|
||
|
mov w0, #AngelSVC_Reason_GetCmdLine
|
||
|
AngelSVCAsm AngelSVC
|
||
|
ldr x8, .Lcmdline
|
||
|
|
||
|
mov x0, #0 /* argc */
|
||
|
mov x1, sp /* argv */
|
||
|
ldr x2, .Lenvp /* envp */
|
||
|
|
||
|
/* Put NULL at end of argv array. */
|
||
|
str x0, [x1, #-8]!
|
||
|
|
||
|
/* Skip leading blanks. */
|
||
|
.Lnext: ldrb w3, [x8], #1
|
||
|
cbz w3, .Lendstr
|
||
|
cmp w3, #' '
|
||
|
b.eq .Lnext
|
||
|
|
||
|
mov w4, #' ' /* Terminator is space. */
|
||
|
|
||
|
/* See whether we are scanning a quoted string by checking for
|
||
|
opening quote (" or '). */
|
||
|
subs w9, w3, #'\"'
|
||
|
sub x8, x8, #1 /* Backup if no match. */
|
||
|
ccmp w9, #('\'' - '\"'), 0x4 /* FLG_Z */, ne
|
||
|
csel w4, w3, w4, eq /* Terminator = quote if match. */
|
||
|
cinc x8, x8, eq
|
||
|
|
||
|
/* Push arg pointer to argv, and bump argc. */
|
||
|
str x8, [x1, #-8]!
|
||
|
add x0, x0, #1
|
||
|
|
||
|
/* Find end of arg string. */
|
||
|
1: ldrb w3, [x8], #1
|
||
|
cbz w3, .Lendstr
|
||
|
cmp w4, w3 /* Reached terminator? */
|
||
|
b.ne 1b
|
||
|
|
||
|
/* Terminate the arg string with NUL char. */
|
||
|
mov w4, #0
|
||
|
strb w4, [x8, #-1]
|
||
|
b .Lnext
|
||
|
|
||
|
/* Reverse argv array. */
|
||
|
.Lendstr:
|
||
|
add x3, x1, #0 /* sp = &argv[0] */
|
||
|
add x4, x1, w0, uxtw #3 /* ep = &argv[argc] */
|
||
|
cmp x4, x3
|
||
|
b.lo 2f
|
||
|
1: ldr x5, [x4, #-8] /* x5 = ep[-1] */
|
||
|
ldr x6, [x3] /* x6 = *sp */
|
||
|
str x6, [x4, #-8]! /* *--ep = x6 */
|
||
|
str x5, [x3], #8 /* *sp++ = x5 */
|
||
|
cmp x4, x3
|
||
|
b.hi 1b
|
||
|
2:
|
||
|
/* Move sp to the 16B boundary below argv. */
|
||
|
and x4, x1, ~15
|
||
|
mov sp, x4
|
||
|
|
||
|
bl FUNCTION (main)
|
||
|
|
||
|
b FUNCTION (exit) /* Cannot return. */
|
||
|
|
||
|
/* Function initializing exception vector table, flatmap, etc.
|
||
|
Declared as weak symbol so that user can override this definition
|
||
|
by linking in their own version of the function. */
|
||
|
.weak FUNCTION (_cpu_init_hook)
|
||
|
FUNCTION (_cpu_init_hook):
|
||
|
ret
|
||
|
|
||
|
.align 3
|
||
|
.LC0:
|
||
|
.dword HeapBase
|
||
|
.LC1:
|
||
|
.dword __bss_start__
|
||
|
.LC2:
|
||
|
.dword __bss_end__
|
||
|
.Lfini:
|
||
|
.dword FUNCTION(_fini)
|
||
|
.Lenvp:
|
||
|
.dword env
|
||
|
.Lcmdline:
|
||
|
.dword CommandLine
|
||
|
.dword 255
|
||
|
|
||
|
/* Workspace for Angel calls. */
|
||
|
.data
|
||
|
.align 3
|
||
|
/* Data returned by monitor SVC. */
|
||
|
.global __stack_base__
|
||
|
HeapBase: .dword 0
|
||
|
HeapLimit: .dword 0
|
||
|
__stack_base__: .dword 0
|
||
|
StackLimit: .dword 0
|
||
|
env: .dword 0 /* Dummy environment array */
|
||
|
CommandLine: .space 256,0 /* Maximum length of 255 chars handled. */
|