diff options
author | Anthony Green <green@cygnus.com> | 1999-08-08 13:27:18 +0000 |
---|---|---|
committer | Anthony Green <green@cygnus.com> | 1999-08-08 13:27:18 +0000 |
commit | bbb2be0728c4e011ee23b4daa04981ac8f99cc6e (patch) | |
tree | 7687d170c71097dc434304205f4ea24833298d64 /libffi/src/alpha | |
parent | fd6e35fcd3458943f09f7d18573770f61e337a26 (diff) |
Initial revision
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@28593 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi/src/alpha')
-rw-r--r-- | libffi/src/alpha/ffi.c | 199 | ||||
-rw-r--r-- | libffi/src/alpha/osf.S | 118 |
2 files changed, 317 insertions, 0 deletions
diff --git a/libffi/src/alpha/ffi.c b/libffi/src/alpha/ffi.c new file mode 100644 index 00000000000..e3d807ab196 --- /dev/null +++ b/libffi/src/alpha/ffi.c @@ -0,0 +1,199 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 1998 Cygnus Solutions + + Alpha Foreign Function Interface + + $Id: ffi.c,v 1.1.1.1 1998/11/29 16:48:16 green Exp $ + + 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. + ----------------------------------------------------------------------- */ + +#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(char *stack, extended_cif *ecif, int bytes, int flags) +{ + register long i, avn; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + /* To streamline things in the assembly code, we always allocate 12 + words for loading up the int and fp argument registers. The layout + is as when processing varargs: the 6 fp args, the 6 int args, then + the incoming stack. ARGP points to the first int slot. */ + argp = stack + 6 * SIZEOF_ARG; + memset (stack, 0, 12 * SIZEOF_ARG); + + if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) + { + *(void **) argp = ecif->rvalue; + argp += sizeof(void *); + } + + i = 0; + avn = ecif->cif->nargs; + p_arg = ecif->cif->arg_types; + p_argv = ecif->avalue; + while (i < avn) + { + size_t z = ALIGN((*p_arg)->size, SIZEOF_ARG); + + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(SINT64 *) argp = *(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(UINT64 *) argp = *(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(SINT64 *) argp = *(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(UINT64 *) argp = *(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_SINT32: + *(SINT64 *) argp = *(SINT32 *)(* p_argv); + break; + + case FFI_TYPE_UINT32: + *(UINT64 *) argp = *(UINT32 *)(* p_argv); + break; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + *(UINT64 *) argp = *(UINT64 *)(* p_argv); + break; + + case FFI_TYPE_FLOAT: + if (argp - stack < 12 * SIZEOF_ARG) + { + /* Note the conversion -- all the fp regs are loaded as + doubles. The in-register format is the same. */ + *(double *) (argp - 6 * SIZEOF_ARG) = *(float *)(* p_argv); + } + else + *(float *) argp = *(float *)(* p_argv); + break; + + case FFI_TYPE_DOUBLE: + if (argp - stack < 12 * SIZEOF_ARG) + *(double *) (argp - 6 * SIZEOF_ARG) = *(double *)(* p_argv); + else + *(double *) argp = *(double *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: + memcpy(argp, *p_argv, (*p_arg)->size); + break; + + default: + FFI_ASSERT(0); + } + + argp += z; + i++, p_arg++, p_argv++; + } +} + +/* Perform machine dependent cif processing */ +ffi_status +ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Adjust cif->bytes. to include 12 words for the temporary register + argument loading area. This will be removed before the call. */ + + cif->bytes += 6*SIZEOF_ARG; + if (cif->bytes < 12*SIZEOF_ARG) + cif->bytes = 12*SIZEOF_ARG; + + /* The stack must be double word aligned, so round bytes up + appropriately. */ + + cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*)); + + /* Set the return type flag */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + cif->flags = cif->rtype->type; + break; + + case FFI_TYPE_FLOAT: + cif->flags = FFI_TYPE_FLOAT; + break; + + case FFI_TYPE_DOUBLE: + cif->flags = FFI_TYPE_DOUBLE; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +extern int ffi_call_osf(void (*)(char *, extended_cif *, int, int), + extended_cif *, unsigned, + unsigned, unsigned *, void (*)()); + +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) + ecif.rvalue = alloca(cif->rtype->size); + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_OSF: + ffi_call_osf(ffi_prep_args, &ecif, cif->bytes, + cif->flags, rvalue, fn); + break; + + default: + FFI_ASSERT(0); + break; + } +} diff --git a/libffi/src/alpha/osf.S b/libffi/src/alpha/osf.S new file mode 100644 index 00000000000..2078683cfb3 --- /dev/null +++ b/libffi/src/alpha/osf.S @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------- + osf.S - Copyright (c) 1998 Cygnus Solutions + + Alpha/OSF Foreign Function Interface + + $Id: osf.S,v 1.1.1.1 1998/11/29 16:48:16 green Exp $ + + 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 <ffi.h> + +#define callback $16 +#define ecifp $17 +#define bytes $18 +#define flags $19 +#define raddr $20 +#define fn $21 + +#define flags_ofs 16 +#define raddr_ofs 24 +#define fn_ofs 32 + +#define SIZEOF_FRAME (6*8) + + .text + .align 4 + .globl ffi_call_osf + .ent ffi_call_osf + +ffi_call_osf: + lda $30, -SIZEOF_FRAME($30) + stq $26, 0($30) + stq $15, 8($30) + stq flags, flags_ofs($30) + stq raddr, raddr_ofs($30) + stq fn, fn_ofs($30) + mov $30, $15 + .frame $15, SIZEOF_FRAME, $26, 0 + .mask 0x4008000, -SIZEOF_FRAME + .prologue 0 + + mov callback, $27 # mov callback into place + subq $30, bytes, $30 # allocate stack space + + # Call ffi_prep_args; ecif, bytes and flags are already in place. + mov $30, $16 # push stack arg + jsr $26, ($27), 0 + + # Load up all of the (potential) argument registers. + ldt $f16, 0($30) + ldt $f17, 8($30) + ldt $f18, 16($30) + ldt $f19, 24($30) + ldt $f20, 32($30) + ldt $f21, 40($30) + ldq $16, 48($30) + ldq $17, 56($30) + ldq $18, 64($30) + ldq $19, 72($30) + ldq $20, 80($30) + ldq $21, 88($30) + + # Get rid of the arg reg temp space and call the function. + ldq $27, fn_ofs($15) + lda $30, 12*8($30) + jsr $26, ($27), 0 + + # If the return value pointer is NULL, assume no return value. + ldq raddr, raddr_ofs($15) + beq raddr, $noretval + + ldq flags, flags_ofs($15) + cmpeq flags, FFI_TYPE_INT, $1 + bne $1, $retint + cmpeq flags, FFI_TYPE_FLOAT, $2 + bne $2, $retfloat + cmpeq flags, FFI_TYPE_DOUBLE, $3 + bne $3, $retdouble + br $retstruct + + .align 3 +$retint: + stq $0, 0(raddr) + br $noretval +$retfloat: + sts $f0, 0(raddr) + br $noretval +$retdouble: + stt $f0, 0(raddr) + +$retstruct: +$noretval: + mov $15, $30 + ldq $26, 0($15) + ldq $15, 8($15) + lda $30, SIZEOF_FRAME($30) + ret + + .end ffi_call_osf |