mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-30 13:39:46 +08:00
ffi.c, [...]: New files.
2000-02-25 Hans Boehm <boehm@acm.org> * src/ia64/ffi.c, src/ia64/ia64_flags.h, src/ia64/unix.S: New files. * src/raw_api.c (ffi_translate_args): Fixed typo in argument list. (ffi_prep_raw_closure): Use ffi_translate_args, not ffi_closure_translate. * src/java_raw_api.c: New file. * src/ffitest.c (closure_test_fn): New function. (main): Define `rint' as long long on IA64. Added new test when FFI_CLOSURES is defined. * include/ffi.h.in (ALIGN): Use size_t, not unsigned. (ffi_abi): Recognize IA64. (ffi_raw): Added `flt' field. Added "Java raw API" code. * configure.in: Recognize ia64. * Makefile.am (TARGET_SRC_IA64): New macro. (libffi_la_common_SOURCES): Added java_raw_api.c. (libffi_la_SOURCES): Define in IA64 case. From-SVN: r32151
This commit is contained in:
parent
0e2eaba46d
commit
dc5de37072
@ -1,3 +1,24 @@
|
||||
2000-02-25 Hans Boehm <boehm@acm.org>
|
||||
|
||||
* src/ia64/ffi.c, src/ia64/ia64_flags.h, src/ia64/unix.S: New
|
||||
files.
|
||||
* src/raw_api.c (ffi_translate_args): Fixed typo in argument
|
||||
list.
|
||||
(ffi_prep_raw_closure): Use ffi_translate_args, not
|
||||
ffi_closure_translate.
|
||||
* src/java_raw_api.c: New file.
|
||||
* src/ffitest.c (closure_test_fn): New function.
|
||||
(main): Define `rint' as long long on IA64. Added new test when
|
||||
FFI_CLOSURES is defined.
|
||||
* include/ffi.h.in (ALIGN): Use size_t, not unsigned.
|
||||
(ffi_abi): Recognize IA64.
|
||||
(ffi_raw): Added `flt' field.
|
||||
Added "Java raw API" code.
|
||||
* configure.in: Recognize ia64.
|
||||
* Makefile.am (TARGET_SRC_IA64): New macro.
|
||||
(libffi_la_common_SOURCES): Added java_raw_api.c.
|
||||
(libffi_la_SOURCES): Define in IA64 case.
|
||||
|
||||
2000-01-04 Tom Tromey <tromey@cygnus.com>
|
||||
|
||||
* Makefile.in: Rebuilt with newer automake.
|
||||
|
@ -42,13 +42,15 @@ TARGET_SRC_MIPS_SGI = src/mips/ffi.c src/mips/o32.s src/mips/n32.s
|
||||
TARGET_SRC_X86 = src/x86/ffi.c src/x86/sysv.S
|
||||
TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S
|
||||
TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
|
||||
TARGET_SRC_IA64 = src/alpha/ffi.c src/alpha/unix.S
|
||||
TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
|
||||
TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S
|
||||
TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
|
||||
|
||||
##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@)
|
||||
## Work around automake deficiency
|
||||
libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c src/raw_api.c
|
||||
libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
|
||||
src/raw_api.c src/java_raw_api.c
|
||||
if MIPS_GCC
|
||||
libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
|
||||
endif
|
||||
@ -64,6 +66,9 @@ endif
|
||||
if ALPHA
|
||||
libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ALPHA)
|
||||
endif
|
||||
if IA64
|
||||
libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_IA64)
|
||||
endif
|
||||
if M68K
|
||||
libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_M68K)
|
||||
endif
|
||||
|
@ -117,16 +117,18 @@ TARGET_SRC_MIPS_SGI = src/mips/ffi.c src/mips/o32.s src/mips/n32.s
|
||||
TARGET_SRC_X86 = src/x86/ffi.c src/x86/sysv.S
|
||||
TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S
|
||||
TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
|
||||
TARGET_SRC_IA64 = src/alpha/ffi.c src/alpha/unix.S
|
||||
TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
|
||||
TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S
|
||||
TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
|
||||
|
||||
libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c src/raw_api.c
|
||||
libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c src/raw_api.c src/java_raw_api.c
|
||||
@MIPS_GCC_TRUE@libffi_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
|
||||
@MIPS_SGI_TRUE@libffi_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI)
|
||||
@X86_TRUE@libffi_la_SOURCES = @X86_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86)
|
||||
@SPARC_TRUE@libffi_la_SOURCES = @SPARC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SPARC)
|
||||
@ALPHA_TRUE@libffi_la_SOURCES = @ALPHA_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ALPHA)
|
||||
@IA64_TRUE@libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_IA64)
|
||||
@M68K_TRUE@libffi_la_SOURCES = @M68K_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_M68K)
|
||||
@POWERPC_TRUE@libffi_la_SOURCES = @POWERPC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC)
|
||||
@ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
|
||||
@ -290,6 +292,7 @@ debug.lo: src/debug.c
|
||||
prep_cif.lo: src/prep_cif.c
|
||||
types.lo: src/types.c
|
||||
raw_api.lo: src/raw_api.c
|
||||
java_raw_api.lo: src/java_raw_api.c
|
||||
ffi.lo: src/alpha/ffi.c
|
||||
osf.lo: src/alpha/osf.S
|
||||
sysv.lo: src/arm/sysv.S
|
||||
|
34
libffi/aclocal.m4
vendored
34
libffi/aclocal.m4
vendored
@ -1,4 +1,4 @@
|
||||
dnl aclocal.m4 generated automatically by aclocal 1.4a
|
||||
dnl aclocal.m4 generated automatically by aclocal 1.4
|
||||
|
||||
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
@ -44,8 +44,6 @@ dnl AM_INIT_AUTOMAKE(package,version, [no-define])
|
||||
|
||||
AC_DEFUN(AM_INIT_AUTOMAKE,
|
||||
[AC_REQUIRE([AC_PROG_INSTALL])
|
||||
dnl We require 2.13 because we rely on SHELL being computed by configure.
|
||||
AC_PREREQ([2.13])
|
||||
PACKAGE=[$1]
|
||||
AC_SUBST(PACKAGE)
|
||||
VERSION=[$2]
|
||||
@ -66,23 +64,6 @@ AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
|
||||
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
|
||||
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
|
||||
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
|
||||
dnl Set install_sh for make dist
|
||||
install_sh="$missing_dir/install-sh"
|
||||
test -f "$install_sh" || install_sh="$missing_dir/install.sh"
|
||||
AC_SUBST(install_sh)
|
||||
dnl We check for tar when the user configures the end package.
|
||||
dnl This is sad, since we only need this for "dist". However,
|
||||
dnl there's no other good way to do it. We prefer GNU tar if
|
||||
dnl we can find it. If we can't find a tar, it doesn't really matter.
|
||||
AC_CHECK_PROGS(AMTAR, gnutar gtar tar)
|
||||
AMTARFLAGS=
|
||||
if test -n "$AMTAR"; then
|
||||
if $SHELL -c "$AMTAR --version" > /dev/null 2>&1; then
|
||||
dnl We have GNU tar.
|
||||
AMTARFLAGS=o
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(AMTARFLAGS)
|
||||
AC_REQUIRE([AC_PROG_MAKE_SET])])
|
||||
|
||||
#
|
||||
@ -191,7 +172,7 @@ LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
|
||||
LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
|
||||
DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
|
||||
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
|
||||
$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
|
||||
$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
|
||||
|| AC_MSG_ERROR([libtool configure failed])
|
||||
|
||||
# Reload cache, that may have been modified by ltconfig
|
||||
@ -223,6 +204,11 @@ AC_REQUIRE([AC_PROG_NM])dnl
|
||||
AC_REQUIRE([AC_PROG_LN_S])dnl
|
||||
dnl
|
||||
|
||||
case "$target" in
|
||||
NONE) lt_target="$host" ;;
|
||||
*) lt_target="$target" ;;
|
||||
esac
|
||||
|
||||
# Check for any special flags to pass to ltconfig.
|
||||
libtool_flags="--cache-file=$cache_file"
|
||||
test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
|
||||
@ -241,7 +227,7 @@ test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
|
||||
|
||||
# Some flags need to be propagated to the compiler or linker for good
|
||||
# libtool support.
|
||||
case "$host" in
|
||||
case "$lt_target" in
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '[#]line __oline__ "configure"' > conftest.$ac_ext
|
||||
@ -457,7 +443,6 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
|
||||
AC_SUBST(LD)
|
||||
AC_PROG_LD_GNU
|
||||
])
|
||||
|
||||
@ -503,14 +488,13 @@ else
|
||||
fi])
|
||||
NM="$ac_cv_path_NM"
|
||||
AC_MSG_RESULT([$NM])
|
||||
AC_SUBST(NM)
|
||||
])
|
||||
|
||||
# AC_CHECK_LIBM - check for math library
|
||||
AC_DEFUN(AC_CHECK_LIBM,
|
||||
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
LIBM=
|
||||
case "$host" in
|
||||
case "$lt_target" in
|
||||
*-*-beos* | *-*-cygwin*)
|
||||
# These system don't have libm
|
||||
;;
|
||||
|
541
libffi/configure
vendored
541
libffi/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@ i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
|
||||
sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
alpha*-*-linux* | alpha*-*-osf*) TARGET=ALPHA; TARGETDIR=alpha;;
|
||||
ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
|
||||
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
|
||||
powerpc-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
@ -42,6 +43,7 @@ AM_CONDITIONAL(MIPS_SGI, test ${TARGET}${ac_cv_prog_gcc} = MIPSno)
|
||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi @VERSION@ - Copyright (c) 1996-1999 Cygnus Solutions
|
||||
|
||||
$Id: ffi.h.in,v 1.2 1999/08/09 02:52:58 green Exp $
|
||||
$Id: ffi.h.in,v 1.3 1999/09/01 23:16:34 tromey Exp $
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@ -24,6 +24,32 @@
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
The basic API is described in the README file.
|
||||
|
||||
The raw API is designed to bypass some of the argument packing
|
||||
and unpacking on architectures for which it can be avoided.
|
||||
|
||||
The closure API allows interpreted functions to be packaged up
|
||||
inside a C function pointer, so that they can be called as C functions,
|
||||
with no understanding on the client side that they are interpreted.
|
||||
It can also be used in other cases in which it is necessary to package
|
||||
up a user specified parameter and a function pointer as a single
|
||||
function pointer.
|
||||
|
||||
The closure API must be implemented in order to get its functionality,
|
||||
e.g. for use by gij. Routines are provided to emulate the raw API
|
||||
if the underlying platform doesn't allow faster implementation.
|
||||
|
||||
More details on the raw and cloure API can be found in:
|
||||
|
||||
http://sourceware.cygnus.com/ml/java-discuss/1999-q3/msg00138.html
|
||||
|
||||
and
|
||||
|
||||
http://sourceware.cygnus.com/ml/java-discuss/1999-q3/msg00174.html
|
||||
-------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#define LIBFFI_H
|
||||
|
||||
@ -138,7 +164,9 @@ extern "C" {
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#define ALIGN(v, a) (((((unsigned) (v))-1) | ((a)-1))+1)
|
||||
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t */
|
||||
/* can hold a pointer. */
|
||||
|
||||
typedef enum ffi_abi {
|
||||
|
||||
@ -159,6 +187,12 @@ typedef enum ffi_abi {
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
/* ---- Intel ia64 ---------------- */
|
||||
#ifdef IA64
|
||||
FFI_UNIX, /* Linux and all Unix variants use the same conventions */
|
||||
FFI_DEFAULT_ABI = FFI_UNIX,
|
||||
#endif
|
||||
|
||||
/* ---- Mips --------------------- */
|
||||
#ifdef MIPS
|
||||
FFI_O32,
|
||||
@ -268,6 +302,7 @@ typedef struct {
|
||||
typedef union {
|
||||
SINT_ARG sint;
|
||||
UINT_ARG uint;
|
||||
float flt;
|
||||
char data[SIZEOF_ARG];
|
||||
void* ptr;
|
||||
} ffi_raw;
|
||||
@ -281,8 +316,22 @@ void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
size_t ffi_raw_size (ffi_cif *cif);
|
||||
|
||||
#if !NO_JAVA_RAW_API
|
||||
|
||||
/* This is analogous to the raw API, except it uses Java parameter */
|
||||
/* packing, even on 64-bit machines. I.e. on 64-bit machines */
|
||||
/* longs and doubles are followed by an empty 64-bit word. */
|
||||
|
||||
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *avalue);
|
||||
|
||||
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
size_t ffi_java_raw_size (ffi_cif *cif);
|
||||
|
||||
#endif /* !NO_JAVA_RAW_API */
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
|
||||
@ -294,6 +343,21 @@ size_t ffi_raw_size (ffi_cif *cif);
|
||||
#define FFI_TRAMPOLINE_SIZE 10
|
||||
#define FFI_NATIVE_RAW_API 1 /* and has native raw api support */
|
||||
|
||||
#elif defined(IA64)
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */
|
||||
/* can be interpreted as a C function */
|
||||
/* decriptor: */
|
||||
|
||||
struct ffi_ia64_trampoline_struct {
|
||||
void * code_pointer; /* Pointer to ffi_closure_UNIX */
|
||||
void * fake_gp; /* Pointer to closure, installed as gp */
|
||||
void * real_gp; /* Real gp value, reinstalled by */
|
||||
/* ffi_closure_UNIX. */
|
||||
};
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#else
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
@ -347,6 +411,14 @@ ffi_prep_raw_closure (ffi_raw_closure*,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data);
|
||||
|
||||
#ifndef NO_JAVA_RAW_API
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data);
|
||||
#endif
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
|
@ -196,6 +196,16 @@ static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
|
||||
return ts1;
|
||||
}
|
||||
|
||||
/* Take an int and a float argument, together with int userdata, and */
|
||||
/* return the sum. */
|
||||
static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
|
||||
{
|
||||
*(int*)resp =
|
||||
*(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
|
||||
}
|
||||
|
||||
typedef int (*closure_test_type)(int, float);
|
||||
|
||||
int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
{
|
||||
ffi_cif cif;
|
||||
@ -214,7 +224,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
signed int si1;
|
||||
signed int si2;
|
||||
|
||||
#if defined(ALPHA) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
|
||||
#if defined(ALPHA) || defined(IA64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
|
||||
long long rint;
|
||||
#else
|
||||
int rint;
|
||||
@ -691,6 +701,27 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
||||
free (ts5_result);
|
||||
}
|
||||
|
||||
# if FFI_CLOSURES
|
||||
/* A simple closure test */
|
||||
{
|
||||
ffi_closure cl;
|
||||
ffi_type * cl_arg_types[3];
|
||||
|
||||
cl_arg_types[0] = &ffi_type_sint;
|
||||
cl_arg_types[1] = &ffi_type_float;
|
||||
cl_arg_types[2] = NULL;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
|
||||
(void *) 3 /* userdata */)
|
||||
== FFI_OK);
|
||||
CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* If we arrived here, all is good */
|
||||
(void) puts("\nLooks good. No surprises.\n");
|
||||
|
||||
|
670
libffi/src/ia64/ffi.c
Normal file
670
libffi/src/ia64/ffi.c
Normal file
@ -0,0 +1,670 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64 Foreign Function Interface
|
||||
|
||||
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>
|
||||
|
||||
#include "ia64_flags.h"
|
||||
|
||||
/* Memory image of fp register contents. Should eventually be an fp */
|
||||
/* type long enough to hold an entire register. For now we use double. */
|
||||
typedef double float80;
|
||||
|
||||
/* The stack layout at call to ffi_prep_regs. Other_args will remain */
|
||||
/* on the stack for the actual call. Everything else we be transferred */
|
||||
/* to registers and popped by the assembly code. */
|
||||
|
||||
struct ia64_args {
|
||||
long scratch[2]; /* Two scratch words at top of stack. */
|
||||
/* Allows sp to passed as arg pointer. */
|
||||
void * r8_contents; /* Value to be passed in r8 */
|
||||
long spare; /* Not used. */
|
||||
float80 fp_regs[8]; /* Contents of 8 floating point argument */
|
||||
/* registers. */
|
||||
long out_regs[8]; /* Contents of the 8 out registers used */
|
||||
/* for integer parameters. */
|
||||
long other_args[0]; /* Arguments passed on stack, variable size */
|
||||
/* Treated as continuation of out_regs. */
|
||||
};
|
||||
|
||||
static size_t float_type_size(unsigned short tp)
|
||||
{
|
||||
switch(tp) {
|
||||
case FFI_TYPE_FLOAT:
|
||||
return sizeof(float);
|
||||
case FFI_TYPE_DOUBLE:
|
||||
return sizeof(double);
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
return sizeof(long double);
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Is type a struct containing at most n floats, doubles, or extended
|
||||
* doubles, all of the same fp type?
|
||||
* If so, set *element_type to the fp type.
|
||||
*/
|
||||
static bool is_homogeneous_fp_aggregate(ffi_type * type, int n,
|
||||
unsigned short * element_type)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
unsigned short element, struct_element;
|
||||
|
||||
int type_set = 0;
|
||||
|
||||
FFI_ASSERT(type != NULL);
|
||||
|
||||
FFI_ASSERT(type->elements != NULL);
|
||||
|
||||
ptr = &(type->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
switch((*ptr) -> type) {
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (type_set && element != FFI_TYPE_FLOAT) return 0;
|
||||
if (--n < 0) return FALSE;
|
||||
type_set = 1;
|
||||
element = FFI_TYPE_FLOAT;
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (type_set && element != FFI_TYPE_DOUBLE) return 0;
|
||||
if (--n < 0) return FALSE;
|
||||
type_set = 1;
|
||||
element = FFI_TYPE_DOUBLE;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (!is_homogeneous_fp_aggregate(type, n, &struct_element))
|
||||
return FALSE;
|
||||
if (type_set && struct_element != element) return FALSE;
|
||||
n -= (type -> size)/float_type_size(element);
|
||||
element = struct_element;
|
||||
if (n < 0) return FALSE;
|
||||
break;
|
||||
/* case FFI_TYPE_LONGDOUBLE:
|
||||
Not yet implemented. */
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
*element_type = element;
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments. Returns nonzero
|
||||
if fp registers are used for arguments. */
|
||||
|
||||
static bool
|
||||
ffi_prep_args(struct ia64_args *stack, extended_cif *ecif, int bytes)
|
||||
{
|
||||
register long i, avn;
|
||||
register void **p_argv;
|
||||
register long *argp = stack -> out_regs;
|
||||
register float80 *fp_argp = stack -> fp_regs;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
/* For big return structs, r8 needs to contain the target address. */
|
||||
/* Since r8 is otherwise dead, we set it unconditionally. */
|
||||
stack -> r8_contents = ecif -> rvalue;
|
||||
i = 0;
|
||||
avn = ecif->cif->nargs;
|
||||
p_arg = ecif->cif->arg_types;
|
||||
p_argv = ecif->avalue;
|
||||
while (i < avn)
|
||||
{
|
||||
size_t z; /* z is in units of arg slots or words, not bytes. */
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
z = 1;
|
||||
*(SINT64 *) argp = *(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
z = 1;
|
||||
*(UINT64 *) argp = *(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
z = 1;
|
||||
*(SINT64 *) argp = *(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
z = 1;
|
||||
*(UINT64 *) argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
z = 1;
|
||||
*(SINT64 *) argp = *(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
z = 1;
|
||||
*(UINT64 *) argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
z = 1;
|
||||
*(UINT64 *) argp = *(UINT64 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
z = 1;
|
||||
if (fp_argp - stack->fp_regs < 8)
|
||||
{
|
||||
/* Note the conversion -- all the fp regs are loaded as
|
||||
doubles. */
|
||||
*fp_argp++ = *(float *)(* p_argv);
|
||||
}
|
||||
/* Also put it into the integer registers or memory: */
|
||||
*(UINT64 *) argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
z = 1;
|
||||
if (fp_argp - stack->fp_regs < 8)
|
||||
*fp_argp++ = *(double *)(* p_argv);
|
||||
/* Also put it into the integer registers or memory: */
|
||||
*(double *) argp = *(double *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t sz = (*p_arg)->size;
|
||||
unsigned short element_type;
|
||||
z = ((*p_arg)->size + SIZEOF_ARG - 1)/SIZEOF_ARG;
|
||||
if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) {
|
||||
int i;
|
||||
int nelements = sz/float_type_size(element_type);
|
||||
for (i = 0; i < nelements; ++i) {
|
||||
switch (element_type) {
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (fp_argp - stack->fp_regs < 8)
|
||||
*fp_argp++ = ((float *)(* p_argv))[i];
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (fp_argp - stack->fp_regs < 8)
|
||||
*fp_argp++ = ((double *)(* p_argv))[i];
|
||||
break;
|
||||
default:
|
||||
/* Extended precision not yet implemented. */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* And pass it in integer registers as a struct, with */
|
||||
/* its actual field sizes packed into registers. */
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += z;
|
||||
i++, p_arg++, p_argv++;
|
||||
}
|
||||
return (fp_argp != stack -> fp_regs);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
long i, avn;
|
||||
bool is_simple = TRUE;
|
||||
long simple_flag = FFI_SIMPLE_V;
|
||||
/* Adjust cif->bytes to include space for the 2 scratch words,
|
||||
r8 register contents, spare word,
|
||||
the 8 fp register contents, and all 8 integer register contents.
|
||||
This will be removed before the call, though 2 scratch words must
|
||||
remain. */
|
||||
|
||||
cif->bytes += 4*sizeof(long) + 8 *sizeof(float80);
|
||||
if (cif->bytes < sizeof(struct ia64_args))
|
||||
cif->bytes = sizeof(struct ia64_args);
|
||||
|
||||
/* The stack must be double word aligned, so round bytes up
|
||||
appropriately. */
|
||||
|
||||
cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
|
||||
|
||||
avn = cif->nargs;
|
||||
if (avn <= 2) {
|
||||
for (i = 0; i < avn; ++i) {
|
||||
switch(cif -> arg_types[i] -> type) {
|
||||
case FFI_TYPE_SINT32:
|
||||
simple_flag = FFI_ADD_INT_ARG(simple_flag);
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
simple_flag = FFI_ADD_LONG_ARG(simple_flag);
|
||||
break;
|
||||
default:
|
||||
is_simple = FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
is_simple = FALSE;
|
||||
}
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = FFI_TYPE_VOID;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t sz = cif -> rtype -> size;
|
||||
unsigned short element_type;
|
||||
|
||||
is_simple = FALSE;
|
||||
if (is_homogeneous_fp_aggregate(cif -> rtype, 8, &element_type)) {
|
||||
int nelements = sz/float_type_size(element_type);
|
||||
if (nelements <= 1) {
|
||||
if (0 == nelements) {
|
||||
cif -> flags = FFI_TYPE_VOID;
|
||||
} else {
|
||||
cif -> flags = element_type;
|
||||
}
|
||||
} else {
|
||||
switch(element_type) {
|
||||
case FFI_TYPE_FLOAT:
|
||||
cif -> flags = FFI_IS_FLOAT_FP_AGGREGATE | nelements;
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif -> flags = FFI_IS_DOUBLE_FP_AGGREGATE | nelements;
|
||||
break;
|
||||
default:
|
||||
/* long double NYI */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (sz <= 32) {
|
||||
if (sz <= 8) {
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
} else if (sz <= 16) {
|
||||
cif->flags = FFI_IS_SMALL_STRUCT2;
|
||||
} else if (sz <= 24) {
|
||||
cif->flags = FFI_IS_SMALL_STRUCT3;
|
||||
} else {
|
||||
cif->flags = FFI_IS_SMALL_STRUCT4;
|
||||
}
|
||||
} else {
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
is_simple = FALSE;
|
||||
cif->flags = FFI_TYPE_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
is_simple = FALSE;
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
/* This seems to depend on little endian mode, and the fact that */
|
||||
/* the return pointer always points to at least 8 bytes. But */
|
||||
/* that also seems to be true for other platforms. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_simple) cif -> flags |= simple_flag;
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern int ffi_call_unix(bool (*)(struct ia64_args *, extended_cif *, int),
|
||||
extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*)());
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
long simple = cif -> flags & FFI_SIMPLE;
|
||||
|
||||
/* Should this also check for Unix ABI? */
|
||||
/* This is almost, but not quite, machine independent. Note that */
|
||||
/* we can get away with not caring about length of the result because */
|
||||
/* we assume we are little endian, and the result buffer is large */
|
||||
/* enough. */
|
||||
/* This needs work for HP/UX. */
|
||||
if (simple) {
|
||||
long (*lfn)() = (long (*)())fn;
|
||||
long result;
|
||||
switch(simple) {
|
||||
case FFI_SIMPLE_V:
|
||||
result = lfn();
|
||||
break;
|
||||
case FFI_SIMPLE_I:
|
||||
result = lfn(*(int *)avalue[0]);
|
||||
break;
|
||||
case FFI_SIMPLE_L:
|
||||
result = lfn(*(long *)avalue[0]);
|
||||
break;
|
||||
case FFI_SIMPLE_II:
|
||||
result = lfn(*(int *)avalue[0], *(int *)avalue[1]);
|
||||
break;
|
||||
case FFI_SIMPLE_IL:
|
||||
result = lfn(*(int *)avalue[0], *(long *)avalue[1]);
|
||||
break;
|
||||
case FFI_SIMPLE_LI:
|
||||
result = lfn(*(long *)avalue[0], *(int *)avalue[1]);
|
||||
break;
|
||||
case FFI_SIMPLE_LL:
|
||||
result = lfn(*(long *)avalue[0], *(long *)avalue[1]);
|
||||
break;
|
||||
}
|
||||
if ((cif->flags & ~FFI_SIMPLE) != FFI_TYPE_VOID && 0 != rvalue) {
|
||||
* (long *)rvalue = result;
|
||||
}
|
||||
return;
|
||||
}
|
||||
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_UNIX:
|
||||
ffi_call_unix(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Closures represent a pair consisting of a function pointer, and
|
||||
* some user data. A closure is invoked by reinterpreting the closure
|
||||
* as a function pointer, and branching to it. Thus we can make an
|
||||
* interpreted function callable as a C function: We turn the interpreter
|
||||
* itself, together with a pointer specifying the interpreted procedure,
|
||||
* into a closure.
|
||||
* On X86, the first few words of the closure structure actually contain code,
|
||||
* which will do the right thing. On most other architectures, this
|
||||
* would raise some Icache/Dcache coherence issues (which can be solved, but
|
||||
* often not cheaply).
|
||||
* For IA64, function pointer are already pairs consisting of a code
|
||||
* pointer, and a gp pointer. The latter is needed to access global variables.
|
||||
* Here we set up such a pair as the first two words of the closure (in
|
||||
* the "trampoline" area), but we replace the gp pointer with a pointer
|
||||
* to the closure itself. We also add the real gp pointer to the
|
||||
* closure. This allows the function entry code to both retrieve the
|
||||
* user data, and to restire the correct gp pointer.
|
||||
*/
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue,
|
||||
void **avalue, ffi_cif *cif);
|
||||
|
||||
/* This function is entered with the doctored gp (r1) value.
|
||||
* This code is extremely gcc specific. There is some argument that
|
||||
* it should really be written in assembly code, since it depends on
|
||||
* gcc properties that might change over time.
|
||||
*/
|
||||
|
||||
/* ffi_closure_UNIX is an assembly routine, which copies the register */
|
||||
/* state into s struct ia64_args, and the invokes */
|
||||
/* ffi_closure_UNIX_inner. It also recovers the closure pointer */
|
||||
/* from its fake gp pointer. */
|
||||
void ffi_closure_UNIX();
|
||||
|
||||
#ifndef __GNUC__
|
||||
# error This requires gcc
|
||||
#endif
|
||||
void
|
||||
ffi_closure_UNIX_inner (ffi_closure *closure, struct ia64_args * args)
|
||||
/* Hopefully declarint this as a varargs function will force all args */
|
||||
/* to memory. */
|
||||
{
|
||||
// this is our return value storage
|
||||
long double res;
|
||||
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
unsigned short rtype;
|
||||
void *resp;
|
||||
void **arg_area;
|
||||
|
||||
resp = (void*)&res;
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_UNIX(args, (void**)&resp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
rtype = cif->flags;
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (rtype == FFI_TYPE_INT)
|
||||
{
|
||||
asm volatile ("ld8 r8=[%0]" : : "r" (resp) : "r8");
|
||||
}
|
||||
else if (rtype == FFI_TYPE_FLOAT)
|
||||
{
|
||||
asm volatile ("ldfs f8=[%0]" : : "r" (resp) : "f8");
|
||||
}
|
||||
else if (rtype == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
asm volatile ("ldfd f8=[%0]" : : "r" (resp) : "f8");
|
||||
}
|
||||
else if (rtype == FFI_IS_SMALL_STRUCT2)
|
||||
{
|
||||
asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]"
|
||||
: : "r" (resp), "r" (resp+8) : "r8","r9");
|
||||
}
|
||||
else if (rtype == FFI_IS_SMALL_STRUCT3)
|
||||
{
|
||||
asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]"
|
||||
: : "r" (resp), "r" (resp+8), "r" (resp+16)
|
||||
: "r8","r9","r10");
|
||||
}
|
||||
else if (rtype == FFI_IS_SMALL_STRUCT4)
|
||||
{
|
||||
asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]; ld8 r11=[%3]"
|
||||
: : "r" (resp), "r" (resp+8), "r" (resp+16), "r" (resp+24)
|
||||
: "r8","r9","r10","r11");
|
||||
}
|
||||
else if (rtype != FFI_TYPE_VOID && rtype != FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* Can only happen for homogeneous FP aggregates? */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register unsigned int avn;
|
||||
register void **p_argv;
|
||||
register unsigned long *argp = args -> out_regs;
|
||||
unsigned fp_reg_num = 0;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
avn = cif->nargs;
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
|
||||
{
|
||||
size_t z; /* In units of words or argument slots. */
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
z = 1;
|
||||
*p_argv = (void *)argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
z = 1;
|
||||
/* Convert argument back to float in place from the saved value */
|
||||
if (fp_reg_num < 8) {
|
||||
*(float *)argp = args -> fp_regs[fp_reg_num++];
|
||||
} else {
|
||||
*(float *)argp = *(double *)argp;
|
||||
}
|
||||
*p_argv = (void *)argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
z = 1;
|
||||
if (fp_reg_num < 8) {
|
||||
*p_argv = args -> fp_regs + fp_reg_num++;
|
||||
} else {
|
||||
*p_argv = (void *)argp;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t sz = (*p_arg)->size;
|
||||
unsigned short element_type;
|
||||
z = ((*p_arg)->size + SIZEOF_ARG - 1)/SIZEOF_ARG;
|
||||
if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) {
|
||||
int nelements = sz/float_type_size(element_type);
|
||||
if (nelements + fp_reg_num >= 8) {
|
||||
/* hard case NYI. */
|
||||
abort();
|
||||
}
|
||||
if (element_type == FFI_TYPE_DOUBLE) {
|
||||
*p_argv = args -> fp_regs + fp_reg_num;
|
||||
fp_reg_num += nelements;
|
||||
break;
|
||||
}
|
||||
if (element_type == FFI_TYPE_FLOAT) {
|
||||
int j;
|
||||
for (j = 0; j < nelements; ++ j) {
|
||||
((float *)argp)[j] = args -> fp_regs[fp_reg_num + j];
|
||||
}
|
||||
*p_argv = (void *)argp;
|
||||
fp_reg_num += nelements;
|
||||
break;
|
||||
}
|
||||
abort(); /* Other fp types NYI */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += z;
|
||||
p_argv++;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Fill in a closure to refer to the specified fun and user_data. */
|
||||
/* cif specifies the argument and result types for fun. */
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
/* The layout of a function descriptor. A C function pointer really */
|
||||
/* points to one of these. */
|
||||
typedef struct ia64_fd_struct {
|
||||
void *code_pointer;
|
||||
void *gp;
|
||||
} ia64_fd;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
struct ffi_ia64_trampoline_struct *tramp =
|
||||
(struct ffi_ia64_trampoline_struct *) (closure -> tramp);
|
||||
ia64_fd *fd = (ia64_fd *)(void *)ffi_closure_UNIX;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
tramp -> code_pointer = fd -> code_pointer;
|
||||
tramp -> real_gp = fd -> gp;
|
||||
tramp -> fake_gp = closure;
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
62
libffi/src/ia64/ia64_flags.h
Normal file
62
libffi/src/ia64/ia64_flags.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
||||
Original author: Hans Boehm, HP Labs
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* Homogeneous Floating Point Aggregates (HFAs) which are returned */
|
||||
/* in FP registers. The least significant bits specify the size in */
|
||||
/* words. */
|
||||
#define FFI_IS_FLOAT_FP_AGGREGATE 0x1000
|
||||
#define FFI_IS_DOUBLE_FP_AGGREGATE 0x0800
|
||||
#define FLOAT_FP_AGGREGATE_BIT 12
|
||||
#define DOUBLE_FP_AGGREGATE_BIT 11
|
||||
|
||||
/* Small structures containing N words. If N=1, they are returned */
|
||||
/* as though they were integers. */
|
||||
#define FFI_IS_SMALL_STRUCT2 0x40 /* Struct > 8, <=16 bytes */
|
||||
#define FFI_IS_SMALL_STRUCT3 0x41 /* Struct > 16 <= 24 bytes */
|
||||
#define FFI_IS_SMALL_STRUCT4 0x42 /* Struct > 24, <=32 bytes */
|
||||
|
||||
/* Flag values identifying particularly simple cases, which are */
|
||||
/* handled specially. We treat functions as simple if they take all */
|
||||
/* arguments can be passed as 32 or 64 bit integer quantities, there is */
|
||||
/* either no return value or it can be treated as a 64bit integer, and */
|
||||
/* if there are at most 2 arguments. */
|
||||
/* This is OR'ed with the normal flag values. */
|
||||
#define FFI_SIMPLE_V 0x10000 /* () -> X */
|
||||
#define FFI_SIMPLE_I 0x20000 /* (int) -> X */
|
||||
#define FFI_SIMPLE_L 0x30000 /* (long) -> X */
|
||||
#define FFI_SIMPLE_II 0x40000 /* (int,int) -> X */
|
||||
#define FFI_SIMPLE_IL 0x50000 /* (int,long) -> X */
|
||||
#define FFI_SIMPLE_LI 0x60000 /* (long,int) -> X */
|
||||
#define FFI_SIMPLE_LL 0x70000 /* (long,long) -> X */
|
||||
|
||||
/* Mask for all of the FFI_SIMPLE bits: */
|
||||
#define FFI_SIMPLE 0xf0000
|
||||
|
||||
/* An easy way to build FFI_SIMPLE flags from FFI_SIMPLE_V: */
|
||||
#define FFI_ADD_LONG_ARG(flag) (((flag) << 1) | 0x10000)
|
||||
#define FFI_ADD_INT_ARG(flag) ((flag) << 1)
|
301
libffi/src/ia64/unix.S
Normal file
301
libffi/src/ia64/unix.S
Normal file
@ -0,0 +1,301 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
unix.S - Copyright (c) 1998 Cygnus Solutions
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
||||
Primary author: Hans Boehm, HP Labs
|
||||
|
||||
Loosely modeled on Cygnus code for other platforms.
|
||||
|
||||
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>
|
||||
#include "ia64_flags.h"
|
||||
|
||||
/* parameters: */
|
||||
#define callback in0
|
||||
#define ecifp in1
|
||||
#define bytes in2
|
||||
#define flags in3
|
||||
#define raddr in4
|
||||
#define fn in5
|
||||
|
||||
#define FLOAT_SZ 8 /* in-memory size of fp operands */
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.global ffi_call_unix#
|
||||
.proc ffi_call_unix#
|
||||
ffi_call_unix:
|
||||
alloc loc0=ar.pfs,6,5,8,0
|
||||
mov loc1=b0;
|
||||
sub sp=sp,bytes
|
||||
mov loc4=r1 /* Save gp */
|
||||
ld8 r8=[callback],8 /* code address of callback */
|
||||
;;
|
||||
mov out0=sp
|
||||
mov out1=ecifp
|
||||
mov out2=bytes
|
||||
ld8 r1=[callback] /* Set up gp for callback. Unnecessary? */
|
||||
mov b6=r8
|
||||
;;
|
||||
br.call.sptk.many b0 = b6 /* call ffi_prep_args */
|
||||
cmp.eq p6,p0=0,r8 /* r8 nonzero ==> need fp regs */
|
||||
;;
|
||||
(p6) add loc2=32+8*FLOAT_SZ,sp
|
||||
(p6) br.cond.dptk.many fp_done
|
||||
;; /* Quiets warning; needed? */
|
||||
add loc2=32,sp
|
||||
add loc3=32+FLOAT_SZ,sp
|
||||
;;
|
||||
ldfd f8=[loc2],2*FLOAT_SZ
|
||||
ldfd f9=[loc3],2*FLOAT_SZ
|
||||
;;
|
||||
ldfd f10=[loc2],2*FLOAT_SZ
|
||||
ldfd f11=[loc3],2*FLOAT_SZ
|
||||
;;
|
||||
ldfd f12=[loc2],2*FLOAT_SZ
|
||||
ldfd f13=[loc3],2*FLOAT_SZ
|
||||
;;
|
||||
ldfd f14=[loc2],2*FLOAT_SZ
|
||||
ldfd f15=[loc3]
|
||||
fp_done:
|
||||
add r9=16,sp /* Pointer to r8_contents */
|
||||
/* loc2 points at first integer register value. */
|
||||
add loc3=8,loc2
|
||||
;;
|
||||
ld8 r8=[r9] /* Just in case we return large struct */
|
||||
ld8 out0=[loc2],16
|
||||
ld8 out1=[loc3],16
|
||||
;;
|
||||
ld8 out2=[loc2],16
|
||||
ld8 out3=[loc3],16
|
||||
;;
|
||||
ld8 out4=[loc2],16
|
||||
ld8 out5=[loc3],16
|
||||
;;
|
||||
ld8 out6=[loc2],16
|
||||
ld8 out7=[loc3]
|
||||
/* loc2 points at first stack parameter. Set sp to 16 bytes */
|
||||
/* below that. */
|
||||
add sp=-16,loc2
|
||||
|
||||
ld8 r8=[fn],8
|
||||
;;
|
||||
ld8 r1=[fn] /* Set up gp */
|
||||
mov b6=r8;;
|
||||
br.call.sptk.many b0 = b6 /* call ffi_prep_args */
|
||||
|
||||
/* Handle return value. */
|
||||
cmp.eq p6,p0=0,raddr
|
||||
cmp.eq p7,p0=FFI_TYPE_INT,flags
|
||||
cmp.eq p10,p0=FFI_IS_SMALL_STRUCT2,flags
|
||||
cmp.eq p11,p0=FFI_IS_SMALL_STRUCT3,flags
|
||||
cmp.eq p12,p0=FFI_IS_SMALL_STRUCT4,flags
|
||||
;;
|
||||
(p6) br.cond.dpnt.few done /* Dont copy ret values if raddr = 0 */
|
||||
(p7) br.cond.dptk.few copy1
|
||||
(p10) br.cond.dpnt.few copy2
|
||||
(p11) br.cond.dpnt.few copy3
|
||||
(p12) br.cond.dpnt.few copy4
|
||||
cmp.eq p8,p0=FFI_TYPE_FLOAT,flags
|
||||
cmp.eq p9,p0=FFI_TYPE_DOUBLE,flags
|
||||
tbit.nz p6,p0=flags,FLOAT_FP_AGGREGATE_BIT
|
||||
tbit.nz p7,p0=flags,DOUBLE_FP_AGGREGATE_BIT
|
||||
;;
|
||||
(p8) stfs [raddr]=f8
|
||||
(p9) stfd [raddr]=f8
|
||||
;;
|
||||
(p6) br.cond.dpnt.few handle_float_hfa
|
||||
(p7) br.cond.dpnt.few handle_double_hfa
|
||||
br done
|
||||
|
||||
copy4:
|
||||
add loc3=24,raddr
|
||||
;;
|
||||
st8 [loc3]=r11
|
||||
copy3:
|
||||
add loc3=16,raddr
|
||||
;;
|
||||
st8 [loc3]=r10
|
||||
copy2:
|
||||
add loc3=8,raddr
|
||||
;;
|
||||
st8 [loc3]=r9
|
||||
copy1:
|
||||
st8 [raddr]=r8
|
||||
/* In the big struct case, raddr was passed as an argument. */
|
||||
/* In the void case there was nothing to do. */
|
||||
|
||||
done:
|
||||
mov r1=loc4 /* Restore gp */
|
||||
mov ar.pfs = loc0
|
||||
mov b0 = loc1
|
||||
br.ret.sptk.many b0
|
||||
|
||||
handle_double_hfa:
|
||||
/* Homogeneous floating point array of doubles is returned in */
|
||||
/* registers f8-f15. Save one at a time to return area. */
|
||||
and flags=0xf,flags /* Retrieve size */
|
||||
;;
|
||||
cmp.eq p6,p0=2,flags
|
||||
cmp.eq p7,p0=3,flags
|
||||
cmp.eq p8,p0=4,flags
|
||||
cmp.eq p9,p0=5,flags
|
||||
cmp.eq p10,p0=6,flags
|
||||
cmp.eq p11,p0=7,flags
|
||||
cmp.eq p12,p0=8,flags
|
||||
;;
|
||||
(p6) br.cond.dptk.few dhfa2
|
||||
(p7) br.cond.dptk.few dhfa3
|
||||
(p8) br.cond.dptk.few dhfa4
|
||||
(p9) br.cond.dptk.few dhfa5
|
||||
(p10) br.cond.dptk.few dhfa6
|
||||
(p11) br.cond.dptk.few dhfa7
|
||||
dhfa8: add loc3=7*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f15
|
||||
dhfa7: add loc3=6*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f14
|
||||
dhfa6: add loc3=5*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f13
|
||||
dhfa5: add loc3=4*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f12
|
||||
dhfa4: add loc3=3*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f11
|
||||
dhfa3: add loc3=2*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f10
|
||||
dhfa2: add loc3=1*8,raddr
|
||||
;;
|
||||
stfd [loc3]=f9
|
||||
stfd [raddr]=f8
|
||||
br done
|
||||
|
||||
handle_float_hfa:
|
||||
/* Homogeneous floating point array of floats is returned in */
|
||||
/* registers f8-f15. Save one at a time to return area. */
|
||||
and flags=0xf,flags /* Retrieve size */
|
||||
;;
|
||||
cmp.eq p6,p0=2,flags
|
||||
cmp.eq p7,p0=3,flags
|
||||
cmp.eq p8,p0=4,flags
|
||||
cmp.eq p9,p0=5,flags
|
||||
cmp.eq p10,p0=6,flags
|
||||
cmp.eq p11,p0=7,flags
|
||||
cmp.eq p12,p0=8,flags
|
||||
;;
|
||||
(p6) br.cond.dptk.few shfa2
|
||||
(p7) br.cond.dptk.few shfa3
|
||||
(p8) br.cond.dptk.few shfa4
|
||||
(p9) br.cond.dptk.few shfa5
|
||||
(p10) br.cond.dptk.few shfa6
|
||||
(p11) br.cond.dptk.few shfa7
|
||||
shfa8: add loc3=7*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f15
|
||||
shfa7: add loc3=6*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f14
|
||||
shfa6: add loc3=5*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f13
|
||||
shfa5: add loc3=4*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f12
|
||||
shfa4: add loc3=3*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f11
|
||||
shfa3: add loc3=2*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f10
|
||||
shfa2: add loc3=1*4,raddr
|
||||
;;
|
||||
stfd [loc3]=f9
|
||||
stfd [raddr]=f8
|
||||
br done
|
||||
|
||||
.endp ffi_call_unix
|
||||
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.global ffi_closure_UNIX
|
||||
.proc ffi_closure_UNIX
|
||||
ffi_closure_UNIX:
|
||||
alloc loc0=ar.pfs,8,2,2,0
|
||||
mov loc1=b0
|
||||
/* Retrieve closure pointer and real gp. */
|
||||
mov out0=gp
|
||||
add gp=16,gp
|
||||
;;
|
||||
ld8 gp=[gp]
|
||||
/* Reserve a structia64_args on the stack such that arguments */
|
||||
/* past the first 8 are automatically placed in the right */
|
||||
/* slot. Note that when we start the sp points at 2 8-byte */
|
||||
/* scratch words, followed by the extra arguments. */
|
||||
# define BASIC_ARGS_SZ (8*FLOAT_SZ+8*8+2*8)
|
||||
# define FIRST_FP_OFFSET (4*8)
|
||||
add r14=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET),sp
|
||||
add r15=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET-FLOAT_SZ),sp
|
||||
add sp=-BASIC_ARGS_SZ,sp
|
||||
/* r14 points to fp_regs[0], r15 points to fp_regs[1] */
|
||||
;;
|
||||
stfd [r14]=f8,2*FLOAT_SZ
|
||||
stfd [r15]=f9,2*FLOAT_SZ
|
||||
;;
|
||||
stfd [r14]=f10,2*FLOAT_SZ
|
||||
stfd [r15]=f11,2*FLOAT_SZ
|
||||
;;
|
||||
stfd [r14]=f12,2*FLOAT_SZ
|
||||
stfd [r15]=f13,2*FLOAT_SZ
|
||||
;;
|
||||
stfd [r14]=f14,FLOAT_SZ+8
|
||||
stfd [r15]=f15,2*8
|
||||
;;
|
||||
/* r14 points to first parameter register area, r15 to second. */
|
||||
st8 [r14]=in0,2*8
|
||||
st8 [r15]=in1,2*8
|
||||
;;
|
||||
st8 [r14]=in2,2*8
|
||||
st8 [r15]=in3,2*8
|
||||
;;
|
||||
st8 [r14]=in4,2*8
|
||||
st8 [r15]=in5,2*8
|
||||
;;
|
||||
st8 [r14]=in6,2*8
|
||||
st8 [r15]=in7,2*8
|
||||
/* Call ffi_closure_UNIX_inner */
|
||||
mov out1=sp
|
||||
br.call.sptk.many b0=ffi_closure_UNIX_inner
|
||||
;;
|
||||
mov b0=loc1
|
||||
mov ar.pfs=loc0
|
||||
br.ret.sptk.many b0
|
||||
.endp ffi_closure_UNIX
|
||||
|
||||
|
271
libffi/src/java_raw_api.c
Normal file
271
libffi/src/java_raw_api.c
Normal file
@ -0,0 +1,271 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
java_raw_api.c - Copyright (c) 1999 Cygnus Solutions
|
||||
|
||||
Cloned from raw_api.c
|
||||
|
||||
Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
|
||||
Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
|
||||
|
||||
$Id $
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This defines a Java- and 64-bit specific variant of the raw API. */
|
||||
/* It assumes that "raw" argument blocks look like Java stacks on a */
|
||||
/* 64-bit machine. Arguments that can be stored in a single stack */
|
||||
/* stack slots (longs, doubles) occupy 128 bits, but only the first */
|
||||
/* 64 bits are actually used. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
|
||||
|
||||
size_t
|
||||
ffi_java_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
switch((*at) -> type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
result += 2 * SIZEOF_ARG;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
default:
|
||||
result += SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_ARG == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void *)raw;
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if SIZEOF_ARG == 8
|
||||
switch((*tp)->type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*args = (void*) raw;
|
||||
raw += 2;
|
||||
break;
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
#else /* SIZEOF_ARG != 8 */
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
#endif /* SIZEOF_ARG == 8 */
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_FLOAT:
|
||||
(raw++)->flt = *(FLOAT32*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
raw->uint = *(UINT64*) (*args);
|
||||
raw += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
#if SIZEOF_ARG == 8
|
||||
FFI_ASSERT(FALSE); /* Should have covered all cases */
|
||||
#else
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_java_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_java_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_java_translate_args,
|
||||
(void*)cl);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
#endif /* !FFI_NO_RAW_API */
|
@ -202,13 +202,13 @@ void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_translate_args (ffi_cif *cif, void *ravlue,
|
||||
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ ffi_prep_raw_closure (ffi_raw_closure* cl,
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_closure_translate,
|
||||
&ffi_translate_args,
|
||||
(void*)cl);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user