aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/alpha
diff options
context:
space:
mode:
authorAnthony Green <green@cygnus.com>1999-08-08 13:27:18 +0000
committerAnthony Green <green@cygnus.com>1999-08-08 13:27:18 +0000
commitbbb2be0728c4e011ee23b4daa04981ac8f99cc6e (patch)
tree7687d170c71097dc434304205f4ea24833298d64 /libffi/src/alpha
parentfd6e35fcd3458943f09f7d18573770f61e337a26 (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.c199
-rw-r--r--libffi/src/alpha/osf.S118
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