aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/sparc
diff options
context:
space:
mode:
authorAnthony Green <green@gcc.gnu.org>1999-08-08 13:27:18 +0000
committerAnthony Green <green@gcc.gnu.org>1999-08-08 13:27:18 +0000
commit63e5e3e0dbb7207e95c0437499b980a304665589 (patch)
tree7687d170c71097dc434304205f4ea24833298d64 /libffi/src/sparc
parent108c535a0c8a62b1edcbe4187365bf82e18d23ad (diff)
downloadgcc-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.c216
-rw-r--r--libffi/src/sparc/v8.S85
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
+