1 /* -----------------------------------------------------------------------
2 sysv.S - Copyright (c) 1998 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__)
72 # define __ARM_ARCH__ 6
76 # define call_reg(x) blx x
77 #elif defined (__ARM_ARCH_4T__)
78 # define call_reg(x) mov lr, pc ; bx x
79 # if defined(__thumb__) || defined(__THUMB_INTERWORK__)
80 # define __INTERWORKING__
83 # define call_reg(x) mov lr, pc ; mov pc, x
86 /* Conditionally compile unwinder directives. */
94 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
95 .macro ARM_FUNC_START name
105 /* A hook to tell gdb that we've switched to ARM mode. Also used to call
106 directly from other local arm routines. */
110 .macro ARM_FUNC_START name
119 .macro RETLDM regs=, cond=, dirn=ia
120 #if defined (__INTERWORKING__)
122 ldr\cond lr, [sp], #4
124 ldm\cond\dirn sp!, {\regs, lr}
129 ldr\cond pc, [sp], #4
131 ldm\cond\dirn sp!, {\regs, pc}
144 @ This assumes we are using gas.
145 ARM_FUNC_START ffi_call_SYSV
147 stmfd sp!, {r0-r3, fp, lr}
148 UNWIND .save {r0-r3, fp, lr}
153 @ Make room for all of the new args.
156 @ Place all of the ffi_prep_args in position
161 @ Call ffi_prep_args(stack, &ecif)
164 @ move first 4 parameters in registers
177 @ Remove the space we pushed for the args
180 @ Load r2 with the pointer to storage for the return value
183 @ Load r3 with the return type code
186 @ If the return value pointer is NULL, assume no return value.
191 cmp r3, #FFI_TYPE_INT
193 cmpne r3, #FFI_TYPE_FLOAT
199 cmp r3, #FFI_TYPE_SINT64
201 cmpne r3, #FFI_TYPE_DOUBLE
209 cmp r3, #FFI_TYPE_FLOAT
213 @ return DOUBLE or LONGDOUBLE
214 cmp r3, #FFI_TYPE_DOUBLE
223 .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
226 unsigned int FFI_HIDDEN
227 ffi_closure_SYSV_inner (closure, respp, args)
228 ffi_closure *closure;
233 ARM_FUNC_START ffi_closure_SYSV
237 UNWIND .save {r0, lr}
243 bl ffi_closure_SYSV_inner
244 cmp r0, #FFI_TYPE_INT
247 cmp r0, #FFI_TYPE_FLOAT
254 cmp r0, #FFI_TYPE_DOUBLE
261 cmp r0, #FFI_TYPE_LONGDOUBLE
268 cmp r0, #FFI_TYPE_SINT64
293 .ffi_closure_SYSV_end:
295 .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
297 #if defined __ELF__ && defined __linux__
298 .section .note.GNU-stack,"",%progbits