diff options
author | Anthony Green <green@gcc.gnu.org> | 1999-08-08 13:27:18 +0000 |
---|---|---|
committer | Anthony Green <green@gcc.gnu.org> | 1999-08-08 13:27:18 +0000 |
commit | 63e5e3e0dbb7207e95c0437499b980a304665589 (patch) | |
tree | 7687d170c71097dc434304205f4ea24833298d64 /libffi/src/sparc | |
parent | 108c535a0c8a62b1edcbe4187365bf82e18d23ad (diff) | |
download | gcc-63e5e3e0dbb7207e95c0437499b980a304665589.zip gcc-63e5e3e0dbb7207e95c0437499b980a304665589.tar.gz gcc-63e5e3e0dbb7207e95c0437499b980a304665589.tar.bz2 |
Initial revision
From-SVN: r28593
Diffstat (limited to 'libffi/src/sparc')
-rw-r--r-- | libffi/src/sparc/ffi.c | 216 | ||||
-rw-r--r-- | libffi/src/sparc/v8.S | 85 |
2 files changed, 301 insertions, 0 deletions
diff --git a/libffi/src/sparc/ffi.c b/libffi/src/sparc/ffi.c new file mode 100644 index 0000000..8ca6710 --- /dev/null +++ b/libffi/src/sparc/ffi.c @@ -0,0 +1,216 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 1996 Cygnus Solutions + + Sparc 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 */ + +void ffi_prep_args(char *stack, extended_cif *ecif) +{ + int i; + int tmp; + int avn; + void **p_argv; + char *argp; + ffi_type **p_arg; + + tmp = 0; + + /* Skip 16 words for the window save area */ + argp = stack + 16*sizeof(void*); + + /* This should only really be done when we are returning a structure, + however, it's faster just to do it all the time... + + if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */ + *(void **) argp = ecif->rvalue; + + /* And 1 word for the structure return value. */ + argp += sizeof(void*); + +#ifdef USING_PURIFY + /* Purify will probably complain in our assembly routine, unless we + zero out this memory. */ + + ((int*)argp)[0] = 0; + ((int*)argp)[1] = 0; + ((int*)argp)[2] = 0; + ((int*)argp)[3] = 0; + ((int*)argp)[4] = 0; + ((int*)argp)[5] = 0; +#endif + + avn = ecif->cif->nargs; + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + i && avn; + i--, p_arg++) + { + size_t z; + + if (avn) + { + avn--; + if ((*p_arg)->type == FFI_TYPE_STRUCT + || (*p_arg)->type == FFI_TYPE_LONGDOUBLE) + { + *(unsigned int *) argp = (unsigned int)(* p_argv); + z = sizeof(void*); + } + else + { + z = (*p_arg)->size; + if (z < sizeof(int)) + { + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = *(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = *(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = *(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = *(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_SINT32: + *(signed int *) argp = *(SINT32 *)(* p_argv); + break; + + case FFI_TYPE_UINT32: + *(unsigned int *) argp = *(UINT32 *)(* p_argv); + break; + + default: + FFI_ASSERT(0); + } + } + else + { + memcpy(argp, *p_argv, z); + } + } + p_argv++; + argp += z; + } + } + + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* If we are returning a struct, this will already have been added. + Otherwise we need to add it because it's always got to be there! */ + + if (cif->rtype->type != FFI_TYPE_STRUCT) + cif->bytes += sizeof(void*); + + /* sparc call frames require that space is allocated for 6 args, + even if they aren't used. Make that space if necessary. */ + + if (cif->bytes < 4*6+4) + cif->bytes = 4*6+4; + + /* Adjust cif->bytes. to include 16 words for the window save area, + and maybe the struct/union return pointer area, */ + + cif->bytes += 64; + + /* 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_V8(void *, extended_cif *, unsigned, + unsigned, unsigned *, 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)) + ecif.rvalue = alloca(cif->rtype->size); + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_V8: + ffi_call_V8(ffi_prep_args, &ecif, cif->bytes, + cif->flags, rvalue, fn); + break; + default: + FFI_ASSERT(0); + break; + } +} diff --git a/libffi/src/sparc/v8.S b/libffi/src/sparc/v8.S new file mode 100644 index 0000000..da0dbe6 --- /dev/null +++ b/libffi/src/sparc/v8.S @@ -0,0 +1,85 @@ +/* ----------------------------------------------------------------------- + v8.S - Copyright (c) 1996, 1997 Cygnus Solutions + + Sparc Foreign Function Interface + + $Id: v8.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 STACKFRAME 96 /* Minimum stack framesize for SPARC */ +#define ARGS (64+4) /* Offset of register area in frame */ + +.text + .align 8 +.globl ffi_call_V8 +.globl _ffi_call_V8 + +ffi_call_V8: +_ffi_call_V8: + save %sp, -STACKFRAME, %sp + + sub %sp, %i2, %sp ! alloca() space in stack for frame to set up + add %sp, STACKFRAME, %l0 ! %l0 has start of + ! frame to set up + + mov %l0, %o0 ! call routine to set up frame + call %i0 + mov %i1, %o1 ! (delay) + + ld [%l0+ARGS], %o0 ! call foreign function + ld [%l0+ARGS+4], %o1 + ld [%l0+ARGS+8], %o2 + ld [%l0+ARGS+12], %o3 + ld [%l0+ARGS+16], %o4 + ld [%l0+ARGS+20], %o5 + call %i5 + mov %l0, %sp ! (delay) switch to frame + + ! If the return value pointer is NULL, assume no return value. + tst %i4 + bz done + nop + + cmp %i3, FFI_TYPE_INT + be,a done + st %o0, [%i4] ! (delay) + + cmp %i3, FFI_TYPE_FLOAT + be,a done + st %f0, [%i4+0] ! (delay) + + cmp %i3, FFI_TYPE_DOUBLE + bne done + nop + st %f0, [%i4+0] + st %f1, [%i4+4] + +done: + ret + restore + +.ffi_call_V8_end: + .size ffi_call_V8,.ffi_call_V8_end-ffi_call_V8 + |