1 /* -----------------------------------------------------------------------
2 sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
3 Copyright (c) 2011 Plausible Labs Cooperative, Inc.
5 ARM Foreign Function Interface
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
29 #include <fficonfig.h>
31 #ifdef HAVE_MACHINE_ASM_H
32 #include <machine/asm.h>
34 #ifdef __USER_LABEL_PREFIX__
35 #define CONCAT1(a, b) CONCAT2(a, b)
36 #define CONCAT2(a, b) a ## b
38 /* Use the right prefix for global labels. */
39 #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
44 #define ENTRY(x) .globl _##x; _##x:
46 #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
47 #endif /* __APPLE__ */
56 /* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
57 Function Call Guide */
62 /* We need a better way of testing for this, but for now, this is all
64 @ This selects the minimum architecture level required.
65 #define __ARM_ARCH__ 3
67 #if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
69 # define __ARM_ARCH__ 4
72 #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
73 || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
74 || defined(__ARM_ARCH_5TEJ__)
76 # define __ARM_ARCH__ 5
79 #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
80 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
81 || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
82 || defined(__ARM_ARCH_6M__)
84 # define __ARM_ARCH__ 6
87 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
88 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
89 || defined(__ARM_ARCH_7EM__)
91 # define __ARM_ARCH__ 7
95 # define call_reg(x) blx x
96 #elif defined (__ARM_ARCH_4T__)
97 # define call_reg(x) mov lr, pc ; bx x
98 # if defined(__thumb__) || defined(__THUMB_INTERWORK__)
99 # define __INTERWORKING__
102 # define call_reg(x) mov lr, pc ; mov pc, x
105 /* Conditionally compile unwinder directives. */
114 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
115 #define ARM_FUNC_START(name) \
127 #define ARM_FUNC_START(name) \
135 .macro RETLDM regs=, cond=, dirn=ia
136 #if defined (__INTERWORKING__)
138 ldr\cond lr, [sp], #4
140 ldm\cond\dirn sp!, {\regs, lr}
145 ldr\cond pc, [sp], #4
147 ldm\cond\dirn sp!, {\regs, pc}
158 @ This assumes we are using gas.
159 ARM_FUNC_START(ffi_call_SYSV)
161 stmfd sp!, {r0-r3, fp, lr}
162 UNWIND .save {r0-r3, fp, lr}
167 @ Make room for all of the new args.
170 @ Place all of the ffi_prep_args in position
174 @ Call ffi_prep_args(stack, &ecif)
175 bl CNAME(ffi_prep_args_SYSV)
177 @ move first 4 parameters in registers
181 sub lr, fp, sp @ cif->bytes == fp - sp
182 ldr ip, [fp] @ load fn() in advance
190 @ Remove the space we pushed for the args
193 @ Load r2 with the pointer to storage for the return value
196 @ Load r3 with the return type code
199 @ If the return value pointer is NULL, assume no return value.
204 cmp r3, #FFI_TYPE_INT
205 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
206 cmpne r3, #FFI_TYPE_FLOAT
212 cmp r3, #FFI_TYPE_SINT64
213 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
214 cmpne r3, #FFI_TYPE_DOUBLE
218 #if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
222 cmp r3, #FFI_TYPE_FLOAT
226 @ return DOUBLE or LONGDOUBLE
227 cmp r3, #FFI_TYPE_DOUBLE
232 #if defined (__INTERWORKING__)
233 ldmia sp!, {r0-r3,fp, lr}
236 ldmia sp!, {r0-r3,fp, pc}
242 .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
247 unsigned int FFI_HIDDEN
248 ffi_closure_inner (closure, respp, args)
249 ffi_closure *closure;
254 ARM_FUNC_START(ffi_closure_SYSV)
258 UNWIND .save {r0, lr}
264 bl CNAME(ffi_closure_inner)
265 cmp r0, #FFI_TYPE_INT
268 cmp r0, #FFI_TYPE_FLOAT
269 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
275 cmp r0, #FFI_TYPE_DOUBLE
276 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
282 cmp r0, #FFI_TYPE_LONGDOUBLE
283 #if defined(__SOFTFP__) || defined(__ARM_EABI__)
289 cmp r0, #FFI_TYPE_SINT64
302 #if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
314 .ffi_closure_SYSV_end:
317 .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
321 /* Below are VFP hard-float ABI call and closure implementations.
322 Add VFP FPU directive here. This is only compiled into the library
333 ARM_FUNC_START(ffi_call_VFP)
335 stmfd sp!, {r0-r3, fp, lr}
336 UNWIND .save {r0-r3, fp, lr}
340 @ Make room for all of the new args.
343 @ Make room for loading VFP args
346 @ Place all of the ffi_prep_args in position
349 sub r2, fp, #64 @ VFP scratch space
351 @ Call ffi_prep_args(stack, &ecif, vfp_space)
352 bl CNAME(ffi_prep_args_VFP)
354 @ Load VFP register args if needed
359 @ Load only d0 if possible
366 @ move first 4 parameters in registers
370 sub lr, ip, sp @ cif->bytes == (fp - 64) - sp
371 ldr ip, [fp] @ load fn() in advance
379 @ Remove the space we pushed for the args
382 @ Load r2 with the pointer to storage for
386 @ Load r3 with the return type code
389 @ If the return value pointer is NULL,
390 @ assume no return value.
392 beq LSYM(Lepilogue_vfp)
394 cmp r3, #FFI_TYPE_INT
396 beq LSYM(Lepilogue_vfp)
398 cmp r3, #FFI_TYPE_SINT64
400 beq LSYM(Lepilogue_vfp)
402 cmp r3, #FFI_TYPE_FLOAT
404 beq LSYM(Lepilogue_vfp)
406 cmp r3, #FFI_TYPE_DOUBLE
408 beq LSYM(Lepilogue_vfp)
410 cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT
411 cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
419 .size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
422 ARM_FUNC_START(ffi_closure_VFP)
428 UNWIND .save {r0, lr}
435 bl CNAME(ffi_closure_inner)
437 cmp r0, #FFI_TYPE_INT
440 cmp r0, #FFI_TYPE_FLOAT
443 cmp r0, #FFI_TYPE_DOUBLE
444 cmpne r0, #FFI_TYPE_LONGDOUBLE
447 cmp r0, #FFI_TYPE_SINT64
448 beq .Lretlonglong_vfp
450 cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT
451 beq .Lretfloat_struct_vfp
453 cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
454 beq .Lretdouble_struct_vfp
456 .Lclosure_epilogue_vfp:
462 b .Lclosure_epilogue_vfp
465 b .Lclosure_epilogue_vfp
468 b .Lclosure_epilogue_vfp
471 b .Lclosure_epilogue_vfp
472 .Lretfloat_struct_vfp:
474 b .Lclosure_epilogue_vfp
475 .Lretdouble_struct_vfp:
477 b .Lclosure_epilogue_vfp
479 .ffi_closure_VFP_end:
481 .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
484 ENTRY(ffi_arm_trampoline)
489 #if defined __ELF__ && defined __linux__
490 .section .note.GNU-stack,"",%progbits