1 /* -----------------------------------------------------------------------
2 sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
4 ARM Foreign Function Interface
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 ``Software''), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 DEALINGS IN THE SOFTWARE.
25 ----------------------------------------------------------------------- */
28 #include <fficonfig.h>
30 #ifdef HAVE_MACHINE_ASM_H
31 #include <machine/asm.h>
33 #ifdef __USER_LABEL_PREFIX__
34 #define CONCAT1(a, b) CONCAT2(a, b)
35 #define CONCAT2(a, b) a ## b
37 /* Use the right prefix for global labels. */
38 #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
42 #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
51 /* We need a better way of testing for this, but for now, this is all
53 @ This selects the minimum architecture level required.
54 #define __ARM_ARCH__ 3
56 #if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
58 # define __ARM_ARCH__ 4
61 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
62 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
63 || defined(__ARM_ARCH_5TEJ__)
65 # define __ARM_ARCH__ 5
68 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
69 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
70 || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
71 || defined(__ARM_ARCH_6M__)
73 # define __ARM_ARCH__ 6
76 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
77 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
79 # define __ARM_ARCH__ 7
83 # define call_reg(x) blx x
84 #elif defined (__ARM_ARCH_4T__)
85 # define call_reg(x) mov lr, pc ; bx x
86 # if defined(__thumb__) || defined(__THUMB_INTERWORK__)
87 # define __INTERWORKING__
90 # define call_reg(x) mov lr, pc ; mov pc, x
93 /* Conditionally compile unwinder directives. */
101 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
102 .macro ARM_FUNC_START name
112 /* A hook to tell gdb that we've switched to ARM mode. Also used to call
113 directly from other local arm routines. */
117 .macro ARM_FUNC_START name
126 .macro RETLDM regs=, cond=, dirn=ia
127 #if defined (__INTERWORKING__)
129 ldr\cond lr, [sp], #4
131 ldm\cond\dirn sp!, {\regs, lr}
136 ldr\cond pc, [sp], #4
138 ldm\cond\dirn sp!, {\regs, pc}
151 @ This assumes we are using gas.
152 ARM_FUNC_START ffi_call_SYSV
154 stmfd sp!, {r0-r3, fp, lr}
155 UNWIND .save {r0-r3, fp, lr}
160 @ Make room for all of the new args.
163 @ Place all of the ffi_prep_args in position
168 @ Call ffi_prep_args(stack, &ecif)
171 @ move first 4 parameters in registers
184 @ Remove the space we pushed for the args
187 @ Load r2 with the pointer to storage for the return value
190 @ Load r3 with the return type code
193 @ If the return value pointer is NULL, assume no return value.
198 cmp r3, #FFI_TYPE_INT
199 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
200 cmpne r3, #FFI_TYPE_FLOAT
206 cmp r3, #FFI_TYPE_SINT64
207 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
208 cmpne r3, #FFI_TYPE_DOUBLE
212 #if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
216 cmp r3, #FFI_TYPE_FLOAT
220 @ return DOUBLE or LONGDOUBLE
221 cmp r3, #FFI_TYPE_DOUBLE
230 .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
233 unsigned int FFI_HIDDEN
234 ffi_closure_SYSV_inner (closure, respp, args)
235 ffi_closure *closure;
240 ARM_FUNC_START ffi_closure_SYSV
244 UNWIND .save {r0, lr}
250 bl ffi_closure_SYSV_inner
251 cmp r0, #FFI_TYPE_INT
254 cmp r0, #FFI_TYPE_FLOAT
255 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
261 cmp r0, #FFI_TYPE_DOUBLE
262 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
268 cmp r0, #FFI_TYPE_LONGDOUBLE
269 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
275 cmp r0, #FFI_TYPE_SINT64
288 #if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
300 .ffi_closure_SYSV_end:
302 .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
304 #if defined __ELF__ && defined __linux__
305 .section .note.GNU-stack,"",%progbits