summaryrefslogtreecommitdiff
path: root/libffi.old/src/arm/sysv.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi.old/src/arm/sysv.S')
-rw-r--r--libffi.old/src/arm/sysv.S127
1 files changed, 127 insertions, 0 deletions
diff --git a/libffi.old/src/arm/sysv.S b/libffi.old/src/arm/sysv.S
new file mode 100644
index 0000000..0e41861
--- /dev/null
+++ b/libffi.old/src/arm/sysv.S
@@ -0,0 +1,127 @@
+/* -----------------------------------------------------------------------
+ sysv.S - Copyright (c) 1998 Red Hat, 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 CYGNUS SOLUTIONS 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>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+#ifdef __USER_LABEL_PREFIX__
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+#define CNAME(x) x
+#endif
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+.text
+
+ # a1: ffi_prep_args
+ # a2: &ecif
+ # a3: cif->bytes
+ # a4: fig->flags
+ # sp+0: ecif.rvalue
+ # sp+4: fn
+
+ # This assumes we are using gas.
+ENTRY(ffi_call_SYSV)
+ # Save registers
+ stmfd sp!, {a1-a4, fp, lr}
+ mov fp, sp
+
+ # Make room for all of the new args.
+ sub sp, fp, a3
+
+ # Place all of the ffi_prep_args in position
+ mov ip, a1
+ mov a1, sp
+ # a2 already set
+
+ # And call
+ mov lr, pc
+ mov pc, ip
+
+ # move first 4 parameters in registers
+ ldr a1, [sp, #0]
+ ldr a2, [sp, #4]
+ ldr a3, [sp, #8]
+ ldr a4, [sp, #12]
+
+ # and adjust stack
+ ldr ip, [fp, #8]
+ cmp ip, #16
+ movge ip, #16
+ add sp, sp, ip
+
+ # call function
+ mov lr, pc
+ ldr pc, [fp, #28]
+
+ # Remove the space we pushed for the args
+ mov sp, fp
+
+ # Load a3 with the pointer to storage for the return value
+ ldr a3, [sp, #24]
+
+ # Load a4 with the return type code
+ ldr a4, [sp, #12]
+
+ # If the return value pointer is NULL, assume no return value.
+ cmp a3, #0
+ beq epilogue
+
+# return INT
+ cmp a4, #FFI_TYPE_INT
+ streq a1, [a3]
+ beq epilogue
+
+# return FLOAT
+ cmp a4, #FFI_TYPE_FLOAT
+#ifdef __SOFTFP__
+ streq a1, [a3]
+#else
+ stfeqs f0, [a3]
+#endif
+ beq epilogue
+
+# return DOUBLE or LONGDOUBLE
+ cmp a4, #FFI_TYPE_DOUBLE
+#ifdef __SOFTFP__
+ stmeqia a3, {a1, a2}
+#else
+ stfeqd f0, [a3]
+#endif
+
+epilogue:
+ ldmfd sp!, {a1-a4, fp, pc}
+
+.ffi_call_SYSV_end:
+ .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+