aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/lib/libffi/src/arm/sysv.S
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--circuitpython/lib/libffi/src/arm/sysv.S335
1 files changed, 335 insertions, 0 deletions
diff --git a/circuitpython/lib/libffi/src/arm/sysv.S b/circuitpython/lib/libffi/src/arm/sysv.S
new file mode 100644
index 0000000..fd16589
--- /dev/null
+++ b/circuitpython/lib/libffi/src/arm/sysv.S
@@ -0,0 +1,335 @@
+/* -----------------------------------------------------------------------
+ sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+
+ ARM Foreign Function Interface
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
+
+/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */
+#ifndef __ARM_ARCH
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+ || defined(__ARM_ARCH_7EM__)
+# define __ARM_ARCH 7
+# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
+ || defined(__ARM_ARCH_6M__)
+# define __ARM_ARCH 6
+# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__)
+# define __ARM_ARCH 5
+# else
+# define __ARM_ARCH 4
+# endif
+#endif
+
+/* Conditionally compile unwinder directives. */
+.macro UNWIND text:vararg
+#ifdef __ARM_EABI__
+ \text
+#endif
+.endm
+#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
+ .cfi_sections .debug_frame
+#endif
+
+#define CONCAT(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X)
+#else
+# define CNAME(X) X
+#endif
+#ifdef __ELF__
+# define SIZE(X) .size CNAME(X), . - CNAME(X)
+# define TYPE(X, Y) .type CNAME(X), Y
+#else
+# define SIZE(X)
+# define TYPE(X, Y)
+#endif
+
+#define ARM_FUNC_START(name, gl) \
+ .align 3; \
+ .ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \
+ TYPE(name, %function); \
+ CNAME(name):
+
+#define ARM_FUNC_END(name) \
+ SIZE(name)
+
+/* Aid in defining a jump table with 8 bytes between entries. */
+.macro E index
+ .if . - 0b - 8*\index
+ .error "type table out of sync"
+ .endif
+.endm
+
+ .text
+ .syntax unified
+ .arm
+
+ /* We require interworking on LDM, which implies ARMv5T,
+ which implies the existance of BLX. */
+ .arch armv5t
+
+ /* Note that we use STC and LDC to encode VFP instructions,
+ so that we do not need ".fpu vfp", nor get that added to
+ the object file attributes. These will not be executed
+ unless the FFI_VFP abi is used. */
+
+ @ r0: stack
+ @ r1: frame
+ @ r2: fn
+ @ r3: vfp_used
+
+ARM_FUNC_START(ffi_call_VFP, 1)
+ UNWIND .fnstart
+ cfi_startproc
+
+ cmp r3, #3 @ load only d0 if possible
+ ldcle p11, cr0, [r0] @ vldrle d0, [sp]
+ ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
+ add r0, r0, #64 @ discard the vfp register args
+ /* FALLTHRU */
+ARM_FUNC_END(ffi_call_VFP)
+
+ARM_FUNC_START(ffi_call_SYSV, 1)
+ stm r1, {fp, lr}
+ mov fp, r1
+
+ @ This is a bit of a lie wrt the origin of the unwind info, but
+ @ now we've got the usual frame pointer and two saved registers.
+ UNWIND .save {fp,lr}
+ UNWIND .setfp fp, sp
+ cfi_def_cfa(fp, 8)
+ cfi_rel_offset(fp, 0)
+ cfi_rel_offset(lr, 4)
+
+ mov sp, r0 @ install the stack pointer
+ mov lr, r2 @ move the fn pointer out of the way
+ ldr ip, [fp, #16] @ install the static chain
+ ldmia sp!, {r0-r3} @ move first 4 parameters in registers.
+ blx lr @ call fn
+
+ @ Load r2 with the pointer to storage for the return value
+ @ Load r3 with the return type code
+ ldr r2, [fp, #8]
+ ldr r3, [fp, #12]
+
+ @ Deallocate the stack with the arguments.
+ mov sp, fp
+ cfi_def_cfa_register(sp)
+
+ @ Store values stored in registers.
+ .align 3
+ add pc, pc, r3, lsl #3
+ nop
+0:
+E ARM_TYPE_VFP_S
+ stc p10, cr0, [r2] @ vstr s0, [r2]
+ pop {fp,pc}
+E ARM_TYPE_VFP_D
+ stc p11, cr0, [r2] @ vstr d0, [r2]
+ pop {fp,pc}
+E ARM_TYPE_VFP_N
+ stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3}
+ pop {fp,pc}
+E ARM_TYPE_INT64
+ str r1, [r2, #4]
+ nop
+E ARM_TYPE_INT
+ str r0, [r2]
+ pop {fp,pc}
+E ARM_TYPE_VOID
+ pop {fp,pc}
+ nop
+E ARM_TYPE_STRUCT
+ pop {fp,pc}
+
+ cfi_endproc
+ UNWIND .fnend
+ARM_FUNC_END(ffi_call_SYSV)
+
+
+/*
+ int ffi_closure_inner_* (cif, fun, user_data, frame)
+*/
+
+ARM_FUNC_START(ffi_go_closure_SYSV, 1)
+ cfi_startproc
+ stmdb sp!, {r0-r3} @ save argument regs
+ cfi_adjust_cfa_offset(16)
+ ldr r0, [ip, #4] @ load cif
+ ldr r1, [ip, #8] @ load fun
+ mov r2, ip @ load user_data
+ b 0f
+ cfi_endproc
+ARM_FUNC_END(ffi_go_closure_SYSV)
+
+ARM_FUNC_START(ffi_closure_SYSV, 1)
+ UNWIND .fnstart
+ cfi_startproc
+ stmdb sp!, {r0-r3} @ save argument regs
+ cfi_adjust_cfa_offset(16)
+ ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
+ ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
+ ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
+0:
+ add ip, sp, #16 @ compute entry sp
+ sub sp, sp, #64+32 @ allocate frame
+ cfi_adjust_cfa_offset(64+32)
+ stmdb sp!, {ip,lr}
+
+ /* Remember that EABI unwind info only applies at call sites.
+ We need do nothing except note the save of the stack pointer
+ and the link registers. */
+ UNWIND .save {sp,lr}
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(lr, 4)
+
+ add r3, sp, #8 @ load frame
+ bl CNAME(ffi_closure_inner_SYSV)
+
+ @ Load values returned in registers.
+ add r2, sp, #8+64 @ load result
+ adr r3, CNAME(ffi_closure_ret)
+ add pc, r3, r0, lsl #3
+ cfi_endproc
+ UNWIND .fnend
+ARM_FUNC_END(ffi_closure_SYSV)
+
+ARM_FUNC_START(ffi_go_closure_VFP, 1)
+ cfi_startproc
+ stmdb sp!, {r0-r3} @ save argument regs
+ cfi_adjust_cfa_offset(16)
+ ldr r0, [ip, #4] @ load cif
+ ldr r1, [ip, #8] @ load fun
+ mov r2, ip @ load user_data
+ b 0f
+ cfi_endproc
+ARM_FUNC_END(ffi_go_closure_VFP)
+
+ARM_FUNC_START(ffi_closure_VFP, 1)
+ UNWIND .fnstart
+ cfi_startproc
+ stmdb sp!, {r0-r3} @ save argument regs
+ cfi_adjust_cfa_offset(16)
+ ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
+ ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
+ ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
+0:
+ add ip, sp, #16
+ sub sp, sp, #64+32 @ allocate frame
+ cfi_adjust_cfa_offset(64+32)
+ stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7}
+ stmdb sp!, {ip,lr}
+
+ /* See above. */
+ UNWIND .save {sp,lr}
+ cfi_adjust_cfa_offset(8)
+ cfi_rel_offset(lr, 4)
+
+ add r3, sp, #8 @ load frame
+ bl CNAME(ffi_closure_inner_VFP)
+
+ @ Load values returned in registers.
+ add r2, sp, #8+64 @ load result
+ adr r3, CNAME(ffi_closure_ret)
+ add pc, r3, r0, lsl #3
+ cfi_endproc
+ UNWIND .fnend
+ARM_FUNC_END(ffi_closure_VFP)
+
+/* Load values returned in registers for both closure entry points.
+ Note that we use LDM with SP in the register set. This is deprecated
+ by ARM, but not yet unpredictable. */
+
+ARM_FUNC_START(ffi_closure_ret, 0)
+ cfi_startproc
+ cfi_rel_offset(sp, 0)
+ cfi_rel_offset(lr, 4)
+0:
+E ARM_TYPE_VFP_S
+ ldc p10, cr0, [r2] @ vldr s0, [r2]
+ ldm sp, {sp,pc}
+E ARM_TYPE_VFP_D
+ ldc p11, cr0, [r2] @ vldr d0, [r2]
+ ldm sp, {sp,pc}
+E ARM_TYPE_VFP_N
+ ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
+ ldm sp, {sp,pc}
+E ARM_TYPE_INT64
+ ldr r1, [r2, #4]
+ nop
+E ARM_TYPE_INT
+ ldr r0, [r2]
+ ldm sp, {sp,pc}
+E ARM_TYPE_VOID
+ ldm sp, {sp,pc}
+ nop
+E ARM_TYPE_STRUCT
+ ldm sp, {sp,pc}
+ cfi_endproc
+ARM_FUNC_END(ffi_closure_ret)
+
+#if FFI_EXEC_TRAMPOLINE_TABLE
+
+/* ??? The iOS support should be updated. The first insn used to
+ be STMFD, but that's been moved into ffi_closure_SYSV. If the
+ writable page is put after this one we can make use of the
+ pc+8 feature of the architecture. We can also reduce the size
+ of the thunk to 8 and pack more of these into the page.
+
+ In the meantime, simply replace the STMFD with a NOP so as to
+ keep all the magic numbers the same within ffi.c. */
+
+ .align 12
+ARM_FUNC_START(ffi_closure_trampoline_table_page)
+.rept 4096 / 12
+ nop
+ ldr ip, [pc, #-4092]
+ ldr pc, [pc, #-4092]
+.endr
+
+#else
+
+ARM_FUNC_START(ffi_arm_trampoline, 1)
+0: adr ip, 0b
+ ldr pc, 1f
+1: .long 0
+ARM_FUNC_END(ffi_arm_trampoline)
+
+#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
+
+#if defined __ELF__ && defined __linux__
+ .section .note.GNU-stack,"",%progbits
+#endif