Akos Kiss 4b9e458f44 Add support for init/fini arrays to libc (#1725)
The arrays contain the addresses of functions annotated with
constructor or destructor attributes. The support is optional,
requires FEATURE_INIT_FINI cmake option to be set. As of now, the
option is _not_ available in tools/build.py directly, only via
`--cmake-param="-DFEATURE_INIT_FINI=ON"`.

JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
2017-04-13 17:18:17 +02:00

193 lines
3.8 KiB
C

/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ASM_ARM_H
#define ASM_ARM_H
/*
* mov syscall_no (%r0) -> %r7
* svc #0
*/
#define SYSCALL_0 \
push {r4-r12, lr}; \
\
mov r7, r0; \
\
svc #0; \
\
pop {r4-r12, pc};
/*
* mov syscall_no (%r0) -> %r7
* mov arg1 (%r1) -> %r0
* svc #0
*/
#define SYSCALL_1 \
push {r4-r12, lr}; \
\
mov r7, r0; \
mov r0, r1; \
\
svc #0; \
\
pop {r4-r12, pc};
/*
* mov syscall_no (%r0) -> %r7
* mov arg1 (%r1) -> %r0
* mov arg2 (%r2) -> %r1
* svc #0
*/
#define SYSCALL_2 \
push {r4-r12, lr}; \
\
mov r7, r0; \
mov r0, r1; \
mov r1, r2; \
\
svc #0; \
\
pop {r4-r12, pc};
/*
* mov syscall_no (%r0) -> %r7
* mov arg1 (%r1) -> %r0
* mov arg2 (%r2) -> %r1
* mov arg3 (%r3) -> %r2
* svc #0
*/
#define SYSCALL_3 \
push {r4-r12, lr}; \
\
mov r7, r0; \
mov r0, r1; \
mov r1, r2; \
mov r2, r3; \
\
svc #0; \
\
pop {r4-r12, pc};
#ifdef ENABLE_INIT_FINI
/*
* bl libc_init_array
*/
#define _INIT \
bl libc_init_array;
#else /* !ENABLE_INIT_FINI */
#define _INIT
#endif /* ENABLE_INIT_FINI */
/*
* bl libc_init_array
*
* ldr argc ([sp + 0x0]) -> r0
* add argv (sp + 0x4) -> r1
* bl main
*
* bl exit
*
* infinite loop
*/
#define _START \
_INIT; \
\
ldr r0, [sp, #0]; \
add r1, sp, #4; \
bl main; \
\
bl exit; \
1: \
b 1b;
/**
* If hard-float mode:
* store s16-s31 vfp registers to buffer, pointed with r0 register,
* and increase the register on size of stored data.
*/
#ifdef __TARGET_HOST_ARMv7_HARD_FLOAT
# define _STORE_VFP_S16_S31_IF_HARD_FLOAT \
vstm r0!, {s16 - s31};
# define _LOAD_VFP_S16_S31_IF_HARD_FLOAT \
vldm r0!, {s16 - s31};
#else /* !__TARGET_HOST_ARMv7_HARD_FLOAT */
# define _STORE_VFP_S16_S31_IF_HARD_FLOAT
# define _LOAD_VFP_S16_S31_IF_HARD_FLOAT
#endif /* __TARGET_HOST_ARMv7_HARD_FLOAT */
/*
* setjmp
*
* According to procedure call standard for the ARM architecture, the following
* registers are callee-saved, and so need to be stored in context:
* - r4 - r11
* - sp
* - s16 - s31
*
* Also, we should store:
* - lr
*
* stmia {r4-r11, sp, lr} -> jmp_buf_0 (r0)!
*
* If hard-float build
* vstm {s16-s31} -> jmp_buf_32 (r0)!
*
* mov r0, #0
*
* bx lr
*/
#define _SETJMP \
stmia r0!, {r4 - r11, sp, lr}; \
\
_STORE_VFP_S16_S31_IF_HARD_FLOAT \
\
mov r0, #0; \
\
bx lr;
/*
* longjmp
*
* See also:
* _SETJMP
*
* ldmia jmp_buf_0 (r0)! -> {r4-r11, sp, lr}
*
* If hard-float build
* vldm jmp_buf_32 (r0)! -> {s16-s31}
*
* mov r1 -> r0
* cmp r0, #0
* bne 1f
* mov #1 -> r0
* 1:
*
* bx lr
*/
#define _LONGJMP \
ldmia r0!, {r4 - r11, sp, lr}; \
\
_LOAD_VFP_S16_S31_IF_HARD_FLOAT \
\
mov r0, r1; \
cmp r0, #0; \
bne 1f; \
mov r0, #1; \
1: \
\
bx lr;
#endif /* !ASM_ARM_H */