summaryrefslogtreecommitdiffstats
path: root/libffi/src
diff options
context:
space:
mode:
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-27 15:10:22 +0000
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-27 15:10:22 +0000
commitc11820d9ce8df3b99806d935aa83358324267447 (patch)
treea62193690e2806ff106cd3e9c9cf8928481f3800 /libffi/src
parent998ae78e9cc8d999b93e582374298be684334efa (diff)
downloadppe42-gcc-c11820d9ce8df3b99806d935aa83358324267447.tar.gz
ppe42-gcc-c11820d9ce8df3b99806d935aa83358324267447.zip
* src/arm/ffi.c (ffi_prep_cif_machdep): Handle functions that return
long long values. Round stack allocation to a multiple of 8 bytes for ATPCS compatibility. * src/arm/sysv.S (ffi_call_SYSV): Rework to avoid use of APCS register names. Handle returning long long types. Add Thumb and interworking support. Improve soft-float code. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89681 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi/src')
-rw-r--r--libffi/src/arm/ffi.c10
-rw-r--r--libffi/src/arm/sysv.S230
2 files changed, 166 insertions, 74 deletions
diff --git a/libffi/src/arm/ffi.c b/libffi/src/arm/ffi.c
index 37e3838246a..1f58d93ef19 100644
--- a/libffi/src/arm/ffi.c
+++ b/libffi/src/arm/ffi.c
@@ -108,6 +108,11 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
+ /* Round the stack up to a multiple of 8 bytes. This isn't needed
+ everywhere, but it is on some platforms, and it doesn't harm anything
+ when it isn't needed. */
+ cif->bytes = (cif->bytes + 7) & ~7;
+
/* Set the return type flag */
switch (cif->rtype->type)
{
@@ -118,6 +123,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = (unsigned) cif->rtype->type;
break;
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_UINT64:
+ cif->flags = (unsigned) FFI_TYPE_SINT64;
+ break;
+
default:
cif->flags = FFI_TYPE_INT;
break;
diff --git a/libffi/src/arm/sysv.S b/libffi/src/arm/sysv.S
index 0e4186114a9..c3471a8a2ff 100644
--- a/libffi/src/arm/sysv.S
+++ b/libffi/src/arm/sysv.S
@@ -40,87 +40,169 @@
#endif
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
#endif
+
+#ifdef __ELF__
+#define LSYM(x) .x
+#else
+#define LSYM(x) x
+#endif
+
+/* We need a better way of testing for this, but for now, this is all
+ we can do. */
+@ This selects the minimum architecture level required.
+#define __ARM_ARCH__ 3
+
+#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 4
+#endif
+
+#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 5
+#endif
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 6
+#endif
+
+#if __ARM_ARCH__ >= 5
+# define call_reg(x) blx x
+#elif defined (__ARM_ARCH_4T__)
+# define call_reg(x) mov lr, pc ; bx x
+# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
+# define __INTERWORKING__
+# endif
+#else
+# define call_reg(x) mov lr, pc ; mov pc, x
+#endif
+
+#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+.macro ARM_FUNC_START name
+ .text
+ .align 0
+ .thumb
+ .thumb_func
+ ENTRY(\name)
+ bx pc
+ nop
+ .arm
+/* A hook to tell gdb that we've switched to ARM mode. Also used to call
+ directly from other local arm routines. */
+_L__\name:
+.endm
+#else
+.macro ARM_FUNC_START name
+ .text
+ .align 0
+ .arm
+ ENTRY(\name)
+.endm
+#endif
+
+.macro RETLDM regs=, cond=, dirn=ia
+#if defined (__INTERWORKING__)
+ .ifc "\regs",""
+ ldr\cond lr, [sp], #4
+ .else
+ ldm\cond\dirn sp!, {\regs, lr}
+ .endif
+ bx\cond lr
+#else
+ .ifc "\regs",""
+ ldr\cond pc, [sp], #4
+ .else
+ ldm\cond\dirn sp!, {\regs, pc}
+ .endif
+#endif
+.endm
+
+
+ @ r0: ffi_prep_args
+ @ r1: &ecif
+ @ r2: cif->bytes
+ @ r3: fig->flags
+ @ sp+0: ecif.rvalue
+ @ sp+4: fn
+
+ @ This assumes we are using gas.
+ARM_FUNC_START ffi_call_SYSV
+ @ Save registers
+ stmfd sp!, {r0-r3, fp, lr}
+ mov fp, sp
+
+ @ Make room for all of the new args.
+ sub sp, fp, r2
+
+ @ Place all of the ffi_prep_args in position
+ mov ip, r0
+ mov r0, sp
+ @ r1 already set
+
+ @ Call ffi_prep_args(stack, &ecif)
+ call_reg(ip)
+
+ @ move first 4 parameters in registers
+ ldmia sp, {r0-r3}
+
+ @ and adjust stack
+ ldr ip, [fp, #8]
+ cmp ip, #16
+ movhs ip, #16
+ add sp, sp, ip
+
+ @ call (fn) (...)
+ ldr ip, [fp, #28]
+ call_reg(ip)
-.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
+ @ Remove the space we pushed for the args
+ mov sp, fp
+
+ @ Load r2 with the pointer to storage for the return value
+ ldr r2, [sp, #24]
+
+ @ Load r3 with the return type code
+ ldr r3, [sp, #12]
+
+ @ If the return value pointer is NULL, assume no return value.
+ cmp r2, #0
+ beq LSYM(Lepilogue)
+
+@ return INT
+ cmp r3, #FFI_TYPE_INT
#ifdef __SOFTFP__
- streq a1, [a3]
-#else
- stfeqs f0, [a3]
+ cmpne r3, #FFI_TYPE_FLOAT
#endif
- beq epilogue
+ streq r0, [r2]
+ beq LSYM(Lepilogue)
-# return DOUBLE or LONGDOUBLE
- cmp a4, #FFI_TYPE_DOUBLE
+ @ return INT64
+ cmp r3, #FFI_TYPE_SINT64
#ifdef __SOFTFP__
- stmeqia a3, {a1, a2}
-#else
- stfeqd f0, [a3]
+ cmpne r3, #FFI_TYPE_DOUBLE
+#endif
+ stmeqia r2, {r0, r1}
+
+#ifndef __SOFTFP__
+ beq LSYM(Lepilogue)
+
+@ return FLOAT
+ cmp r3, #FFI_TYPE_FLOAT
+ stfeqs f0, [r2]
+ beq LSYM(Lepilogue)
+
+@ return DOUBLE or LONGDOUBLE
+ cmp r3, #FFI_TYPE_DOUBLE
+ stfeqd f0, [r2]
#endif
-epilogue:
- ldmfd sp!, {a1-a4, fp, pc}
+LSYM(Lepilogue):
+ RETLDM "r0-r3,fp"
.ffi_call_SYSV_end:
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
OpenPOWER on IntegriCloud