aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/powerpc
diff options
context:
space:
mode:
authorAndreas Tobler <toa@pop.agri.ch>2002-03-07 18:24:42 +0000
committerDavid Edelsohn <edelsohn@gnu.org>2002-03-07 18:24:42 +0000
commit76842f218bf3360992a5e8a5a700eb4f402abf27 (patch)
tree2067fd3b0161aebe36726eaf4d9574b16aa6c1d3 /libffi/src/powerpc
parent5161e8886bab0e9c850a7264cd133d3f7b1cf7b3 (diff)
2002-03-07 Andreas Tobler <toa@pop.agri.ch>
David Edelsohn <edelsohn@gnu.org> * Makefile.am (EXTRA_DIST): Add Darwin and AIX closure files. (TARGET_SRC_POWERPC_AIX): Add aix_closure.S. (TARGET_SRC_POWERPC_DARWIN): Add darwin_closure.S. * Makefile.in: Regenerate. * include/ffi.h.in: Add AIX and Darwin closure definitions. * src/powerpc/ffi_darwin.c (ffi_prep_closure): New function. (flush_icache, flush_range): New functions. (ffi_closure_helper_DARWIN): New function. * src/powerpc/aix_closure.S: New file. * src/powerpc/darwin_closure.S: New file. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@50408 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi/src/powerpc')
-rw-r--r--libffi/src/powerpc/aix_closure.S251
-rw-r--r--libffi/src/powerpc/darwin_closure.S189
-rw-r--r--libffi/src/powerpc/ffi_darwin.c329
3 files changed, 768 insertions, 1 deletions
diff --git a/libffi/src/powerpc/aix_closure.S b/libffi/src/powerpc/aix_closure.S
new file mode 100644
index 00000000000..7fa96f1fc95
--- /dev/null
+++ b/libffi/src/powerpc/aix_closure.S
@@ -0,0 +1,251 @@
+/* -----------------------------------------------------------------------
+ aix_closures.S - Copyright (c) 2002 Free Software Foundation, Inc.
+ based on darwin_closures.S
+
+ PowerPC Assembly glue.
+
+ 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 AUTHOR 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.
+ ----------------------------------------------------------------------- */
+
+ .set r0,0
+ .set r1,1
+ .set r2,2
+ .set r3,3
+ .set r4,4
+ .set r5,5
+ .set r6,6
+ .set r7,7
+ .set r8,8
+ .set r9,9
+ .set r10,10
+ .set r11,11
+ .set r12,12
+ .set r13,13
+ .set r14,14
+ .set r15,15
+ .set r16,16
+ .set r17,17
+ .set r18,18
+ .set r19,19
+ .set r20,20
+ .set r21,21
+ .set r22,22
+ .set r23,23
+ .set r24,24
+ .set r25,25
+ .set r26,26
+ .set r27,27
+ .set r28,28
+ .set r29,29
+ .set r30,30
+ .set r31,31
+ .set f0,0
+ .set f1,1
+ .set f2,2
+ .set f3,3
+ .set f4,4
+ .set f5,5
+ .set f6,6
+ .set f7,7
+ .set f8,8
+ .set f9,9
+ .set f10,10
+ .set f11,11
+ .set f12,12
+ .set f13,13
+ .set f14,14
+ .set f15,15
+ .set f16,16
+ .set f17,17
+ .set f18,18
+ .set f19,19
+ .set f20,20
+ .set f21,21
+
+#define LIBFFI_ASM
+#define JUMPTARGET(name) name
+#define L(x) x
+ .file "aix_closure.S"
+ .toc
+LC..60:
+ .tc L..60[TC],L..60
+ .csect .text[PR]
+ .align 2
+
+.csect .text[PR]
+ .align 2
+ .globl ffi_closure_ASM
+ .globl .ffi_closure_ASM
+.csect ffi_closure_ASM[DS]
+
+ffi_closure_ASM:
+ .long .ffi_closure_ASM, TOC[tc0], 0
+ .csect .text[PR]
+.ffi_closure_ASM:
+
+ mflr r0 /* extract return address */
+ stw r0, 8(r1) /* save the return address */
+
+ /* 24 Bytes (Linkage Area) */
+ /* 32 Bytes (params) */
+ /* 104 Bytes (13*8 from FPR) */
+ /* 4 Bytes (result)
+ /* 164 Bytes */
+
+ stwu r1,-164(r1) /* skip over caller save area */
+
+/* we want to build up an area for the parameters passed */
+/* in registers (both floating point and integer) */
+
+ /* we store gpr 3 to gpr 10 (aligned to 4) */
+ /* in the parents outgoing area */
+ stw r3, 188(r1)
+ stw r4, 192(r1)
+ stw r5, 196(r1)
+ stw r6, 200(r1)
+ stw r7, 204(r1)
+ stw r8, 208(r1)
+ stw r9, 212(r1)
+ stw r10, 216(r1)
+
+ /* next save fpr 1 to fpr 13 (aligned to 8) */
+ stfd f1, 56(r1)
+ stfd f2, 64(r1)
+ stfd f3, 72(r1)
+ stfd f4, 80(r1)
+ stfd f5, 88(r1)
+ stfd f6, 96(r1)
+ stfd f7, 104(r1)
+ stfd f8, 112(r1)
+ stfd f9, 120(r1)
+ stfd f10, 128(r1)
+ stfd f11, 136(r1)
+ stfd f12, 144(r1)
+ stfd f13, 152(r1)
+
+ /* set up registers for the routine that actually does the work */
+ /* get the context pointer from the trampoline */
+ mr r3,r11
+
+ /* now load up the pointer to the result storage */
+ addi r4,r1,160
+
+ /* now load up the pointer to the saved gpr registers */
+ addi r5,r1,188
+
+ /* now load up the pointer to the saved fpr registers */
+ addi r6,r1,56
+
+ /* now load up the pointer to the outgoing parameter */
+ /* stack in the previous frame */
+ addi r7,r1,220
+
+ /* make the call */
+ bl .ffi_closure_helper_DARWIN
+ nop
+
+ /* now r3 contains the return type */
+ /* so use it to look up in a table */
+ /* so we know how to deal with each type */
+
+ /* look up the proper starting point in table */
+ /* by using return type as offset */
+ addi r5,r1,160 /* get pointer to results area */
+ lwz r4,LC..60(2) /* get address of jump table */
+ slwi r3,r3,2 /* now multiply return type by 4 */
+ lwzx r3,r4,r3 /* get the contents of that table value */
+ add r3,r3,r4 /* add contents of table to table address */
+ mtctr r3
+ bctr /* jump to it */
+
+L..60:
+ .long L..44-L..60 /* FFI_TYPE_VOID */
+ .long L..50-L..60 /* FFI_TYPE_INT */
+ .long L..47-L..60 /* FFI_TYPE_FLOAT */
+ .long L..46-L..60 /* FFI_TYPE_DOUBLE */
+ .long L..46-L..60 /* FFI_TYPE_LONGDOUBLE */
+ .long L..56-L..60 /* FFI_TYPE_UINT8 */
+ .long L..55-L..60 /* FFI_TYPE_SINT8 */
+ .long L..58-L..60 /* FFI_TYPE_UINT16 */
+ .long L..57-L..60 /* FFI_TYPE_SINT16 */
+ .long L..50-L..60 /* FFI_TYPE_UINT32 */
+ .long L..50-L..60 /* FFI_TYPE_SINT32 */
+ .long L..48-L..60 /* FFI_TYPE_UINT64 */
+ .long L..48-L..60 /* FFI_TYPE_SINT64 */
+ .long L..44-L..60 /* FFI_TYPE_STRUCT */
+ .long L..50-L..60 /* FFI_TYPE_POINTER */
+
+
+/* case double */
+L..46:
+ lfd f1,0(r5)
+ b L..44
+
+/* case float */
+L..47:
+ lfs f1,0(r5)
+ b L..44
+
+/* case long long */
+L..48:
+ lwz r3,0(r5)
+ lwz r4,4(r5)
+ b L..44
+
+/* case default / int32 / pointer */
+L..50:
+ lwz r3,0(r5)
+ b L..44
+
+/* case signed int8 */
+L..55:
+ addi r5,r5,3
+ lbz r3,0(r5)
+ slwi r3,r3,24
+ srawi r3,r3,24
+ b L..44
+
+/* case unsigned int8 */
+L..56:
+ addi r5,r5,3
+ lbz r3,0(r5)
+ b L..44
+
+/* case signed int16 */
+L..57:
+ addi r5,r5,2
+ lhz r3,0(r5)
+ extsh r3,r3
+ b L..44
+
+/* case unsigned int16 */
+L..58:
+ addi r5,r5,2
+ lhz r3,0(r5)
+
+/* case void / done */
+L..44:
+
+ addi r1,r1,164 /* restore stack pointer */
+ lwz r0,8(r1) /* get return address */
+ mtlr r0 /* reset link register */
+ blr
+
+/* END(ffi_closure_ASM) */
diff --git a/libffi/src/powerpc/darwin_closure.S b/libffi/src/powerpc/darwin_closure.S
new file mode 100644
index 00000000000..9e54d2231b9
--- /dev/null
+++ b/libffi/src/powerpc/darwin_closure.S
@@ -0,0 +1,189 @@
+/* -----------------------------------------------------------------------
+ darwin_closures.S - Copyright (c) 2002 Free Software Foundation, Inc.
+ based on ppc_closures.S
+
+ PowerPC Assembly glue.
+
+ 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 AUTHOR 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
+#define JUMPTARGET(name) name
+#define L(x) x
+.text
+.globl _ffi_closure_helper_DARWIN
+
+.text
+ .align 2
+.globl _ffi_closure_ASM
+
+.text
+ .align 2
+_ffi_closure_ASM:
+
+ mflr r0 /* extract return address */
+ stw r0, 8(r1) /* save the return address */
+
+ /* 24 Bytes (Linkage Area) */
+ /* 32 Bytes (outgoing parameter area, always reserved) */
+ /* 104 Bytes (13*8 from FPR) */
+ /* 4 Bytes (result)
+ /* 164 Bytes */
+
+ stwu r1,-164(r1) /* skip over caller save area */
+
+/* we want to build up an area for the parameters passed */
+/* in registers (both floating point and integer) */
+
+ /* we store gpr 3 to gpr 10 (aligned to 4) */
+ /* in the parents outgoing area */
+ stw r3, 188(r1)
+ stw r4, 192(r1)
+ stw r5, 196(r1)
+ stw r6, 200(r1)
+ stw r7, 204(r1)
+ stw r8, 208(r1)
+ stw r9, 212(r1)
+ stw r10, 216(r1)
+
+ /* we save fpr 1 to fpr 13 (aligned to 8) */
+ stfd f1, 56(r1)
+ stfd f2, 64(r1)
+ stfd f3, 72(r1)
+ stfd f4, 80(r1)
+ stfd f5, 88(r1)
+ stfd f6, 96(r1)
+ stfd f7, 104(r1)
+ stfd f8, 112(r1)
+ stfd f9, 120(r1)
+ stfd f10, 128(r1)
+ stfd f11, 136(r1)
+ stfd f12, 144(r1)
+ stfd f13, 152(r1)
+
+ /* set up registers for the routine that actually does the work */
+ /* get the context pointer from the trampoline */
+ mr r3,r11
+
+ /* now load up the pointer to the result storage */
+ addi r4,r1,160
+
+ /* now load up the pointer to the saved gpr registers */
+ addi r5,r1,188
+
+ /* now load up the pointer to the saved fpr registers */
+ addi r6,r1,56
+
+ /* now load up the pointer to the outgoing parameter */
+ /* stack in the previous frame */
+ addi r7,r1,220
+
+ /* make the call */
+ bl L(_ffi_closure_helper_DARWIN)
+
+ /* now r3 contains the return type */
+ /* so use it to look up in a table */
+ /* so we know how to deal with each type */
+
+ /* look up the proper starting point in table */
+ /* by using return type as offset */
+ addi r5,r1,160 /* get pointer to results area */
+ addis r4,0,ha16(.L60) /* get address of jump table */
+ addi r4,r4,lo16(.L60)
+ slwi r3,r3,2 /* now multiply return type by 4 */
+ lwzx r3,r4,r3 /* get the contents of that table value */
+ add r3,r3,r4 /* add contents of table to table address */
+ mtctr r3
+ bctr /* jump to it */
+
+.L60:
+ .long .L44-.L60 /* FFI_TYPE_VOID */
+ .long .L50-.L60 /* FFI_TYPE_INT */
+ .long .L47-.L60 /* FFI_TYPE_FLOAT */
+ .long .L46-.L60 /* FFI_TYPE_DOUBLE */
+ .long .L46-.L60 /* FFI_TYPE_LONGDOUBLE */
+ .long .L56-.L60 /* FFI_TYPE_UINT8 */
+ .long .L55-.L60 /* FFI_TYPE_SINT8 */
+ .long .L58-.L60 /* FFI_TYPE_UINT16 */
+ .long .L57-.L60 /* FFI_TYPE_SINT16 */
+ .long .L50-.L60 /* FFI_TYPE_UINT32 */
+ .long .L50-.L60 /* FFI_TYPE_SINT32 */
+ .long .L48-.L60 /* FFI_TYPE_UINT64 */
+ .long .L48-.L60 /* FFI_TYPE_SINT64 */
+ .long .L44-.L60 /* FFI_TYPE_STRUCT */
+ .long .L50-.L60 /* FFI_TYPE_POINTER */
+
+
+/* case double */
+.L46:
+ lfd f1,0(r5)
+ b .L44
+
+/* case float */
+.L47:
+ lfs f1,0(r5)
+ b .L44
+
+/* case long long */
+.L48:
+ lwz r3,0(r5)
+ lwz r4,4(r5)
+ b .L44
+
+/* case default / int32 / pointer */
+.L50:
+ lwz r3,0(r5)
+ b .L44
+
+/* case signed int8 */
+.L55:
+ addi r5,r5,3
+ lbz r3,0(r5)
+ extsb r3,r3
+ b .L44
+
+/* case unsigned int8 */
+.L56:
+ addi r5,r5,3
+ lbz r3,0(r5)
+ b .L44
+
+/* case signed int16 */
+.L57:
+ addi r5,r5,2
+ lhz r3,0(r5)
+ extsh r3,r3
+ b .L44
+
+/* case unsigned int16 */
+.L58:
+ addi r5,r5,2
+ lhz r3,0(r5)
+
+/* case void / done */
+.L44:
+
+ addi r1,r1,164 /* restore stack pointer */
+ lwz r0,8(r1) /* get return address */
+ mtlr r0 /* reset link register */
+ blr
+
+/* END(ffi_closure_ASM) */
+
diff --git a/libffi/src/powerpc/ffi_darwin.c b/libffi/src/powerpc/ffi_darwin.c
index 3cf504cf150..d80f6bfc6f0 100644
--- a/libffi/src/powerpc/ffi_darwin.c
+++ b/libffi/src/powerpc/ffi_darwin.c
@@ -6,7 +6,7 @@
Darwin ABI support (c) 2001 John Hornkvist
AIX ABI support (c) 2002 Free Software Foundation, Inc.
- $Id: ffi_darwin.c,v 1.2 2002/01/17 16:04:21 dje Exp $
+ $Id: ffi_darwin.c,v 1.3 2002/02/21 19:14:28 dje Exp $
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -31,6 +31,8 @@
#include <ffi_common.h>
#include <stdlib.h>
+
+extern void ffi_closure_ASM(void);
enum {
/* The assembly depends on these exact flags. */
@@ -382,3 +384,328 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
break;
}
}
+
+static void flush_icache(char *);
+static void flush_range(char *, int);
+
+/* The layout of a function descriptor. A C function pointer really */
+/* points to one of these. */
+
+typedef struct aix_fd_struct {
+ void *code_pointer;
+ void *toc;
+} aix_fd;
+
+/* here I'd like to add the stack frame layout we use in darwin_closure.S
+ * and aix_clsoure.S
+ *
+/* SP previous -> +---------------------------------------+ <--- child frame
+ | back chain to caller 4 |
+ +---------------------------------------+ 4
+ | saved CR 4 |
+ +---------------------------------------+ 8
+ | saved LR 4 |
+ +---------------------------------------+ 12
+ | reserved for compilers 4 |
+ +---------------------------------------+ 16
+ | reserved for binders 4 |
+ +---------------------------------------+ 20
+ | saved TOC pointer 4 |
+ +---------------------------------------+ 24
+ | always reserved 8*4=32 (revious GPRs)|
+ | according to the linkage convention |
+ | from AIX |
+ +---------------------------------------+ 56
+ | our FPR area 13*8=104 |
+ | f1 |
+ | . |
+ | f13 |
+ +---------------------------------------+ 160
+ | result area 4 |
+SP current --> +---------------------------------------+ 164 <- parent frame
+ | back chain to caller 4 |
+ +---------------------------------------+ 168
+ | saved CR 4 |
+ +---------------------------------------+ 172
+ | saved LR 4 |
+ +---------------------------------------+ 176
+ | reserved for compilers 4 |
+ +---------------------------------------+ 180
+ | reserved for binders 4 |
+ +---------------------------------------+ 184
+ | saved TOC pointer 4 |
+ +---------------------------------------+ 188
+ | always reserved 8*4=32 we store our |
+ | GPRs here |
+ | r3 |
+ | . |
+ | r10 |
+ +---------------------------------------+ 220
+ | PST area, overflow part |
+ +---------------------------------------+ xxx
+ | ???? |
+ +---------------------------------------+ xxx
+
+*/
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+ ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*),
+ void *user_data)
+{
+ unsigned int *tramp;
+ struct ffi_aix_trampoline_struct *tramp_aix;
+
+ switch (cif->abi)
+ {
+ case FFI_DARWIN:
+
+ FFI_ASSERT (cif->abi == FFI_DARWIN);
+
+ tramp = (unsigned int *) &closure->tramp[0];
+ tramp[0] = 0x7c0802a6; /* mflr r0 */
+ tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
+ tramp[4] = 0x7d6802a6; /* mflr r11 */
+ tramp[5] = 0x818b0000; /* lwz r12,0(r11) /* function address */
+ tramp[6] = 0x7c0803a6; /* mtlr r0 */
+ tramp[7] = 0x7d8903a6; /* mtctr r12 */
+ tramp[8] = 0x816b0004; /* lwz r11,4(r11) /* static chain */
+ tramp[9] = 0x4e800420; /* bctr */
+ *(void **) &tramp[2] = (void *)ffi_closure_ASM; /* function */
+ *(void **) &tramp[3] = (void *)closure; /* context */
+
+ closure->cif = cif;
+ closure->fun = fun;
+ closure->user_data = user_data;
+
+ /* Flush the icache. Only necessary on Darwin */
+ flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
+
+ break;
+
+ case FFI_AIX:
+
+ tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
+ aix_fd *fd = (aix_fd *)(void *)ffi_closure_ASM;
+
+ FFI_ASSERT (cif->abi == FFI_AIX);
+
+ tramp_aix->code_pointer = fd->code_pointer;
+ tramp_aix->toc = fd->toc;
+ tramp_aix->static_chain = closure;
+ closure->cif = cif;
+ closure->fun = fun;
+ closure->user_data = user_data;
+
+ default:
+
+ FFI_ASSERT(0);
+ break;
+ }
+ return FFI_OK;
+}
+
+static void
+flush_icache(char *addr)
+{
+#ifndef _AIX
+ __asm__ volatile (
+ "dcbf 0,%0;"
+ "sync;"
+ "icbi 0,%0;"
+ "sync;"
+ "isync;"
+ : : "r"(addr) : "memory");
+#endif
+}
+
+static void
+flush_range(char * addr1, int size)
+{
+#define MIN_LINE_SIZE 32
+ int i;
+ for (i = 0; i < size; i += MIN_LINE_SIZE)
+ flush_icache(addr1+i);
+ flush_icache(addr1+size-1);
+}
+
+int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*,
+ unsigned long*, unsigned long*);
+
+/* Basically the trampoline invokes ffi_closure_ASM, and on
+ * entry, r11 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_ASM invokes the
+ * following helper function to do most of the work
+ */
+
+int
+ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
+ unsigned long * pgr, unsigned long * pfr,
+ unsigned long * pst)
+{
+ /* rvalue is the pointer to space for return value in closure assembly */
+ /* pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM */
+ /* pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM */
+ /* pst is the pointer to outgoing parameter stack in original caller */
+
+ void ** avalue;
+ ffi_type ** arg_types;
+ long i, avn;
+ long nf; /* number of floating registers already used */
+ long ng; /* number of general registers already used */
+ ffi_cif * cif;
+ double temp;
+
+ cif = closure->cif;
+ avalue = alloca(cif->nargs * sizeof(void *));
+
+ nf = 0;
+ ng = 0;
+
+ /* Copy the caller's structure return value address so that the closure
+ returns the data directly to the caller. */
+ if (cif->rtype->type == FFI_TYPE_STRUCT)
+ {
+ rvalue = (void *)pgr;
+ ng++;
+ pgr++;
+ }
+
+ i = 0;
+ avn = cif->nargs;
+ arg_types = cif->arg_types;
+
+ /* Grab the addresses of the arguments from the stack frame. */
+ while (i < avn)
+ {
+ switch (arg_types[i]->type)
+ {
+ case FFI_TYPE_SINT8:
+ case FFI_TYPE_UINT8:
+ /* there are 8 gpr registers used to pass values */
+ if (ng < 8) {
+ avalue[i] = (((char *)pgr)+3);
+ ng++;
+ pgr++;
+ } else {
+ avalue[i] = (((char *)pst)+3);
+ pst++;
+ }
+ break;
+
+ case FFI_TYPE_SINT16:
+ case FFI_TYPE_UINT16:
+ /* there are 8 gpr registers used to pass values */
+ if (ng < 8) {
+ avalue[i] = (((char *)pgr)+2);
+ ng++;
+ pgr++;
+ } else {
+ avalue[i] = (((char *)pst)+2);
+ pst++;
+ }
+ break;
+
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_STRUCT:
+ /* there are 8 gpr registers used to pass values */
+ if (ng < 8) {
+ avalue[i] = pgr;
+ ng++;
+ pgr++;
+ } else {
+ avalue[i] = pst;
+ pst++;
+ }
+ break;
+
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_UINT64:
+ /* long long ints are passed in two gpr's if available or in
+ * the pst, one place is a bit odd, when a long long passes
+ * the boundary between gpr and pst area we have to increment
+ * the pst by one.
+ */
+ if (ng < 7) {
+ avalue[i] = pgr;
+ ng+=2;
+ pgr+=2;
+ } else if (ng == 7) {
+ avalue[i] = pgr;
+ ng++;
+ pgr++;
+ pst++;
+ } else {
+ avalue[i] = pst;
+ pst+=2;
+ }
+ break;
+
+ case FFI_TYPE_FLOAT:
+ /* a float value consumes a GPR
+ *
+ * there are 13 64bit floating point registers
+ */
+
+ if ((ng > 7) && (nf < 13)) {
+ pst++;
+ }
+ if (nf < 13) {
+ temp = *(double*)pfr;
+ *(float*)pfr = (float)temp;
+ avalue[i] = pfr;
+ nf++;
+ pfr+=2;
+ ng++;
+ pgr++;
+
+ } else {
+ avalue[i] = pst;
+ nf++;
+ pst++;
+ }
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ /* a double value consumes two GPRs
+ *
+ * there are 13 64bit floating point registers
+ */
+
+ if ((ng == 7) && (nf < 13)) {
+ pst++; /* if only one gpr is left the double steals it */
+ } else if ((ng > 7) && (nf < 13)) {
+ pst+=2; /* a double consumes two GPRs in Darwin/AIX */
+ }
+ if (nf < 13) {
+ avalue[i] = pfr;
+ nf++;
+ pfr+=2;
+ ng+=2;
+ pgr+=2;
+
+ } else {
+ avalue[i] = pst;
+ nf++;
+ pst+=2;
+ }
+ break;
+
+ default:
+ FFI_ASSERT(0);
+
+ }
+
+ i++;
+ }
+
+ (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+ /* Tell ffi_closure_ASM to perform return type promotions. */
+ return cif->rtype->type;
+
+}