diff options
Diffstat (limited to 'libffi/src/m68k')
-rw-r--r-- | libffi/src/m68k/ffi.c | 176 | ||||
-rw-r--r-- | libffi/src/m68k/ffitarget.h | 47 | ||||
-rw-r--r-- | libffi/src/m68k/sysv.S | 97 |
3 files changed, 320 insertions, 0 deletions
diff --git a/libffi/src/m68k/ffi.c b/libffi/src/m68k/ffi.c new file mode 100644 index 0000000..55f3a98 --- /dev/null +++ b/libffi/src/m68k/ffi.c @@ -0,0 +1,176 @@ +/* ----------------------------------------------------------------------- + ffi.c + + m68k Foreign Function Interface + ----------------------------------------------------------------------- */ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> + +/* ffi_prep_args is called by the assembly routine once stack space has + been allocated for the function's arguments. */ + +static void * +ffi_prep_args (void *stack, extended_cif *ecif) +{ + unsigned int i; + void **p_argv; + char *argp; + ffi_type **p_arg; + void *struct_value_ptr; + + argp = stack; + + if (ecif->cif->rtype->type == FFI_TYPE_STRUCT + && ecif->cif->rtype->size > 8) + struct_value_ptr = ecif->rvalue; + else + struct_value_ptr = NULL; + + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + i != 0; + i--, p_arg++) + { + 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)) + { + 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); + } + else + memcpy (argp, *p_argv, z); + p_argv++; + argp += z; + } + + return struct_value_ptr; +} + +#define CIF_FLAGS_INT 1 +#define CIF_FLAGS_DINT 2 +#define CIF_FLAGS_FLOAT 4 +#define CIF_FLAGS_DOUBLE 8 +#define CIF_FLAGS_LDOUBLE 16 +#define CIF_FLAGS_POINTER 32 +#define CIF_FLAGS_STRUCT 64 + +/* Perform machine dependent cif processing */ +ffi_status +ffi_prep_cif_machdep (ffi_cif *cif) +{ + /* Set the return type flag */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + cif->flags = 0; + 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; + break; + + case FFI_TYPE_FLOAT: + cif->flags = CIF_FLAGS_FLOAT; + break; + + case FFI_TYPE_DOUBLE: + cif->flags = CIF_FLAGS_DOUBLE; + break; + + case FFI_TYPE_LONGDOUBLE: + cif->flags = CIF_FLAGS_LDOUBLE; + break; + + case FFI_TYPE_POINTER: + cif->flags = CIF_FLAGS_POINTER; + break; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags = CIF_FLAGS_DINT; + break; + + default: + cif->flags = CIF_FLAGS_INT; + break; + } + + 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) +{ + extended_cif ecif; + + 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. */ + + if (rvalue == NULL + && cif->rtype->type == FFI_TYPE_STRUCT + && cif->rtype->size > 8) + ecif.rvalue = alloca (cif->rtype->size); + else + ecif.rvalue = rvalue; + + + switch (cif->abi) + { + case FFI_SYSV: + ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, + cif->flags, cif->rtype->size * 8, + ecif.rvalue, fn); + break; + + default: + FFI_ASSERT (0); + break; + } +} diff --git a/libffi/src/m68k/ffitarget.h b/libffi/src/m68k/ffitarget.h new file mode 100644 index 0000000..aca7fac --- /dev/null +++ b/libffi/src/m68k/ffitarget.h @@ -0,0 +1,47 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. + Target configuration macros for Motorola 68K. + + 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. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV, + FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 +} ffi_abi; +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 0 +#define FFI_NATIVE_RAW_API 0 + +#endif + diff --git a/libffi/src/m68k/sysv.S b/libffi/src/m68k/sysv.S new file mode 100644 index 0000000..d019a37 --- /dev/null +++ b/libffi/src/m68k/sysv.S @@ -0,0 +1,97 @@ +/* ----------------------------------------------------------------------- + sysv.S + + m68k Foreign Function Interface + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> + + .text + + .globl ffi_call_SYSV + .type ffi_call_SYSV,@function + +ffi_call_SYSV: + link %fp,#0 + move.l %d2,-(%sp) + + | Make room for all of the new args. + sub.l 16(%fp),%sp + + | Call ffi_prep_args + move.l 12(%fp),-(%sp) + pea 4(%sp) + move.l 8(%fp),%a0 + jsr (%a0) + addq.l #8,%sp + + | Pass pointer to struct value, if any + move.l %a0,%a1 + + | Call the function + move.l 32(%fp),%a0 + jsr (%a0) + + | Remove the space we pushed for the args + add.l 16(%fp),%sp + + | Load the pointer to storage for the return value + move.l 28(%fp),%a1 + + | Load the return type code + move.l 20(%fp),%d2 + + | If the return value pointer is NULL, assume no return value. + tst.l %a1 + jbeq noretval + + btst #0,%d2 + jbeq retlongint + move.l %d0,(%a1) + jbra epilogue + +retlongint: + btst #1,%d2 + jbeq retfloat + move.l %d0,(%a1) + move.l %d1,4(%a1) + jbra epilogue + +retfloat: + btst #2,%d2 + jbeq retdouble + fmove.s %fp0,(%a1) + jbra epilogue + +retdouble: + btst #3,%d2 + jbeq retlongdouble + fmove.d %fp0,(%a1) + jbra epilogue + +retlongdouble: + btst #4,%d2 + jbeq retpointer + fmove.x %fp0,(%a1) + jbra epilogue + +retpointer: + btst #5,%d2 + jbeq retstruct + move.l %a0,(%a1) + jbra epilogue + +retstruct: + btst #6,%d2 + jbeq noretval + move.l 24(%fp),%d2 + bfins %d0,(%a1){#0,%d2} + +noretval: +epilogue: + move.l (%sp)+,%d2 + unlk %a6 + rts + .size ffi_call_SYSV,.-ffi_call_SYSV |