aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/m68k/ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/m68k/ffi.c')
-rw-r--r--libffi/src/m68k/ffi.c214
1 files changed, 158 insertions, 56 deletions
diff --git a/libffi/src/m68k/ffi.c b/libffi/src/m68k/ffi.c
index 55f3a988bc4..600cf20527f 100644
--- a/libffi/src/m68k/ffi.c
+++ b/libffi/src/m68k/ffi.c
@@ -8,11 +8,23 @@
#include <ffi_common.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <asm/cachectl.h>
+
+void ffi_call_SYSV (extended_cif *,
+ unsigned, unsigned,
+ void *, void (*fn) ());
+void *ffi_prep_args (void *stack, extended_cif *ecif);
+void ffi_closure_SYSV (ffi_closure *);
+void ffi_closure_struct_SYSV (ffi_closure *);
+unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
+ void *resp, void *args);
/* ffi_prep_args is called by the assembly routine once stack space has
been allocated for the function's arguments. */
-static void *
+void *
ffi_prep_args (void *stack, extended_cif *ecif)
{
unsigned int i;
@@ -24,7 +36,7 @@ ffi_prep_args (void *stack, extended_cif *ecif)
argp = stack;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
- && ecif->cif->rtype->size > 8)
+ && !ecif->cif->flags)
struct_value_ptr = ecif->rvalue;
else
struct_value_ptr = NULL;
@@ -37,44 +49,47 @@ ffi_prep_args (void *stack, extended_cif *ecif)
{
size_t z;
- /* Align if necessary. */
- if (((*p_arg)->alignment - 1) & (unsigned) argp)
- argp = (char *) ALIGN (argp, (*p_arg)->alignment);
-
- z = (*p_arg)->size;
- if (z < sizeof (int))
+ z = (*p_arg)->size;
+ if (z < sizeof (int))
+ {
+ switch ((*p_arg)->type)
{
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
- break;
-
- case FFI_TYPE_STRUCT:
- memcpy (argp + sizeof (int) - z, *p_argv, z);
- break;
-
- default:
- FFI_ASSERT (0);
- }
- z = sizeof (int);
+ case FFI_TYPE_SINT8:
+ *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
+ break;
+
+ case FFI_TYPE_UINT8:
+ *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
+ break;
+
+ case FFI_TYPE_SINT16:
+ *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
+ break;
+
+ case FFI_TYPE_UINT16:
+ *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
+ break;
+
+ case FFI_TYPE_STRUCT:
+ memcpy (argp + sizeof (int) - z, *p_argv, z);
+ break;
+
+ default:
+ FFI_ASSERT (0);
}
- else
- memcpy (argp, *p_argv, z);
- p_argv++;
- argp += z;
+ z = sizeof (int);
+ }
+ else
+ {
+ memcpy (argp, *p_argv, z);
+
+ /* Align if necessary. */
+ if ((sizeof(int) - 1) & z)
+ z = ALIGN(z, sizeof(int));
+ }
+
+ p_argv++;
+ argp += z;
}
return struct_value_ptr;
@@ -86,7 +101,8 @@ ffi_prep_args (void *stack, extended_cif *ecif)
#define CIF_FLAGS_DOUBLE 8
#define CIF_FLAGS_LDOUBLE 16
#define CIF_FLAGS_POINTER 32
-#define CIF_FLAGS_STRUCT 64
+#define CIF_FLAGS_STRUCT1 64
+#define CIF_FLAGS_STRUCT2 128
/* Perform machine dependent cif processing */
ffi_status
@@ -100,12 +116,24 @@ ffi_prep_cif_machdep (ffi_cif *cif)
break;
case FFI_TYPE_STRUCT:
- if (cif->rtype->size > 4 && cif->rtype->size <= 8)
- cif->flags = CIF_FLAGS_DINT;
- else if (cif->rtype->size <= 4)
- cif->flags = CIF_FLAGS_STRUCT;
- else
- cif->flags = 0;
+ switch (cif->rtype->size)
+ {
+ case 1:
+ cif->flags = CIF_FLAGS_STRUCT1;
+ break;
+ case 2:
+ cif->flags = CIF_FLAGS_STRUCT2;
+ break;
+ case 4:
+ cif->flags = CIF_FLAGS_INT;
+ break;
+ case 8:
+ cif->flags = CIF_FLAGS_DINT;
+ break;
+ default:
+ cif->flags = 0;
+ break;
+ }
break;
case FFI_TYPE_FLOAT:
@@ -137,11 +165,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
return FFI_OK;
}
-extern void ffi_call_SYSV (void *(*) (void *, extended_cif *),
- extended_cif *,
- unsigned, unsigned, unsigned,
- void *, void (*fn) ());
-
void
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
{
@@ -149,7 +172,7 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
ecif.cif = cif;
ecif.avalue = avalue;
-
+
/* If the return value is a struct and we don't have a return value
address then we need to make one. */
@@ -159,13 +182,11 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
ecif.rvalue = alloca (cif->rtype->size);
else
ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
+
+ switch (cif->abi)
{
case FFI_SYSV:
- ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
- cif->flags, cif->rtype->size * 8,
+ ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
break;
@@ -174,3 +195,84 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
break;
}
}
+
+static void
+ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
+{
+ unsigned int i;
+ void **p_argv;
+ char *argp;
+ ffi_type **p_arg;
+
+ argp = stack;
+ p_argv = avalue;
+
+ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+ {
+ size_t z;
+
+ z = (*p_arg)->size;
+ if (z <= 4)
+ {
+ *p_argv = (void *) (argp + 4 - z);
+
+ z = 4;
+ }
+ else
+ {
+ *p_argv = (void *) argp;
+
+ /* Align if necessary */
+ if ((sizeof(int) - 1) & z)
+ z = ALIGN(z, sizeof(int));
+ }
+
+ p_argv++;
+ argp += z;
+ }
+}
+
+unsigned int
+ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
+{
+ ffi_cif *cif;
+ void **arg_area;
+
+ cif = closure->cif;
+ arg_area = (void**) alloca (cif->nargs * sizeof (void *));
+
+ ffi_prep_incoming_args_SYSV(args, arg_area, cif);
+
+ (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+ return cif->flags;
+}
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+ ffi_cif* cif,
+ void (*fun)(ffi_cif*,void*,void**,void*),
+ void *user_data,
+ void *codeloc)
+{
+ FFI_ASSERT (cif->abi == FFI_SYSV);
+
+ *(unsigned short *)closure->tramp = 0x207c;
+ *(void **)(closure->tramp + 2) = codeloc;
+ *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
+ if (cif->rtype->type == FFI_TYPE_STRUCT
+ && !cif->flags)
+ *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
+ else
+ *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
+
+ syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
+ FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
+
+ closure->cif = cif;
+ closure->user_data = user_data;
+ closure->fun = fun;
+
+ return FFI_OK;
+}
+