Pulled in libffi from gcc trunk.
Fixed build and install for standalone use.
This commit is contained in:
2419
libffi/ChangeLog
2419
libffi/ChangeLog
File diff suppressed because it is too large
Load Diff
40
libffi/ChangeLog.libgcj
Normal file
40
libffi/ChangeLog.libgcj
Normal file
@@ -0,0 +1,40 @@
|
||||
2004-01-14 Kelley Cook <kcook@gcc.gnu.org>
|
||||
|
||||
* configure.in: Add in AC_PREREQ(2.13)
|
||||
|
||||
2003-02-20 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to
|
||||
config.status.
|
||||
* configure: Rebuilt.
|
||||
|
||||
2002-01-27 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST.
|
||||
Remove USE_LIBDIR conditional.
|
||||
* Makefile.am (toolexecdir, toolexeclibdir): Don't override.
|
||||
* Makefile.in, configure: Rebuilt.
|
||||
|
||||
Mon Aug 9 18:33:38 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
|
||||
|
||||
* include/Makefile.in: Rebuilt.
|
||||
* Makefile.in: Rebuilt
|
||||
* Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native
|
||||
builds.
|
||||
Use USE_LIBDIR.
|
||||
|
||||
* configure: Rebuilt.
|
||||
* configure.in (USE_LIBDIR): Define for native builds.
|
||||
Use lowercase in configure --help explanations.
|
||||
|
||||
1999-08-08 Anthony Green <green@cygnus.com>
|
||||
|
||||
* include/ffi.h.in (FFI_FN): Remove `...'.
|
||||
|
||||
1999-08-08 Anthony Green <green@cygnus.com>
|
||||
|
||||
* Makefile.in: Rebuilt.
|
||||
* Makefile.am (AM_CFLAGS): Compile with -fexceptions.
|
||||
|
||||
* src/x86/sysv.S: Add exception handling metadata.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
libffi - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
|
||||
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,46 +1,168 @@
|
||||
## Process this with automake to create Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-installinfo
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
ACLOCAL_AMFLAGS =
|
||||
|
||||
if TESTSUBDIR
|
||||
SUBDIRS = include testsuite
|
||||
else
|
||||
SUBDIRS = include
|
||||
endif
|
||||
|
||||
EXTRA_DIST = LICENSE README ChangeLog.v1 alpha/ffi.c arm/ffi.c \
|
||||
ia64/ffi.c m68k/ffi.c mips/ffi.c powerpc/ffi.c s390/ffi.c \
|
||||
sparc/ffi.c x86/ffi.c alpha/osf.S arm/sysv.S ia64/unix.S \
|
||||
m68k/sysv.S mips/n32.S mips/o32.S \
|
||||
powerpc/sysv.S s390/sysv.S sparc/v8.S sparc/v9.S x86/win32.S \
|
||||
x86/sysv.S
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 \
|
||||
src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
|
||||
src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
|
||||
src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
|
||||
src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
|
||||
src/mips/ffitarget.h \
|
||||
src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \
|
||||
src/m68k/ffi.c src/m68k/sysv.S src/m68k/ffitarget.h \
|
||||
src/powerpc/ffi.c src/powerpc/sysv.S \
|
||||
src/powerpc/linux64.S src/powerpc/linux64_closure.S \
|
||||
src/powerpc/ppc_closure.S src/powerpc/asm.h \
|
||||
src/powerpc/aix.S src/powerpc/darwin.S \
|
||||
src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
|
||||
src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
|
||||
src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
|
||||
src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h \
|
||||
src/sh64/ffi.c src/sh64/sysv.S src/sh64/ffitarget.h \
|
||||
src/sparc/v8.S src/sparc/v9.S src/sparc/ffitarget.h \
|
||||
src/sparc/ffi.c \
|
||||
src/x86/ffi.c src/x86/sysv.S src/x86/win32.S src/x86/darwin.S \
|
||||
src/x86/ffi64.c src/x86/unix64.S src/x86/ffitarget.h \
|
||||
src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \
|
||||
src/frv/eabi.S src/frv/ffitarget.h
|
||||
|
||||
# Multilib support variables.
|
||||
MULTISRCTOP =
|
||||
MULTIBUILDTOP =
|
||||
MULTIDIRS =
|
||||
MULTISUBDIR =
|
||||
MULTIDO = true
|
||||
MULTICLEAN = true
|
||||
## ################################################################
|
||||
|
||||
## Install a library built with a cross compiler in tooldir, not
|
||||
## libdir.
|
||||
if USE_LIBDIR
|
||||
toolexeclibdir = $(libdir)$(MULTISUBDIR)
|
||||
else
|
||||
toolexecdir = $(exec_prefix)/$(target_alias)
|
||||
toolexeclibdir = $(toolexecdir)/lib$(MULTISUBDIR)
|
||||
endif
|
||||
##
|
||||
## This section is for make and multilib madness.
|
||||
##
|
||||
|
||||
# Work around what appears to be a GNU make bug handling MAKEFLAGS
|
||||
# values defined in terms of make variables, as is the case for CC and
|
||||
# friends when we are called from the top level Makefile.
|
||||
AM_MAKEFLAGS = \
|
||||
"AR_FLAGS=$(AR_FLAGS)" \
|
||||
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
|
||||
"CFLAGS=$(CFLAGS)" \
|
||||
"CXXFLAGS=$(CXXFLAGS)" \
|
||||
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
|
||||
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
|
||||
"INSTALL=$(INSTALL)" \
|
||||
"INSTALL_DATA=$(INSTALL_DATA)" \
|
||||
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
|
||||
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
|
||||
"JC1FLAGS=$(JC1FLAGS)" \
|
||||
"LDFLAGS=$(LDFLAGS)" \
|
||||
"LIBCFLAGS=$(LIBCFLAGS)" \
|
||||
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
|
||||
"MAKE=$(MAKE)" \
|
||||
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
"PICFLAG=$(PICFLAG)" \
|
||||
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
|
||||
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
|
||||
"SHELL=$(SHELL)" \
|
||||
"exec_prefix=$(exec_prefix)" \
|
||||
"infodir=$(infodir)" \
|
||||
"libdir=$(libdir)" \
|
||||
"prefix=$(prefix)" \
|
||||
"AR=$(AR)" \
|
||||
"AS=$(AS)" \
|
||||
"CC=$(CC)" \
|
||||
"CXX=$(CXX)" \
|
||||
"LD=$(LD)" \
|
||||
"NM=$(NM)" \
|
||||
"RANLIB=$(RANLIB)" \
|
||||
"DESTDIR=$(DESTDIR)"
|
||||
|
||||
MAKEOVERRIDES=
|
||||
|
||||
toolexeclib_LTLIBRARIES = libffi.la
|
||||
noinst_LTLIBRARIES = libffi_convenience.la
|
||||
|
||||
## Work around automake deficiency
|
||||
nodist_libffi_la_SOURCES = t-ffi.c t-asm.S
|
||||
libffi_la_SOURCES = debug.c prep_cif.c types.c \
|
||||
raw_api.c java_raw_api.c $(nodist_libffi_la_SOURCES)
|
||||
libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \
|
||||
src/raw_api.c src/java_raw_api.c
|
||||
|
||||
AM_CFLAGS = -fexceptions
|
||||
nodist_libffi_la_SOURCES =
|
||||
|
||||
libffi_la_LDFLAGS = -release $(VERSION)
|
||||
if MIPS_IRIX
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
endif
|
||||
if MIPS_LINUX
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S
|
||||
endif
|
||||
if X86
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if X86_WIN32
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
|
||||
endif
|
||||
if X86_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
|
||||
endif
|
||||
if SPARC
|
||||
nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
|
||||
endif
|
||||
if ALPHA
|
||||
nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
|
||||
endif
|
||||
if IA64
|
||||
nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
|
||||
endif
|
||||
if M32R
|
||||
nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
|
||||
endif
|
||||
if M68K
|
||||
nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
|
||||
endif
|
||||
if POWERPC
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
|
||||
endif
|
||||
if POWERPC_AIX
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
|
||||
endif
|
||||
if POWERPC_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
|
||||
endif
|
||||
if POWERPC_FREEBSD
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
|
||||
endif
|
||||
if ARM
|
||||
nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
|
||||
endif
|
||||
if LIBFFI_CRIS
|
||||
nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
|
||||
endif
|
||||
if FRV
|
||||
nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
|
||||
endif
|
||||
if S390
|
||||
nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
|
||||
endif
|
||||
if X86_64
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if SH
|
||||
nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
|
||||
endif
|
||||
if SH64
|
||||
nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
|
||||
endif
|
||||
if PA_LINUX
|
||||
nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
|
||||
endif
|
||||
if PA_HPUX
|
||||
nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
|
||||
endif
|
||||
|
||||
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
|
||||
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
|
||||
|
||||
AM_CFLAGS = -Wall -g -fexceptions
|
||||
|
||||
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
|
||||
|
||||
AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
|
||||
AM_CCASFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
# No install-html support
|
||||
.PHONY: install-html
|
||||
install-html:
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -Iinclude
|
||||
|
||||
1545
libffi/Makefile.in
1545
libffi/Makefile.in
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,13 @@
|
||||
README for libffi-2.00
|
||||
This directory contains the libffi package, which is not part of GCC but
|
||||
shipped with GCC as convenience.
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
libffi-2.00 has not been released yet! This is a development snapshot!
|
||||
|
||||
libffi-1.20 was released on [SOME FUTURE DAY]. Check the libffi web
|
||||
page for updates: <URL:http://sourceware.cygnus.com/libffi/>.
|
||||
libffi-1.20 was released on October 5, 1998. Check the libffi web
|
||||
page for updates: <URL:http://sources.redhat.com/libffi/>.
|
||||
|
||||
|
||||
What is libffi?
|
||||
@@ -42,34 +46,32 @@ Supported Platforms and Prerequisites
|
||||
|
||||
Libffi has been ported to:
|
||||
|
||||
SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
|
||||
|
||||
Irix 5.3 & 6.2 (System V/o32 & n32)
|
||||
|
||||
Intel x86 - Linux (System V ABI)
|
||||
|
||||
Alpha - Linux and OSF/1
|
||||
|
||||
ARM - Linux (System V ABI)
|
||||
|
||||
IA-32 - Linux, Solaris, and BeOS (System V ABI)
|
||||
|
||||
IA-64 - Linux (System V ABI)
|
||||
|
||||
m68k - Linux (System V ABI)
|
||||
|
||||
MIPS, 32- and 64-bit - Irix (System V/o32 and n32)
|
||||
PowerPC - Linux (System V ABI, Darwin, AIX)
|
||||
|
||||
PowerPC - Linux (System V ABI)
|
||||
ARM - Linux (System V ABI)
|
||||
|
||||
S390 - Linux (System V ABI)
|
||||
Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
|
||||
that other versions will work. Libffi has also been built and tested
|
||||
with the SGI compiler tools.
|
||||
|
||||
Sparc, 32-bit - SunOS 4.1.3, Solaris 2.x, and Linux (Sparc v8)
|
||||
On PowerPC, the tests failed (see the note below).
|
||||
|
||||
Sparc, 64-bit - Linux (Sparc v9)
|
||||
|
||||
|
||||
Libffi has been tested with GCC 3.00 and newer compilers.
|
||||
|
||||
You must use GNU make to build libffi.
|
||||
You must use GNU make to build libffi. SGI's make will not work.
|
||||
Sun's probably won't either.
|
||||
|
||||
If you port libffi to another platform, please let me know! I assume
|
||||
that some will be easy (x86 NetBSD), and others will be more difficult
|
||||
(HP, AIX).
|
||||
(HP).
|
||||
|
||||
|
||||
Installing libffi
|
||||
@@ -304,15 +306,9 @@ Platform Specific Notes
|
||||
|
||||
There are no known problems with the x86 port.
|
||||
|
||||
Sun Sparc - SunOS 4.1.3 & Solaris 2.x
|
||||
Sun SPARC - SunOS 4.1.3 & Solaris 2.x
|
||||
-------------------------------------
|
||||
|
||||
There's a bug in the structure passing code for sparc processors.
|
||||
Struct arguments that are passed in value actually end up being passed
|
||||
by reference. This will be fixed Real Soon Now.
|
||||
|
||||
"long long" values are not supported yet.
|
||||
|
||||
You must use GNU Make to build libffi on Sun platforms.
|
||||
|
||||
MIPS - Irix 5.3 & 6.x
|
||||
@@ -347,10 +343,7 @@ You must use GNU Make to build libffi on SGI platforms.
|
||||
------------------
|
||||
|
||||
The ARM port was performed on a NetWinder running ARM Linux ELF
|
||||
(2.0.31) and gcc 2.8.1. config.sub still does not recognize the
|
||||
machine name sa110-unknown-linux-gnu (currently returned by
|
||||
NetWinder). In the mean time the package can be configured by running
|
||||
'configure arm-linux'.
|
||||
(2.0.31) and gcc 2.8.1.
|
||||
|
||||
|
||||
|
||||
@@ -382,17 +375,6 @@ arguments' test).
|
||||
History
|
||||
=======
|
||||
|
||||
2.00 ???-??-01
|
||||
|
||||
Many configure improvements. No more run tests required at
|
||||
configure time so cross compiling should work well. ffi.h is
|
||||
target independent now and may be installed safely anywhere.
|
||||
ffitest replaced with dejagnu testing infrastructure. s390
|
||||
port from ????. ia64 port from Hans Boehm. General
|
||||
performance improvements. Closures designed and implemented
|
||||
by Kresten Krab Thorup and ported to ia64 and powerpc by Hans
|
||||
Boehm and ???? respectively.
|
||||
|
||||
1.20 Oct-5-98
|
||||
Raffaele Sena produces ARM port.
|
||||
|
||||
@@ -476,19 +458,19 @@ History
|
||||
Authors & Credits
|
||||
=================
|
||||
|
||||
libffi was written by Anthony Green <green@redhat.com>.
|
||||
libffi was written by Anthony Green <green@cygnus.com>.
|
||||
|
||||
Portions of libffi were derived from Gianni Mariani's free gencall
|
||||
library for Silicon Graphics machines.
|
||||
|
||||
The closure mechanism was designed and implemented on IA-32 by Kresten
|
||||
Krab Thorup.
|
||||
The closure mechanism was designed and implemented by Kresten Krab
|
||||
Thorup.
|
||||
|
||||
The initial Sparc port was derived from code contributed by the fine
|
||||
folks at Visible Decisions Inc. Further enhancements were made by
|
||||
Gordon Irlam while at Cygnus Solutions.
|
||||
The Sparc port was derived from code contributed by the fine folks at
|
||||
Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
|
||||
made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
|
||||
|
||||
The Alpha port was written by Richard Henderson at Cygnus Solutions/Red Hat.
|
||||
The Alpha port was written by Richard Henderson at Cygnus Solutions.
|
||||
|
||||
Andreas Schwab ported libffi to m68k Linux and provided a number of
|
||||
bug fixes.
|
||||
@@ -497,10 +479,6 @@ Geoffrey Keating ported libffi to the PowerPC.
|
||||
|
||||
Raffaele Sena ported libffi to the ARM.
|
||||
|
||||
Hans Boehm ported libffi to IA-64.
|
||||
|
||||
Jakub Jelinek ported libffi to 32- and 64-bit Sparc Linux.
|
||||
|
||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
||||
stepping through the code and tracking down bugs.
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/* Define this if you want extra debugging */
|
||||
#undef FFI_DEBUG
|
||||
|
||||
/* Define this if you are using Purify and want to suppress
|
||||
spurious messages. */
|
||||
#undef USING_PURIFY
|
||||
|
||||
/* Define this is you do not want support for aggregate types. */
|
||||
#undef FFI_NO_STRUCTS
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
#undef FFI_NO_RAW_API
|
||||
@@ -1,97 +1,92 @@
|
||||
AC_DEFUN([AC_COMPILE_CHECK_SIZEOF],
|
||||
[changequote(<<, >>)dnl
|
||||
dnl The name to #define.
|
||||
define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
|
||||
dnl The cache variable name.
|
||||
define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
|
||||
changequote([, ])dnl
|
||||
AC_MSG_CHECKING(size of $1)
|
||||
AC_CACHE_VAL(AC_CV_NAME,
|
||||
[for ac_size in 4 8 1 2 16 12 $2 ; do # List sizes in rough order of prevalence.
|
||||
AC_TRY_COMPILE([#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
$2
|
||||
], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size)
|
||||
if test x$AC_CV_NAME != x ; then break; fi
|
||||
done
|
||||
])
|
||||
if test x$AC_CV_NAME = x ; then
|
||||
AC_MSG_ERROR([cannot determine a size for $1])
|
||||
fi
|
||||
AC_MSG_RESULT($AC_CV_NAME)
|
||||
AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
|
||||
undefine([AC_TYPE_NAME])dnl
|
||||
undefine([AC_CV_NAME])dnl
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([AC_C_BIGENDIAN_CROSS],
|
||||
[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian,
|
||||
[ac_cv_c_bigendian=unknown
|
||||
# See if sys/param.h defines the BYTE_ORDER macro.
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/param.h>], [
|
||||
#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
|
||||
bogus endian macros
|
||||
#endif], [# It does; now see whether it defined to BIG_ENDIAN or not.
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/param.h>], [
|
||||
#if BYTE_ORDER != BIG_ENDIAN
|
||||
not big endian
|
||||
#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)])
|
||||
if test $ac_cv_c_bigendian = unknown; then
|
||||
AC_TRY_RUN([main () {
|
||||
/* Are we little or big endian? From Harbison&Steele. */
|
||||
union
|
||||
{
|
||||
long l;
|
||||
char c[sizeof (long)];
|
||||
} u;
|
||||
u.l = 1;
|
||||
exit (u.c[sizeof (long) - 1] == 1);
|
||||
}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes,
|
||||
[ echo $ac_n "cross-compiling... " 2>&AC_FD_MSG ])
|
||||
fi])
|
||||
if test $ac_cv_c_bigendian = unknown; then
|
||||
AC_MSG_CHECKING(to probe for byte ordering)
|
||||
# mmap(2) blacklisting. Some platforms provide the mmap library routine
|
||||
# but don't support all of the features we need from it.
|
||||
AC_DEFUN([AC_FUNC_MMAP_BLACKLIST],
|
||||
[
|
||||
cat >conftest.c <<EOF
|
||||
short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
|
||||
short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
|
||||
void _ascii() { char* s = (char*) ascii_mm; s = (char*) ascii_ii; }
|
||||
short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
|
||||
short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
|
||||
void _ebcdic() { char* s = (char*) ebcdic_mm; s = (char*) ebcdic_ii; }
|
||||
int main() { _ascii (); _ebcdic (); return 0; }
|
||||
EOF
|
||||
] if test -f conftest.c ; then
|
||||
if ${CC-cc} ${CFLAGS} conftest.c -o conftest.o && test -f conftest.o ; then
|
||||
if test `grep -l BIGenDianSyS conftest.o` ; then
|
||||
echo $ac_n ' big endian probe OK, ' 1>&AC_FD_MSG
|
||||
ac_cv_c_bigendian=yes
|
||||
fi
|
||||
if test `grep -l LiTTleEnDian conftest.o` ; then
|
||||
echo $ac_n ' little endian probe OK, ' 1>&AC_FD_MSG
|
||||
if test $ac_cv_c_bigendian = yes ; then
|
||||
ac_cv_c_bigendian=unknown;
|
||||
else
|
||||
ac_cv_c_bigendian=no
|
||||
fi
|
||||
fi
|
||||
echo $ac_n 'guessing bigendian ... ' >&AC_FD_MSG
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT($ac_cv_c_bigendian)
|
||||
fi
|
||||
if test $ac_cv_c_bigendian = yes; then
|
||||
AC_DEFINE(WORDS_BIGENDIAN, 1, [whether byteorder is bigendian])
|
||||
BYTEORDER=4321
|
||||
AC_CHECK_HEADER([sys/mman.h],
|
||||
[libffi_header_sys_mman_h=yes], [libffi_header_sys_mman_h=no])
|
||||
AC_CHECK_FUNC([mmap], [libffi_func_mmap=yes], [libffi_func_mmap=no])
|
||||
if test "$libffi_header_sys_mman_h" != yes \
|
||||
|| test "$libffi_func_mmap" != yes; then
|
||||
ac_cv_func_mmap_file=no
|
||||
ac_cv_func_mmap_dev_zero=no
|
||||
ac_cv_func_mmap_anon=no
|
||||
else
|
||||
BYTEORDER=1234
|
||||
AC_CACHE_CHECK([whether read-only mmap of a plain file works],
|
||||
ac_cv_func_mmap_file,
|
||||
[# Add a system to this blacklist if
|
||||
# mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
|
||||
# memory area containing the same data that you'd get if you applied
|
||||
# read() to the same fd. The only system known to have a problem here
|
||||
# is VMS, where text files have record structure.
|
||||
case "$host_os" in
|
||||
vms* | ultrix*)
|
||||
ac_cv_func_mmap_file=no ;;
|
||||
*)
|
||||
ac_cv_func_mmap_file=yes;;
|
||||
esac])
|
||||
AC_CACHE_CHECK([whether mmap from /dev/zero works],
|
||||
ac_cv_func_mmap_dev_zero,
|
||||
[# Add a system to this blacklist if it has mmap() but /dev/zero
|
||||
# does not exist, or if mmapping /dev/zero does not give anonymous
|
||||
# zeroed pages with both the following properties:
|
||||
# 1. If you map N consecutive pages in with one call, and then
|
||||
# unmap any subset of those pages, the pages that were not
|
||||
# explicitly unmapped remain accessible.
|
||||
# 2. If you map two adjacent blocks of memory and then unmap them
|
||||
# both at once, they must both go away.
|
||||
# Systems known to be in this category are Windows (all variants),
|
||||
# VMS, and Darwin.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
|
||||
ac_cv_func_mmap_dev_zero=no ;;
|
||||
*)
|
||||
ac_cv_func_mmap_dev_zero=yes;;
|
||||
esac])
|
||||
|
||||
# Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
|
||||
AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon,
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
],
|
||||
[int n = MAP_ANONYMOUS;],
|
||||
ac_cv_decl_map_anon=yes,
|
||||
ac_cv_decl_map_anon=no)])
|
||||
|
||||
if test $ac_cv_decl_map_anon = no; then
|
||||
ac_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
|
||||
ac_cv_func_mmap_anon,
|
||||
[# Add a system to this blacklist if it has mmap() and MAP_ANON or
|
||||
# MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
# doesn't give anonymous zeroed pages with the same properties listed
|
||||
# above for use of /dev/zero.
|
||||
# Systems known to be in this category are Windows, VMS, and SCO Unix.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | sco* | udk* )
|
||||
ac_cv_func_mmap_anon=no ;;
|
||||
*)
|
||||
ac_cv_func_mmap_anon=yes;;
|
||||
esac])
|
||||
fi
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(BYTEORDER, $BYTEORDER, [1234 = LIL_ENDIAN, 4321 = BIGENDIAN])
|
||||
if test $ac_cv_c_bigendian = unknown; then
|
||||
AC_MSG_ERROR(unknown endianess - sorry, please pre-set ac_cv_c_bigendian)
|
||||
|
||||
if test $ac_cv_func_mmap_file = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_FILE, 1,
|
||||
[Define if read-only mmap of a plain file works.])
|
||||
fi
|
||||
if test $ac_cv_func_mmap_dev_zero = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
|
||||
[Define if mmap of /dev/zero works.])
|
||||
fi
|
||||
if test $ac_cv_func_mmap_anon = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_ANON, 1,
|
||||
[Define if mmap with MAP_ANON(YMOUS) works.])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
7734
libffi/aclocal.m4
vendored
7734
libffi/aclocal.m4
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,111 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998 Cygnus Solutions
|
||||
|
||||
ARM 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
/* XXX these lose for some platforms, I'm sure. */
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
# a1: ffi_prep_args
|
||||
# a2: &ecif
|
||||
# a3: cif->bytes
|
||||
# a4: fig->flags
|
||||
# sp+0: ecif.rvalue
|
||||
# sp+4: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
ENTRY(ffi_call_SYSV)
|
||||
# Save registers
|
||||
stmfd sp!, {a1-a4, fp, lr}
|
||||
mov fp, sp
|
||||
|
||||
# Make room for all of the new args.
|
||||
sub sp, fp, a3
|
||||
|
||||
# Place all of the ffi_prep_args in position
|
||||
mov ip, a1
|
||||
mov a1, sp
|
||||
# a2 already set
|
||||
|
||||
# And call
|
||||
mov lr, pc
|
||||
mov pc, ip
|
||||
|
||||
# move first 4 parameters in registers
|
||||
ldr a1, [sp, #0]
|
||||
ldr a2, [sp, #4]
|
||||
ldr a3, [sp, #8]
|
||||
ldr a4, [sp, #12]
|
||||
|
||||
# and adjust stack
|
||||
ldr ip, [fp, #8]
|
||||
cmp ip, #16
|
||||
movge ip, #16
|
||||
add sp, sp, ip
|
||||
|
||||
# call function
|
||||
mov lr, pc
|
||||
ldr pc, [fp, #28]
|
||||
|
||||
# Remove the space we pushed for the args
|
||||
mov sp, fp
|
||||
|
||||
# Load a3 with the pointer to storage for the return value
|
||||
ldr a3, [sp, #24]
|
||||
|
||||
# Load a4 with the return type code
|
||||
ldr a4, [sp, #12]
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
cmp a3, #0
|
||||
beq epilogue
|
||||
|
||||
# return INT
|
||||
cmp a4, #FFI_TYPE_INT
|
||||
streq a1, [a3]
|
||||
beq epilogue
|
||||
|
||||
# return FLOAT
|
||||
cmp a4, #FFI_TYPE_FLOAT
|
||||
stfeqs f0, [a3]
|
||||
beq epilogue
|
||||
|
||||
# return DOUBLE or LONGDOUBLE
|
||||
cmp a4, #FFI_TYPE_DOUBLE
|
||||
stfeqd f0, [a3]
|
||||
|
||||
epilogue:
|
||||
ldmfd sp!, {a1-a4, fp, pc}
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
142
libffi/compile
Executable file
142
libffi/compile
Executable file
@@ -0,0 +1,142 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand `-c -o'.
|
||||
|
||||
scriptversion=2005-05-14.22
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand `-c -o'.
|
||||
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file `INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
eat=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as `compile cc -o foo foo.c'.
|
||||
# So we strip `-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no `-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# `.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use `[/.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
1335
libffi/config.guess
vendored
1335
libffi/config.guess
vendored
File diff suppressed because it is too large
Load Diff
541
libffi/config.sub
vendored
541
libffi/config.sub
vendored
@@ -1,9 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script, version 1.1.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
||||
# Free Software Foundation, Inc.
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
version='2001-04-06'
|
||||
timestamp='2005-07-08'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -21,15 +21,17 @@ version='2001-04-06'
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
@@ -60,33 +62,45 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||
Canonicalize a configuration name.
|
||||
|
||||
Operation modes:
|
||||
-h, --help print this help, then exit
|
||||
-V, --version print version number, then exit"
|
||||
-h, --help print this help, then exit
|
||||
-t, --time-stamp print date of last modification, then exit
|
||||
-v, --version print version number, then exit
|
||||
|
||||
Report bugs and patches to <config-patches@gnu.org>."
|
||||
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
||||
help="
|
||||
Try \`$me --help' for more information."
|
||||
|
||||
# Parse command line
|
||||
while test $# -gt 0 ; do
|
||||
case "$1" in
|
||||
--version | --vers* | -V )
|
||||
echo "$version" ; exit 0 ;;
|
||||
case $1 in
|
||||
--time-stamp | --time* | -t )
|
||||
echo "$timestamp" ; exit ;;
|
||||
--version | -v )
|
||||
echo "$version" ; exit ;;
|
||||
--help | --h* | -h )
|
||||
echo "$usage"; exit 0 ;;
|
||||
echo "$usage"; exit ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
- ) # Use stdin as input.
|
||||
break ;;
|
||||
-* )
|
||||
exec >&2
|
||||
echo "$me: invalid option $1"
|
||||
echo "$help"
|
||||
echo "$me: invalid option $1$help"
|
||||
exit 1 ;;
|
||||
|
||||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo $1
|
||||
exit 0;;
|
||||
exit ;;
|
||||
|
||||
* )
|
||||
break ;;
|
||||
@@ -105,7 +119,8 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | storm-chaos*)
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
|
||||
kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
@@ -131,7 +146,7 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis)
|
||||
-apple | -axis | -knuth | -cray)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
@@ -211,22 +226,57 @@ esac
|
||||
case $basic_machine in
|
||||
# Recognize the basic CPU types without company name.
|
||||
# Some are omitted here because they have special meanings below.
|
||||
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm | xscale \
|
||||
| arme[lb] | armv[2345] | armv[345][lb] | pyramid | mn10200 | mn10300 | tron | a29k \
|
||||
| 580 | i960 | h8300 \
|
||||
| x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \
|
||||
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
|
||||
| hppa64 \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
|
||||
| alphaev6[78] \
|
||||
| we32k | ns16k | clipper | i370 | sh | sh[34] \
|
||||
| powerpc | powerpcle \
|
||||
| 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
|
||||
| mips64orion | mips64orionel | mipstx39 | mipstx39el \
|
||||
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr5000 | miprs64vr5000el | mcore \
|
||||
| sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
|
||||
| thumb | d10v | d30v | fr30 | avr)
|
||||
1750a | 580 \
|
||||
| a29k \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64orion | mips64orionel \
|
||||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| ms1 \
|
||||
| msp430 \
|
||||
| ns16k | ns32k \
|
||||
| or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| z8k)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m32c)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
@@ -234,13 +284,13 @@ case $basic_machine in
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl)
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
i[234567]86 | x86_64)
|
||||
i*86 | x86_64)
|
||||
basic_machine=$basic_machine-pc
|
||||
;;
|
||||
# Object if more than one company name word.
|
||||
@@ -249,28 +299,67 @@ case $basic_machine in
|
||||
exit 1
|
||||
;;
|
||||
# Recognize the basic CPU types with company name.
|
||||
# FIXME: clean up the formatting here.
|
||||
vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
|
||||
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
|
||||
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
|
||||
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
|
||||
| xmp-* | ymp-* \
|
||||
| x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \
|
||||
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
|
||||
| hppa2.0n-* | hppa64-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
|
||||
| alphaev6[78]-* \
|
||||
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
|
||||
| clipper-* | orion-* \
|
||||
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
|
||||
| sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
|
||||
| mips64el-* | mips64orion-* | mips64orionel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
|
||||
| mipstx39-* | mipstx39el-* | mcore-* \
|
||||
| f301-* | armv*-* | s390-* | s390x-* | sv1-* | t3e-* \
|
||||
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
|
||||
| thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \
|
||||
| bs2000-* | tic54x-* | c54x-* | x86_64-*)
|
||||
580-* \
|
||||
| a29k-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64orion-* | mips64orionel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| ms1-* \
|
||||
| msp430-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
;;
|
||||
m32c-*)
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
@@ -288,6 +377,9 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
basic_machine=m68010-adobe
|
||||
os=-scout
|
||||
@@ -302,6 +394,12 @@ case $basic_machine in
|
||||
basic_machine=a29k-none
|
||||
os=-bsd
|
||||
;;
|
||||
amd64)
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
amd64-*)
|
||||
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
os=-sysv
|
||||
@@ -333,6 +431,10 @@ case $basic_machine in
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
convex-c1)
|
||||
basic_machine=c1-convex
|
||||
os=-bsd
|
||||
@@ -353,30 +455,45 @@ case $basic_machine in
|
||||
basic_machine=c38-convex
|
||||
os=-bsd
|
||||
;;
|
||||
cray | ymp)
|
||||
basic_machine=ymp-cray
|
||||
cray | j90)
|
||||
basic_machine=j90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cray2)
|
||||
basic_machine=cray2-cray
|
||||
os=-unicos
|
||||
craynv)
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
[ctj]90-cray)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
crisv32 | crisv32-* | etraxfs*)
|
||||
basic_machine=crisv32-axis
|
||||
;;
|
||||
cris | cris-* | etrax*)
|
||||
basic_machine=cris-axis
|
||||
;;
|
||||
crx)
|
||||
basic_machine=crx-unknown
|
||||
os=-elf
|
||||
;;
|
||||
da30 | da30-*)
|
||||
basic_machine=m68k-da30
|
||||
;;
|
||||
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
|
||||
basic_machine=mips-dec
|
||||
;;
|
||||
decsystem10* | dec10*)
|
||||
basic_machine=pdp10-dec
|
||||
os=-tops10
|
||||
;;
|
||||
decsystem20* | dec20*)
|
||||
basic_machine=pdp10-dec
|
||||
os=-tops20
|
||||
;;
|
||||
delta | 3300 | motorola-3300 | motorola-delta \
|
||||
| 3300-motorola | delta-motorola)
|
||||
basic_machine=m68k-motorola
|
||||
@@ -385,6 +502,10 @@ case $basic_machine in
|
||||
basic_machine=m88k-motorola
|
||||
os=-sysv3
|
||||
;;
|
||||
djgpp)
|
||||
basic_machine=i586-pc
|
||||
os=-msdosdjgpp
|
||||
;;
|
||||
dpx20 | dpx20-*)
|
||||
basic_machine=rs6000-bull
|
||||
os=-bosx
|
||||
@@ -418,6 +539,10 @@ case $basic_machine in
|
||||
basic_machine=tron-gmicro
|
||||
os=-sysv
|
||||
;;
|
||||
go32)
|
||||
basic_machine=i386-pc
|
||||
os=-go32
|
||||
;;
|
||||
h3050r* | hiux*)
|
||||
basic_machine=hppa1.1-hitachi
|
||||
os=-hiuxwe2
|
||||
@@ -493,19 +618,19 @@ case $basic_machine in
|
||||
basic_machine=i370-ibm
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i[34567]86v32)
|
||||
i*86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
;;
|
||||
i[34567]86v4*)
|
||||
i*86v4*)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv4
|
||||
;;
|
||||
i[34567]86v)
|
||||
i*86v)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv
|
||||
;;
|
||||
i[34567]86sol2)
|
||||
i*86sol2)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-solaris2
|
||||
;;
|
||||
@@ -517,18 +642,6 @@ case $basic_machine in
|
||||
basic_machine=i386-unknown
|
||||
os=-vsta
|
||||
;;
|
||||
i386-go32 | go32)
|
||||
basic_machine=i386-unknown
|
||||
os=-go32
|
||||
;;
|
||||
i386-mingw32 | mingw32)
|
||||
basic_machine=i386-unknown
|
||||
os=-mingw32
|
||||
;;
|
||||
i[34567]86-pw32 | pw32)
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
iris | iris4d)
|
||||
basic_machine=mips-sgi
|
||||
case $os in
|
||||
@@ -554,6 +667,10 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
@@ -561,30 +678,22 @@ case $basic_machine in
|
||||
basic_machine=m68k-atari
|
||||
os=-mint
|
||||
;;
|
||||
mipsel*-linux*)
|
||||
basic_machine=mipsel-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips*-linux*)
|
||||
basic_machine=mips-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips3*-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
||||
;;
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
;;
|
||||
morphos)
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-unknown
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
;;
|
||||
mvs)
|
||||
@@ -648,6 +757,10 @@ case $basic_machine in
|
||||
basic_machine=i960-intel
|
||||
os=-mon960
|
||||
;;
|
||||
nonstopux)
|
||||
basic_machine=mips-compaq
|
||||
os=-nonstopux
|
||||
;;
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
@@ -658,6 +771,13 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
openrisc | openrisc-*)
|
||||
basic_machine=or32-unknown
|
||||
;;
|
||||
os400)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-os400
|
||||
;;
|
||||
OSE68000 | ose68000)
|
||||
basic_machine=m68000-ericsson
|
||||
os=-ose
|
||||
@@ -680,45 +800,65 @@ case $basic_machine in
|
||||
pbb)
|
||||
basic_machine=m68k-tti
|
||||
;;
|
||||
pc532 | pc532-*)
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexen)
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
pentiumpro | p6 | 6x86 | athlon)
|
||||
pentiumpro | p6 | 6x86 | athlon | athlon_*)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentiumii | pentium2)
|
||||
pentiumii | pentium2 | pentiumiii | pentium3)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium4)
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexen-*)
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumii-* | pentium2-*)
|
||||
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium4-*)
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
;;
|
||||
power) basic_machine=rs6000-ibm
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
;;
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
;;
|
||||
;;
|
||||
ppcle-* | powerpclittle-*)
|
||||
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64) basic_machine=powerpc64-unknown
|
||||
;;
|
||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||
basic_machine=powerpc64le-unknown
|
||||
;;
|
||||
ppc64le-* | powerpc64little-*)
|
||||
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ps2)
|
||||
basic_machine=i386-ibm
|
||||
;;
|
||||
pw32)
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
@@ -729,10 +869,26 @@ case $basic_machine in
|
||||
rtpc | rtpc-*)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
s390 | s390-*)
|
||||
basic_machine=s390-ibm
|
||||
;;
|
||||
s390x | s390x-*)
|
||||
basic_machine=s390x-ibm
|
||||
;;
|
||||
sa29200)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
sb1)
|
||||
basic_machine=mipsisa64sb1-unknown
|
||||
;;
|
||||
sb1el)
|
||||
basic_machine=mipsisa64sb1el-unknown
|
||||
;;
|
||||
sei)
|
||||
basic_machine=mips-sei
|
||||
os=-seiux
|
||||
;;
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
@@ -740,7 +896,10 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sparclite-wrs)
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparclite-wrs | simso-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
@@ -807,22 +966,42 @@ case $basic_machine in
|
||||
os=-dynix
|
||||
;;
|
||||
t3e)
|
||||
basic_machine=t3e-cray
|
||||
basic_machine=alphaev5-cray
|
||||
os=-unicos
|
||||
;;
|
||||
t90)
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
tx39el)
|
||||
basic_machine=mipstx39el-unknown
|
||||
;;
|
||||
toad1)
|
||||
basic_machine=pdp10-xkl
|
||||
os=-tops20
|
||||
;;
|
||||
tower | tower-32)
|
||||
basic_machine=m68k-ncr
|
||||
;;
|
||||
tpf)
|
||||
basic_machine=s390x-ibm
|
||||
os=-tpf
|
||||
;;
|
||||
udi29k)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
@@ -844,8 +1023,8 @@ case $basic_machine in
|
||||
os=-vms
|
||||
;;
|
||||
vpp*|vx|vx-*)
|
||||
basic_machine=f301-fujitsu
|
||||
;;
|
||||
basic_machine=f301-fujitsu
|
||||
;;
|
||||
vxworks960)
|
||||
basic_machine=i960-wrs
|
||||
os=-vxworks
|
||||
@@ -866,13 +1045,17 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
xmp)
|
||||
basic_machine=xmp-cray
|
||||
os=-unicos
|
||||
xbox)
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
xps | xps100)
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
z8k-*-coff)
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
@@ -893,35 +1076,35 @@ case $basic_machine in
|
||||
op60c)
|
||||
basic_machine=hppa1.1-oki
|
||||
;;
|
||||
mips)
|
||||
if [ x$os = x-linux-gnu ]; then
|
||||
basic_machine=mips-unknown
|
||||
else
|
||||
basic_machine=mips-mips
|
||||
fi
|
||||
;;
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
mmix)
|
||||
basic_machine=mmix-knuth
|
||||
;;
|
||||
rs6000)
|
||||
basic_machine=rs6000-ibm
|
||||
;;
|
||||
vax)
|
||||
basic_machine=vax-dec
|
||||
;;
|
||||
pdp10)
|
||||
# there are many clones, so DEC is not a safe bet
|
||||
basic_machine=pdp10-unknown
|
||||
;;
|
||||
pdp11)
|
||||
basic_machine=pdp11-dec
|
||||
;;
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4)
|
||||
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sparc | sparcv9)
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
cydra)
|
||||
basic_machine=cydra-cydrome
|
||||
;;
|
||||
orion)
|
||||
@@ -936,13 +1119,9 @@ case $basic_machine in
|
||||
pmac | pmac-mpw)
|
||||
basic_machine=powerpc-apple
|
||||
;;
|
||||
c4x*)
|
||||
basic_machine=c4x-none
|
||||
os=-coff
|
||||
;;
|
||||
*-unknown)
|
||||
# Make sure to match an already-canonicalized machine name.
|
||||
;;
|
||||
# Make sure to match an already-canonicalized machine name.
|
||||
;;
|
||||
*)
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
@@ -995,36 +1174,47 @@ case $os in
|
||||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -storm-chaos*)
|
||||
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
case $basic_machine in
|
||||
x86-* | i[34567]86-*)
|
||||
x86-* | i*86-*)
|
||||
;;
|
||||
*)
|
||||
os=-nto$os
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-nto-qnx*)
|
||||
;;
|
||||
-nto*)
|
||||
os=-nto-qnx
|
||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
os=`echo $os | sed -e 's|mac|macos|'`
|
||||
;;
|
||||
-linux-dietlibc)
|
||||
os=-linux-dietlibc
|
||||
;;
|
||||
-linux*)
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
@@ -1037,6 +1227,9 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
os=-wince
|
||||
;;
|
||||
@@ -1055,14 +1248,23 @@ case $os in
|
||||
-acis*)
|
||||
os=-aos
|
||||
;;
|
||||
-atheos*)
|
||||
os=-atheos
|
||||
;;
|
||||
-syllable*)
|
||||
os=-syllable
|
||||
;;
|
||||
-386bsd)
|
||||
os=-bsd
|
||||
;;
|
||||
-ctix* | -uts*)
|
||||
os=-sysv
|
||||
;;
|
||||
-nova*)
|
||||
os=-rtmk-nova
|
||||
;;
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
os=-nextstep2
|
||||
;;
|
||||
-nsk*)
|
||||
os=-nsk
|
||||
@@ -1074,6 +1276,9 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
os=-sysv3
|
||||
;;
|
||||
@@ -1101,8 +1306,17 @@ case $os in
|
||||
-xenix)
|
||||
os=-xenix
|
||||
;;
|
||||
-*mint | -*MiNT)
|
||||
os=-mint
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
os=-mint
|
||||
;;
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
@@ -1135,7 +1349,14 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
pdp11-*)
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
;;
|
||||
pdp11-*)
|
||||
os=-none
|
||||
;;
|
||||
*-dec | vax-*)
|
||||
@@ -1162,6 +1383,9 @@ case $basic_machine in
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
or32-*)
|
||||
os=-coff
|
||||
;;
|
||||
*-tti) # must be before sparc entry or we get the wrong os.
|
||||
os=-sysv3
|
||||
;;
|
||||
@@ -1171,9 +1395,15 @@ case $basic_machine in
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-haiku)
|
||||
os=-haiku
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
@@ -1225,25 +1455,25 @@ case $basic_machine in
|
||||
*-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
*-gould)
|
||||
*-gould)
|
||||
os=-sysv
|
||||
;;
|
||||
*-highlevel)
|
||||
*-highlevel)
|
||||
os=-bsd
|
||||
;;
|
||||
*-encore)
|
||||
os=-bsd
|
||||
;;
|
||||
*-sgi)
|
||||
*-sgi)
|
||||
os=-irix
|
||||
;;
|
||||
*-siemens)
|
||||
*-siemens)
|
||||
os=-sysv4
|
||||
;;
|
||||
*-masscomp)
|
||||
os=-rtu
|
||||
;;
|
||||
f301-fujitsu)
|
||||
f30[01]-fujitsu | f700-fujitsu)
|
||||
os=-uxpv
|
||||
;;
|
||||
*-rom68k)
|
||||
@@ -1306,10 +1536,16 @@ case $basic_machine in
|
||||
-mvs* | -opened*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-os400*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-ptx*)
|
||||
vendor=sequent
|
||||
;;
|
||||
-vxsim* | -vxworks*)
|
||||
-tpf*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-vxsim* | -vxworks* | -windiss*)
|
||||
vendor=wrs
|
||||
;;
|
||||
-aux*)
|
||||
@@ -1321,20 +1557,23 @@ case $basic_machine in
|
||||
-mpw* | -macos*)
|
||||
vendor=apple
|
||||
;;
|
||||
-*mint | -*MiNT)
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
vendor=atari
|
||||
;;
|
||||
-vos*)
|
||||
vendor=stratus
|
||||
;;
|
||||
esac
|
||||
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
exit 0
|
||||
exit
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "version='"
|
||||
# time-stamp-start: "timestamp='"
|
||||
# time-stamp-format: "%:y-%02m-%02d"
|
||||
# time-stamp-end: "'"
|
||||
# End:
|
||||
|
||||
24698
libffi/configure
vendored
24698
libffi/configure
vendored
File diff suppressed because it is too large
Load Diff
295
libffi/configure.ac
Normal file
295
libffi/configure.ac
Normal file
@@ -0,0 +1,295 @@
|
||||
dnl Process this with autoconf to create configure
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
AC_INIT([libffi], [2.1], [http://gcc.gnu.org/bugs.html])
|
||||
AC_CONFIG_HEADERS([fficonfig.h])
|
||||
|
||||
dnl LIBFFI LOCAL: no multilib here.
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
target_alias=${target_alias-$host_alias}
|
||||
|
||||
. ${srcdir}/configure.host
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
# The same as in boehm-gc and libstdc++. Have to borrow it from there.
|
||||
# We must force CC to /not/ be precious variables; otherwise
|
||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
||||
# As a side effect, we have to subst CFLAGS ourselves.
|
||||
|
||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
||||
AC_PROG_CC
|
||||
m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
|
||||
AM_PROG_AS
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_CHECK_HEADERS(sys/mman.h)
|
||||
AC_CHECK_FUNCS(mmap)
|
||||
AC_FUNC_MMAP_BLACKLIST
|
||||
|
||||
dnl The -no-testsuite modules omit the test subdir.
|
||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
||||
|
||||
TARGETDIR="unknown"
|
||||
case "$host" in
|
||||
i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-solaris2.1[[0-9]]*) TARGET=X86_64; TARGETDIR=x86;;
|
||||
i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
|
||||
i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-rtems*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-win32*) TARGET=X86_WIN32; TARGETDIR=x86;;
|
||||
i*86-*-cygwin*) TARGET=X86_WIN32; TARGETDIR=x86;;
|
||||
i*86-*-mingw*) TARGET=X86_WIN32; TARGETDIR=x86;;
|
||||
frv-*-*) TARGET=FRV; TARGETDIR=frv;;
|
||||
sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc*-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc-*-linux* | sparc-*-netbsdelf* | sparc-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc*-*-rtems*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc64-*-linux* | sparc64-*-freebsd* | sparc64-*-netbsd* | sparc64-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
alpha*-*-linux* | alpha*-*-osf* | alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu | alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu) TARGET=ALPHA; TARGETDIR=alpha;;
|
||||
ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
|
||||
m32r*-*-linux* ) TARGET=M32R; TARGETDIR=m32r;;
|
||||
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
|
||||
mips64*-*);;
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.*) TARGET=MIPS_IRIX; TARGETDIR=mips;;
|
||||
mips*-*-linux*) TARGET=MIPS_LINUX; TARGETDIR=mips;;
|
||||
powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
|
||||
powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
|
||||
powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;;
|
||||
powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
|
||||
arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
|
||||
arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
|
||||
arm*-*-rtems*) TARGET=ARM; TARGETDIR=arm;;
|
||||
cris-*-*) TARGET=LIBFFI_CRIS; TARGETDIR=cris;;
|
||||
s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
|
||||
s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
|
||||
x86_64-*-linux* | x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) TARGET=X86_64; TARGETDIR=x86;;
|
||||
x86_64-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
|
||||
sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
|
||||
sh-*-rtems*) TARGET=SH; TARGETDIR=sh;;
|
||||
sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
|
||||
hppa*-*-linux* | parisc*-*-linux*) TARGET=PA_LINUX; TARGETDIR=pa;;
|
||||
hppa*64-*-hpux*) TARGET=PA64_HPUX; TARGETDIR=pa;;
|
||||
hppa*-*-hpux*) TARGET=PA_HPUX; TARGETDIR=pa;;
|
||||
esac
|
||||
|
||||
AC_SUBST(AM_RUNTESTFLAGS)
|
||||
|
||||
if test $TARGETDIR = unknown; then
|
||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(MIPS_IRIX, test x$TARGET = xMIPS_IRIX)
|
||||
AM_CONDITIONAL(MIPS_LINUX, test x$TARGET = xMIPS_LINUX)
|
||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
||||
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
|
||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
||||
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
|
||||
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
|
||||
AM_CONDITIONAL(S390, test x$TARGET = xS390)
|
||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
||||
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
|
||||
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
|
||||
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
|
||||
|
||||
case x$TARGET in
|
||||
xMIPS*) TARGET=MIPS ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_FUNCS(memcpy)
|
||||
AC_FUNC_ALLOCA
|
||||
|
||||
AC_CHECK_SIZEOF(double)
|
||||
AC_CHECK_SIZEOF(long double)
|
||||
|
||||
# Also AC_SUBST this variable for ffi.h.
|
||||
HAVE_LONG_DOUBLE=0
|
||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
||||
if test $ac_cv_sizeof_long_double != 0; then
|
||||
HAVE_LONG_DOUBLE=1
|
||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
if test x$TARGET = xSPARC; then
|
||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
||||
libffi_cv_as_sparc_ua_pcrel, [
|
||||
save_CFLAGS="$CFLAGS"
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
CFLAGS="$CFLAGS -fpic"
|
||||
LDFLAGS="$LDFLAGS -shared"
|
||||
AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
|
||||
[libffi_cv_as_sparc_ua_pcrel=yes],
|
||||
[libffi_cv_as_sparc_ua_pcrel=no])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
LDFLAGS="$save_LDFLAGS"])
|
||||
if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
|
||||
[Define if your assembler and linker support unaligned PC relative relocs.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([assembler .register pseudo-op support],
|
||||
libffi_cv_as_register_pseudo_op, [
|
||||
libffi_cv_as_register_pseudo_op=unknown
|
||||
# Check if we have .register
|
||||
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
|
||||
[libffi_cv_as_register_pseudo_op=yes],
|
||||
[libffi_cv_as_register_pseudo_op=no])
|
||||
])
|
||||
if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
|
||||
[Define if your assembler supports .register.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
|
||||
libffi_cv_ro_eh_frame, [
|
||||
libffi_cv_ro_eh_frame=no
|
||||
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
|
||||
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
|
||||
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
|
||||
libffi_cv_ro_eh_frame=yes
|
||||
elif grep '.section.*eh_frame.*#alloc' conftest.c \
|
||||
| grep -v '#write' > /dev/null; then
|
||||
libffi_cv_ro_eh_frame=yes
|
||||
fi
|
||||
fi
|
||||
rm -f conftest.*
|
||||
])
|
||||
if test "x$libffi_cv_ro_eh_frame" = xyes; then
|
||||
AC_DEFINE(HAVE_RO_EH_FRAME, 1,
|
||||
[Define if .eh_frame sections should be read-only.])
|
||||
AC_DEFINE(EH_FRAME_FLAGS, "a",
|
||||
[Define to the flags needed for the .section .eh_frame directive.])
|
||||
else
|
||||
AC_DEFINE(EH_FRAME_FLAGS, "aw",
|
||||
[Define to the flags needed for the .section .eh_frame directive.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
|
||||
libffi_cv_hidden_visibility_attribute, [
|
||||
echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1; }' > conftest.c
|
||||
libffi_cv_hidden_visibility_attribute=no
|
||||
if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
||||
if grep '\.hidden.*foo' conftest.s >/dev/null; then
|
||||
libffi_cv_hidden_visibility_attribute=yes
|
||||
fi
|
||||
fi
|
||||
rm -f conftest.*
|
||||
])
|
||||
if test $libffi_cv_hidden_visibility_attribute = yes; then
|
||||
AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
|
||||
[Define if __attribute__((visibility("hidden"))) is supported.])
|
||||
fi
|
||||
|
||||
AH_BOTTOM([
|
||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
#ifdef LIBFFI_ASM
|
||||
#define FFI_HIDDEN(name) .hidden name
|
||||
#else
|
||||
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
#else
|
||||
#ifdef LIBFFI_ASM
|
||||
#define FFI_HIDDEN(name)
|
||||
#else
|
||||
#define FFI_HIDDEN
|
||||
#endif
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_SUBST(TARGET)
|
||||
AC_SUBST(TARGETDIR)
|
||||
|
||||
AC_SUBST(SHELL)
|
||||
|
||||
AC_ARG_ENABLE(debug,
|
||||
[ --enable-debug debugging mode],
|
||||
if test "$enable_debug" = "yes"; then
|
||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(structs,
|
||||
[ --disable-structs omit code for struct support],
|
||||
if test "$enable_structs" = "no"; then
|
||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(raw-api,
|
||||
[ --disable-raw-api make the raw api unavailable],
|
||||
if test "$enable_raw_api" = "no"; then
|
||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(purify-safety,
|
||||
[ --enable-purify-safety purify-safe mode],
|
||||
if test "$enable_purify_safety" = "yes"; then
|
||||
AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
|
||||
fi)
|
||||
|
||||
if test -n "$with_cross_host" &&
|
||||
test x"$with_cross_host" != x"no"; then
|
||||
toolexecdir='$(exec_prefix)/$(target_alias)'
|
||||
toolexeclibdir='$(toolexecdir)/lib'
|
||||
else
|
||||
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
|
||||
toolexeclibdir='$(libdir)'
|
||||
fi
|
||||
multi_os_directory=`$CC -print-multi-os-directory`
|
||||
case $multi_os_directory in
|
||||
.) ;; # Avoid trailing /.
|
||||
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
|
||||
esac
|
||||
AC_SUBST(toolexecdir)
|
||||
AC_SUBST(toolexeclibdir)
|
||||
|
||||
if test "${multilib}" = "yes"; then
|
||||
multilib_arg="--enable-multilib"
|
||||
else
|
||||
multilib_arg=
|
||||
fi
|
||||
|
||||
AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
|
||||
AC_CONFIG_COMMANDS(src, [
|
||||
test -d src || mkdir src
|
||||
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
||||
], [TARGETDIR="$TARGETDIR"])
|
||||
|
||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
||||
|
||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile)
|
||||
|
||||
AC_OUTPUT
|
||||
11
libffi/configure.host
Normal file
11
libffi/configure.host
Normal file
@@ -0,0 +1,11 @@
|
||||
# configure.host
|
||||
#
|
||||
# This shell script handles all host based configuration for libffi.
|
||||
#
|
||||
|
||||
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
|
||||
case "${host}" in
|
||||
frv*-elf)
|
||||
LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
|
||||
;;
|
||||
esac
|
||||
@@ -1,168 +0,0 @@
|
||||
dnl Process this with autoconf to create configure
|
||||
AC_INIT(fficonfig.h.in)
|
||||
AM_CONFIG_HEADER(fficonfig.h)
|
||||
|
||||
dnl Default to --enable-multilib
|
||||
AC_ARG_ENABLE(multilib,
|
||||
[ --enable-multilib build many library versions (default)],
|
||||
[case "${enableval}" in
|
||||
yes) multilib=yes ;;
|
||||
no) multilib=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
|
||||
esac], [multilib=yes])dnl
|
||||
|
||||
dnl We may get other options which we don't document:
|
||||
dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
|
||||
|
||||
if test "${srcdir}" = "."; then
|
||||
if test "${with_target_subdir}" != "."; then
|
||||
libffi_basedir="${srcdir}/${with_multisrctop}.."
|
||||
else
|
||||
libffi_basedir="${srcdir}/${with_multisrctop}"
|
||||
fi
|
||||
else
|
||||
libffi_basedir="${srcdir}"
|
||||
fi
|
||||
AC_SUBST(libffi_basedir)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AM_INIT_AUTOMAKE(libffi,2.00,no-define)
|
||||
|
||||
AC_EXEEXT
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
AM_PROG_LIBTOOL
|
||||
AC_PROG_LN_S
|
||||
|
||||
dnl The -no-testsuite modules omit the test subdir.
|
||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
||||
|
||||
AM_RUNTESTFLAGS=
|
||||
|
||||
TARGET="unknown"
|
||||
case "$host" in
|
||||
alpha*-*-linux* | alpha*-*-osf*)
|
||||
TARGET=ALPHA;
|
||||
$LN_S ${srcdir}/alpha/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/alpha/osf.S t-asm.S;;
|
||||
arm*-*-linux-*)
|
||||
TARGET=ARM;
|
||||
$LN_S $srcdir/arm/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/arm/ffi.S t-asm.S;;
|
||||
i*86-*-beos*|i*86-*-freebsd*|i*86-*-linux*|i*86-*-solaris*)
|
||||
TARGET=X86;
|
||||
$LN_S $srcdir/x86/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/x86/sysv.S t-asm.S;;
|
||||
i*86-*-cygwin*|i*86-*-mingw*|i*86-*-win32*)
|
||||
TARGET=X86_WIN32;
|
||||
$LN_S $srcdir/x86/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/x86/win32.S t-asm.S;;
|
||||
ia64*-*-*)
|
||||
TARGET=IA64;
|
||||
$LN_S $srcdir/ia64/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/ia64/unix.S t-asm.S;;
|
||||
m68k-*-linux*)
|
||||
TARGET=M68K;
|
||||
$LN_S $srcdir/m68k/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/m68k/unix.S t-asm.S;;
|
||||
mips-*-elf)
|
||||
TARGET=MIPS;
|
||||
$LN_S $srcdir/mips/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/mips/o32.S t-asm.S;;
|
||||
mips-sgi-irix5.*)
|
||||
TARGET=MIPS;
|
||||
$LN_S $srcdir/mips/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/mips/o32.S t-asm.S;;
|
||||
mips-sgi-irix6.*)
|
||||
TARGET=MIPS;
|
||||
$LN_S $srcdir/mips/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/mips/n32.S t-asm.S;;
|
||||
powerpc-*-linux* | powerpc-*-sysv* | powerpc-*-beos*)
|
||||
TARGET=POWERPC;
|
||||
$LN_S $srcdir/powerpc/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/powerpc/sysv.S t-asm.S;;
|
||||
s390-*-linux*)
|
||||
TARGET=S390;
|
||||
$LN_S $srcdir/s390/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/s390/v8.S t-asm.S;;
|
||||
sparc-*-linux*|sparc-sun-*)
|
||||
TARGET=SPARC;
|
||||
$LN_S $srcdir/sparc/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/sparc/v8.S t-asm.S;;
|
||||
sparc64-*-linux*)
|
||||
TARGET=SPARC;
|
||||
$LN_S $srcdir/sparc/ffi.c t-ffi.c;
|
||||
$LN_S $srcdir/sparc/v9.S t-asm.S;;
|
||||
esac
|
||||
|
||||
AC_SUBST(AM_RUNTESTFLAGS)
|
||||
|
||||
if test ${TARGET} = unknown; then
|
||||
AC_ERROR("libffi has not been ported to $host.")
|
||||
fi
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_FUNCS(memcpy)
|
||||
AC_FUNC_ALLOCA
|
||||
|
||||
dnl AC_CHECK_SIZEOF(char)
|
||||
AC_COMPILE_CHECK_SIZEOF(short)
|
||||
AC_COMPILE_CHECK_SIZEOF(int)
|
||||
AC_COMPILE_CHECK_SIZEOF(long)
|
||||
AC_COMPILE_CHECK_SIZEOF(long long)
|
||||
AC_COMPILE_CHECK_SIZEOF(float)
|
||||
AC_COMPILE_CHECK_SIZEOF(double)
|
||||
AC_COMPILE_CHECK_SIZEOF(long double)
|
||||
|
||||
AC_COMPILE_CHECK_SIZEOF(void *)
|
||||
AC_C_BIGENDIAN_CROSS
|
||||
|
||||
AC_SUBST(TARGET)
|
||||
AC_SUBST(TARGETDIR)
|
||||
|
||||
AC_SUBST(SHELL)
|
||||
|
||||
AC_ARG_ENABLE(debug,[ --enable-debug debugging mode], AC_DEFINE(FFI_DEBUG))
|
||||
|
||||
AC_ARG_ENABLE(debug,[ --disable-structs omit code for struct support], AC_DEFINE(FFI_NO_STRUCTS))
|
||||
|
||||
AC_ARG_ENABLE(debug,[ --disable-raw-api make the raw api unavailable], AC_DEFINE(FFI_NO_RAW_API))
|
||||
|
||||
AC_ARG_ENABLE(purify-safety,
|
||||
[ --enable-purify-safety purify-safe mode], AC_DEFINE(USING_PURIFY))
|
||||
|
||||
AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
|
||||
|
||||
if test "${multilib}" = "yes"; then
|
||||
multilib_arg="--enable-multilib"
|
||||
else
|
||||
multilib_arg=
|
||||
fi
|
||||
|
||||
AC_OUTPUT(include/Makefile testsuite/Makefile Makefile,
|
||||
[
|
||||
if test -n "$CONFIG_FILES"; then
|
||||
ac_file=Makefile . ${libffi_basedir}/config-ml.in
|
||||
fi
|
||||
],
|
||||
srcdir=${srcdir}
|
||||
host=${host}
|
||||
target=${target}
|
||||
with_multisubdir=${with_multisubdir}
|
||||
ac_configure_args="${multilib_arg} ${ac_configure_args}"
|
||||
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
libffi_basedir=${libffi_basedir}
|
||||
CC="${CC}"
|
||||
DEFS="$DEFS"
|
||||
test ! -d include && mkdir include
|
||||
test ! -f include/fficonfig.h && cp fficonfig.h include/fficonfig.h
|
||||
if cmp -s fficonfig.h include/fficonfig.h 2>/dev/null; then
|
||||
echo fficonfig.h unchanged
|
||||
else
|
||||
echo Moving fficonfig.h to include/fficonfig.h
|
||||
cp fficonfig.h include/fficonfig.h
|
||||
fi
|
||||
)
|
||||
530
libffi/depcomp
Executable file
530
libffi/depcomp
Executable file
@@ -0,0 +1,530 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2005-07-09.11
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by `PROGRAMS ARGS'.
|
||||
object Object file output by `PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputing dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the `deleted header file' problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the `:'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like `#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr '
|
||||
' ' ' >> $depfile
|
||||
echo >> $depfile
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> $depfile
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
|
||||
tmpdepfile="$stripped.u"
|
||||
if test "$libtool" = yes; then
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test -f "$tmpdepfile"; then :
|
||||
else
|
||||
stripped=`echo "$stripped" | sed 's,^.*/,,'`
|
||||
tmpdepfile="$stripped.u"
|
||||
fi
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
if test -f "$tmpdepfile"; then
|
||||
outname="$stripped.o"
|
||||
# Each line is of the form `foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler understands `-MD -MF file'. However on
|
||||
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want:
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using \ :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
|
||||
sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in `foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mecanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for `:'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no
|
||||
for arg in "$@"; do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix="`echo $object | sed 's/^.*\././'`"
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' '
|
||||
' | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o,
|
||||
# because we must use -o when running libtool.
|
||||
"$@" || exit $?
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
|
||||
echo " " >> "$depfile"
|
||||
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
@@ -1,73 +1,157 @@
|
||||
/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */
|
||||
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if using alloca.c. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
|
||||
This function is required for alloca.c support on those systems. */
|
||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||
systems. This function is required for `alloca.c' support on those systems.
|
||||
*/
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define if you have alloca, as a function or macro. */
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
/* Define to the flags needed for the .section .eh_frame directive. */
|
||||
#undef EH_FRAME_FLAGS
|
||||
|
||||
/* Define this if you want extra debugging. */
|
||||
#undef FFI_DEBUG
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
#undef FFI_NO_RAW_API
|
||||
|
||||
/* Define this is you do not want support for aggregate types. */
|
||||
#undef FFI_NO_STRUCTS
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
|
||||
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||
*/
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
/* Define if your assembler supports .register. */
|
||||
#undef HAVE_AS_REGISTER_PSEUDO_OP
|
||||
|
||||
/* Define if your assembler and linker support unaligned PC relative relocs.
|
||||
*/
|
||||
#undef HAVE_AS_SPARC_UA_PCREL
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define if __attribute__((visibility("hidden"))) is supported. */
|
||||
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define if you have the long double type and it is bigger than a double */
|
||||
#undef HAVE_LONG_DOUBLE
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define if mmap with MAP_ANON(YMOUS) works. */
|
||||
#undef HAVE_MMAP_ANON
|
||||
|
||||
/* Define if mmap of /dev/zero works. */
|
||||
#undef HAVE_MMAP_DEV_ZERO
|
||||
|
||||
/* Define if read-only mmap of a plain file works. */
|
||||
#undef HAVE_MMAP_FILE
|
||||
|
||||
/* Define if .eh_frame sections should be read-only. */
|
||||
#undef HAVE_RO_EH_FRAME
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* The size of a `double', as computed by sizeof. */
|
||||
#undef SIZEOF_DOUBLE
|
||||
|
||||
/* The size of a `long double', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG_DOUBLE
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at run-time.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown
|
||||
*/
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
#undef STACK_DIRECTION
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define this if you want extra debugging */
|
||||
#undef FFI_DEBUG
|
||||
|
||||
/* Define this if you are using Purify and want to suppress
|
||||
spurious messages. */
|
||||
/* Define this if you are using Purify and want to suppress spurious messages.
|
||||
*/
|
||||
#undef USING_PURIFY
|
||||
|
||||
/* Define this is you do not want support for aggregate types. */
|
||||
#undef FFI_NO_STRUCTS
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
#undef FFI_NO_RAW_API
|
||||
|
||||
/* Define if you have the memcpy function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
/* The number of bytes in type short */
|
||||
#undef SIZEOF_SHORT
|
||||
|
||||
/* The number of bytes in type int */
|
||||
#undef SIZEOF_INT
|
||||
|
||||
/* The number of bytes in type long */
|
||||
#undef SIZEOF_LONG
|
||||
|
||||
/* The number of bytes in type long long */
|
||||
#undef SIZEOF_LONG_LONG
|
||||
|
||||
/* The number of bytes in type float */
|
||||
#undef SIZEOF_FLOAT
|
||||
|
||||
/* The number of bytes in type double */
|
||||
#undef SIZEOF_DOUBLE
|
||||
|
||||
/* The number of bytes in type long double */
|
||||
#undef SIZEOF_LONG_DOUBLE
|
||||
|
||||
/* The number of bytes in type void * */
|
||||
#undef SIZEOF_VOID_P
|
||||
|
||||
/* whether byteorder is bigendian */
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
|
||||
#undef BYTEORDER
|
||||
|
||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
#ifdef LIBFFI_ASM
|
||||
#define FFI_HIDDEN(name) .hidden name
|
||||
#else
|
||||
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
#else
|
||||
#ifdef LIBFFI_ASM
|
||||
#define FFI_HIDDEN(name)
|
||||
#else
|
||||
#define FFI_HIDDEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
736
libffi/ffitest.c
736
libffi/ffitest.c
@@ -1,736 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
|
||||
|
||||
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 RED HAT 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
/* This is lame. Long double support is barely there under SunOS 4.x */
|
||||
#if defined(__sparc__) && (SIZEOF_LONG_DOUBLE != 16)
|
||||
#define BROKEN_LONG_DOUBLE
|
||||
#endif
|
||||
|
||||
#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
|
||||
|
||||
static int fail(char *file, int line)
|
||||
{
|
||||
fprintf(stderr, "Test failure: %s line %d\n", file, line);
|
||||
exit(EXIT_FAILURE);
|
||||
/*@notreached@*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_ARGS 256
|
||||
|
||||
static size_t my_strlen(char *s)
|
||||
{
|
||||
return (strlen(s));
|
||||
}
|
||||
|
||||
static int promotion(signed char sc, signed short ss,
|
||||
unsigned char uc, unsigned short us)
|
||||
{
|
||||
int r = (int) sc + (int) ss + (int) uc + (int) us;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static signed char return_sc(signed char sc)
|
||||
{
|
||||
return sc;
|
||||
}
|
||||
|
||||
static unsigned char return_uc(unsigned char uc)
|
||||
{
|
||||
return uc;
|
||||
}
|
||||
|
||||
static long long return_ll(long long ll)
|
||||
{
|
||||
return ll;
|
||||
}
|
||||
|
||||
static int floating(int a, float b, double c, long double d, int e)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
/* This is ifdef'd out for now. long double support under SunOS/gcc
|
||||
is pretty much non-existent. You'll get the odd bus error in library
|
||||
routines like printf(). */
|
||||
printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
|
||||
#endif
|
||||
|
||||
i = (int) ((float)a/b + ((float)c/(float)d));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static float many(float f1,
|
||||
float f2,
|
||||
float f3,
|
||||
float f4,
|
||||
float f5,
|
||||
float f6,
|
||||
float f7,
|
||||
float f8,
|
||||
float f9,
|
||||
float f10,
|
||||
float f11,
|
||||
float f12,
|
||||
float f13)
|
||||
{
|
||||
#if 0
|
||||
printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
|
||||
(double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
|
||||
(double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
|
||||
(double) f11, (double) f12, (double) f13);
|
||||
#endif
|
||||
|
||||
return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
|
||||
}
|
||||
|
||||
static double dblit(float f)
|
||||
{
|
||||
return f/3.0;
|
||||
}
|
||||
|
||||
static long double ldblit(float f)
|
||||
{
|
||||
return (long double) (((long double) f)/ (long double) 3.0);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char uc;
|
||||
double d;
|
||||
unsigned int ui;
|
||||
} test_structure_1;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double d1;
|
||||
double d2;
|
||||
} test_structure_2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int si;
|
||||
} test_structure_3;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned ui1;
|
||||
unsigned ui2;
|
||||
unsigned ui3;
|
||||
} test_structure_4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char c1;
|
||||
char c2;
|
||||
} test_structure_5;
|
||||
|
||||
static test_structure_1 struct1(test_structure_1 ts)
|
||||
{
|
||||
/*@-type@*/
|
||||
ts.uc++;
|
||||
/*@=type@*/
|
||||
ts.d--;
|
||||
ts.ui++;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_2 struct2(test_structure_2 ts)
|
||||
{
|
||||
ts.d1--;
|
||||
ts.d2--;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_3 struct3(test_structure_3 ts)
|
||||
{
|
||||
ts.si = -(ts.si*2);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_4 struct4(test_structure_4 ts)
|
||||
{
|
||||
ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
|
||||
{
|
||||
ts1.c1 += ts2.c1;
|
||||
ts1.c2 -= ts2.c2;
|
||||
|
||||
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;
|
||||
ffi_type *args[MAX_ARGS];
|
||||
void *values[MAX_ARGS];
|
||||
char *s;
|
||||
signed char sc;
|
||||
unsigned char uc;
|
||||
signed short ss;
|
||||
unsigned short us;
|
||||
unsigned long ul;
|
||||
long long ll;
|
||||
float f;
|
||||
double d;
|
||||
long double ld;
|
||||
signed int si1;
|
||||
signed int si2;
|
||||
|
||||
#if defined(__alpha__) || defined(IA64) || defined(SPARC64) || (defined(__mips__) && (_MIPS_SIM == _ABIN32))
|
||||
long long rint;
|
||||
#else
|
||||
int rint;
|
||||
#endif
|
||||
long long rlonglong;
|
||||
|
||||
ffi_type ts1_type;
|
||||
ffi_type ts2_type;
|
||||
ffi_type ts3_type;
|
||||
ffi_type ts4_type;
|
||||
ffi_type ts5_type;
|
||||
ffi_type *ts1_type_elements[4];
|
||||
ffi_type *ts2_type_elements[3];
|
||||
ffi_type *ts3_type_elements[2];
|
||||
ffi_type *ts4_type_elements[4];
|
||||
ffi_type *ts5_type_elements[3];
|
||||
|
||||
ts1_type.size = 0;
|
||||
ts1_type.alignment = 0;
|
||||
ts1_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts2_type.size = 0;
|
||||
ts2_type.alignment = 0;
|
||||
ts2_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts3_type.size = 0;
|
||||
ts3_type.alignment = 0;
|
||||
ts3_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts4_type.size = 0;
|
||||
ts4_type.alignment = 0;
|
||||
ts4_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
ts5_type.size = 0;
|
||||
ts5_type.alignment = 0;
|
||||
ts5_type.type = FFI_TYPE_STRUCT;
|
||||
|
||||
/*@-immediatetrans@*/
|
||||
ts1_type.elements = ts1_type_elements;
|
||||
ts2_type.elements = ts2_type_elements;
|
||||
ts3_type.elements = ts3_type_elements;
|
||||
ts4_type.elements = ts4_type_elements;
|
||||
ts5_type.elements = ts5_type_elements;
|
||||
/*@=immediatetrans@*/
|
||||
|
||||
ts1_type_elements[0] = &ffi_type_uchar;
|
||||
ts1_type_elements[1] = &ffi_type_double;
|
||||
ts1_type_elements[2] = &ffi_type_uint;
|
||||
ts1_type_elements[3] = NULL;
|
||||
|
||||
ts2_type_elements[0] = &ffi_type_double;
|
||||
ts2_type_elements[1] = &ffi_type_double;
|
||||
ts2_type_elements[2] = NULL;
|
||||
|
||||
ts3_type_elements[0] = &ffi_type_sint;
|
||||
ts3_type_elements[1] = NULL;
|
||||
|
||||
ts4_type_elements[0] = &ffi_type_uint;
|
||||
ts4_type_elements[1] = &ffi_type_uint;
|
||||
ts4_type_elements[2] = &ffi_type_uint;
|
||||
ts4_type_elements[3] = NULL;
|
||||
|
||||
ts5_type_elements[0] = &ffi_type_schar;
|
||||
ts5_type_elements[1] = &ffi_type_schar;
|
||||
ts5_type_elements[2] = NULL;
|
||||
|
||||
ul = 0;
|
||||
|
||||
/* return value tests */
|
||||
{
|
||||
#if defined(__mips__) /* || defined(ARM) */
|
||||
puts ("long long tests not run. This is a known bug on this architecture.");
|
||||
#else
|
||||
args[0] = &ffi_type_sint64;
|
||||
values[0] = ≪
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_sint64, args) == FFI_OK);
|
||||
|
||||
for (ll = 0LL; ll < 100LL; ll++)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
|
||||
CHECK(rlonglong == ll);
|
||||
}
|
||||
|
||||
for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
|
||||
CHECK(rlonglong == ll);
|
||||
}
|
||||
#endif
|
||||
|
||||
args[0] = &ffi_type_schar;
|
||||
values[0] = ≻
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_schar, args) == FFI_OK);
|
||||
|
||||
for (sc = (signed char) -127;
|
||||
sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_sc), &rint, values);
|
||||
CHECK(rint == (int) sc);
|
||||
}
|
||||
|
||||
args[0] = &ffi_type_uchar;
|
||||
values[0] = &uc;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uchar, args) == FFI_OK);
|
||||
|
||||
for (uc = (unsigned char) '\x00';
|
||||
uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(return_uc), &rint, values);
|
||||
CHECK(rint == (signed int) uc);
|
||||
}
|
||||
|
||||
printf("%lu return value tests run\n", ul);
|
||||
}
|
||||
|
||||
#ifdef BROKEN_LONG_DOUBLE
|
||||
printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
|
||||
#else
|
||||
/* float arg tests */
|
||||
{
|
||||
args[0] = &ffi_type_float;
|
||||
values[0] = &f;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_longdouble, args) == FFI_OK);
|
||||
|
||||
f = 3.14159;
|
||||
|
||||
#if 0
|
||||
/* This is ifdef'd out for now. long double support under SunOS/gcc
|
||||
is pretty much non-existent. You'll get the odd bus error in library
|
||||
routines like printf(). */
|
||||
printf ("%Lf\n", ldblit(f));
|
||||
#endif
|
||||
ld = 666;
|
||||
ffi_call(&cif, FFI_FN(ldblit), &ld, values);
|
||||
|
||||
#if 0
|
||||
/* This is ifdef'd out for now. long double support under SunOS/gcc
|
||||
is pretty much non-existent. You'll get the odd bus error in library
|
||||
routines like printf(). */
|
||||
printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
|
||||
#endif
|
||||
|
||||
/* These are not always the same!! Check for a reasonable delta */
|
||||
/*@-realcompare@*/
|
||||
if (ld - ldblit(f) < LDBL_EPSILON)
|
||||
/*@=realcompare@*/
|
||||
puts("long double return value tests ok!");
|
||||
else
|
||||
CHECK(0);
|
||||
}
|
||||
|
||||
/* float arg tests */
|
||||
{
|
||||
args[0] = &ffi_type_sint;
|
||||
values[0] = &si1;
|
||||
args[1] = &ffi_type_float;
|
||||
values[1] = &f;
|
||||
args[2] = &ffi_type_double;
|
||||
values[2] = &d;
|
||||
args[3] = &ffi_type_longdouble;
|
||||
values[3] = &ld;
|
||||
args[4] = &ffi_type_sint;
|
||||
values[4] = &si2;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
si1 = 6;
|
||||
f = 3.14159;
|
||||
d = (double)1.0/(double)3.0;
|
||||
ld = 2.71828182846L;
|
||||
si2 = 10;
|
||||
|
||||
floating (si1, f, d, ld, si2);
|
||||
|
||||
ffi_call(&cif, FFI_FN(floating), &rint, values);
|
||||
|
||||
printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
|
||||
|
||||
CHECK(rint == floating(si1, f, d, ld, si2));
|
||||
|
||||
printf("float arg tests ok!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* strlen tests */
|
||||
{
|
||||
args[0] = &ffi_type_pointer;
|
||||
values[0] = (void*) &s;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
s = "a";
|
||||
ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
||||
CHECK(rint == 1);
|
||||
|
||||
s = "1234567";
|
||||
ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
||||
CHECK(rint == 7);
|
||||
|
||||
s = "1234567890123456789012345";
|
||||
ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
||||
CHECK(rint == 25);
|
||||
|
||||
printf("strlen tests passed\n");
|
||||
}
|
||||
|
||||
/* float arg tests */
|
||||
{
|
||||
args[0] = &ffi_type_float;
|
||||
values[0] = &f;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_double, args) == FFI_OK);
|
||||
|
||||
f = 3.14159;
|
||||
|
||||
ffi_call(&cif, FFI_FN(dblit), &d, values);
|
||||
|
||||
/* These are not always the same!! Check for a reasonable delta */
|
||||
/*@-realcompare@*/
|
||||
CHECK(d - dblit(f) < DBL_EPSILON);
|
||||
/*@=realcompare@*/
|
||||
|
||||
printf("double return value tests ok!\n");
|
||||
}
|
||||
|
||||
/* many arg tests */
|
||||
{
|
||||
float ff;
|
||||
float fa[13];
|
||||
|
||||
for (ul = 0; ul < 13; ul++)
|
||||
{
|
||||
args[ul] = &ffi_type_float;
|
||||
values[ul] = &fa[ul];
|
||||
fa[ul] = (float) ul;
|
||||
}
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
|
||||
&ffi_type_float, args) == FFI_OK);
|
||||
|
||||
/*@-usedef@*/
|
||||
ff = many(fa[0], fa[1],
|
||||
fa[2], fa[3],
|
||||
fa[4], fa[5],
|
||||
fa[6], fa[7],
|
||||
fa[8], fa[9],
|
||||
fa[10],fa[11],fa[12]);
|
||||
/*@=usedef@*/
|
||||
|
||||
ffi_call(&cif, FFI_FN(many), &f, values);
|
||||
|
||||
/*@-realcompare@*/
|
||||
if (f - ff < FLT_EPSILON)
|
||||
/*@=realcompare@*/
|
||||
printf("many arg tests ok!\n");
|
||||
else
|
||||
#ifdef POWERPC
|
||||
printf("many arg tests failed! This is a gcc bug.\n");
|
||||
#else
|
||||
CHECK(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* promotion tests */
|
||||
{
|
||||
args[0] = &ffi_type_schar;
|
||||
args[1] = &ffi_type_sshort;
|
||||
args[2] = &ffi_type_uchar;
|
||||
args[3] = &ffi_type_ushort;
|
||||
values[0] = ≻
|
||||
values[1] = &ss;
|
||||
values[2] = &uc;
|
||||
values[3] = &us;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
us = 0;
|
||||
ul = 0;
|
||||
|
||||
for (sc = (signed char) -127;
|
||||
sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
|
||||
for (ss = -30000; ss <= 30000; ss += 10000)
|
||||
for (uc = (unsigned char) 0;
|
||||
uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
|
||||
for (us = 0; us <= 60000; us += 10000)
|
||||
{
|
||||
ul++;
|
||||
ffi_call(&cif, FFI_FN(promotion), &rint, values);
|
||||
CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
|
||||
}
|
||||
printf("%lu promotion tests run\n", ul);
|
||||
}
|
||||
|
||||
#ifndef X86_WIN32 /* Structures dont work on Win32 */
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_1 ts1_arg;
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_1 *ts1_result =
|
||||
(test_structure_1 *) malloc (sizeof(test_structure_1));
|
||||
|
||||
args[0] = &ts1_type;
|
||||
values[0] = &ts1_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ts1_type, args) == FFI_OK);
|
||||
|
||||
ts1_arg.uc = '\x01';
|
||||
ts1_arg.d = 3.14159;
|
||||
ts1_arg.ui = 555;
|
||||
|
||||
ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
|
||||
|
||||
CHECK(ts1_result->ui == 556);
|
||||
CHECK(ts1_result->d == 3.14159 - 1);
|
||||
|
||||
puts ("structure test 1 ok!\n");
|
||||
|
||||
free (ts1_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_2 ts2_arg;
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_2 *ts2_result =
|
||||
(test_structure_2 *) malloc (sizeof(test_structure_2));
|
||||
|
||||
args[0] = &ts2_type;
|
||||
values[0] = &ts2_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ts2_type, args) == FFI_OK);
|
||||
|
||||
ts2_arg.d1 = 5.55;
|
||||
ts2_arg.d2 = 6.66;
|
||||
|
||||
printf ("%g\n", ts2_result->d1);
|
||||
printf ("%g\n", ts2_result->d2);
|
||||
|
||||
ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
|
||||
|
||||
printf ("%g\n", ts2_result->d1);
|
||||
printf ("%g\n", ts2_result->d2);
|
||||
|
||||
CHECK(ts2_result->d1 == 5.55 - 1);
|
||||
CHECK(ts2_result->d2 == 6.66 - 1);
|
||||
|
||||
printf("structure test 2 ok!\n");
|
||||
|
||||
free (ts2_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
int compare_value;
|
||||
test_structure_3 ts3_arg;
|
||||
test_structure_3 *ts3_result =
|
||||
(test_structure_3 *) malloc (sizeof(test_structure_3));
|
||||
|
||||
args[0] = &ts3_type;
|
||||
values[0] = &ts3_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ts3_type, args) == FFI_OK);
|
||||
|
||||
ts3_arg.si = -123;
|
||||
compare_value = ts3_arg.si;
|
||||
|
||||
ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
|
||||
|
||||
printf ("%d %d\n", ts3_result->si, -(compare_value*2));
|
||||
|
||||
if (ts3_result->si == -(ts3_arg.si*2))
|
||||
puts ("structure test 3 ok!");
|
||||
else
|
||||
{
|
||||
puts ("Structure test 3 found structure passing bug.");
|
||||
puts (" Current versions of GCC are not 100% compliant with the");
|
||||
puts (" n32 ABI. There is a known problem related to passing");
|
||||
puts (" small structures. Send a bug report to the gcc maintainers.");
|
||||
}
|
||||
|
||||
free (ts3_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_4 ts4_arg;
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_4 *ts4_result =
|
||||
(test_structure_4 *) malloc (sizeof(test_structure_4));
|
||||
|
||||
args[0] = &ts4_type;
|
||||
values[0] = &ts4_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ts4_type, args) == FFI_OK);
|
||||
|
||||
ts4_arg.ui1 = 2;
|
||||
ts4_arg.ui2 = 3;
|
||||
ts4_arg.ui3 = 4;
|
||||
|
||||
ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
|
||||
|
||||
if (ts4_result->ui3 == 2U * 3U * 4U)
|
||||
puts ("structure test 4 ok!");
|
||||
else
|
||||
puts ("Structure test 4 found GCC's structure passing bug.");
|
||||
|
||||
free (ts4_result);
|
||||
}
|
||||
|
||||
/* struct tests */
|
||||
{
|
||||
test_structure_5 ts5_arg1, ts5_arg2;
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_5 *ts5_result =
|
||||
(test_structure_5 *) malloc (sizeof(test_structure_5));
|
||||
|
||||
args[0] = &ts5_type;
|
||||
args[1] = &ts5_type;
|
||||
values[0] = &ts5_arg1;
|
||||
values[1] = &ts5_arg2;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
||||
&ts5_type, args) == FFI_OK);
|
||||
|
||||
ts5_arg1.c1 = 2;
|
||||
ts5_arg1.c2 = 6;
|
||||
ts5_arg2.c1 = 5;
|
||||
ts5_arg2.c2 = 3;
|
||||
|
||||
ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
|
||||
|
||||
if (ts5_result->c1 == 7
|
||||
&& ts5_result->c2 == 3)
|
||||
puts ("structure test 5 ok!");
|
||||
else
|
||||
puts ("Structure test 5 found GCC's structure passing bug.");
|
||||
|
||||
free (ts5_result);
|
||||
}
|
||||
|
||||
#else
|
||||
printf("Structure passing doesn't work on Win32.\n");
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
# 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");
|
||||
|
||||
/*@-compdestroy@*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,670 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
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_private.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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
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)
|
||||
@@ -1,301 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
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
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
## Process this with automake to create Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
|
||||
noinst_HEADERS=ffi_private.h
|
||||
include_HEADERS=ffi.h
|
||||
DISTCLEANFILES=ffitarget.h
|
||||
EXTRA_DIST=ffi.h.in ffi_common.h
|
||||
|
||||
## LIBFFI LOCAL: install in includedir.
|
||||
include_HEADERS = ffi.h ffitarget.h
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Makefile.in generated automatically by automake 1.4 from Makefile.am
|
||||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
@@ -10,229 +12,449 @@
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = include
|
||||
DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/ffi.h.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/fficonfig.h
|
||||
CONFIG_CLEAN_FILES = ffi.h ffitarget.h
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
am__installdirs = "$(DESTDIR)$(includedir)"
|
||||
includeHEADERS_INSTALL = $(INSTALL_HEADER)
|
||||
HEADERS = $(include_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ALLOCA = @ALLOCA@
|
||||
ALPHA_FALSE = @ALPHA_FALSE@
|
||||
ALPHA_TRUE = @ALPHA_TRUE@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
|
||||
AS = @AS@
|
||||
AR = @AR@
|
||||
ARM_FALSE = @ARM_FALSE@
|
||||
ARM_TRUE = @ARM_TRUE@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
CCAS = @CCAS@
|
||||
CCASFLAGS = @CCASFLAGS@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
LD = @LD@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
FRV_FALSE = @FRV_FALSE@
|
||||
FRV_TRUE = @FRV_TRUE@
|
||||
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
|
||||
IA64_FALSE = @IA64_FALSE@
|
||||
IA64_TRUE = @IA64_TRUE@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBFFI_CRIS_FALSE = @LIBFFI_CRIS_FALSE@
|
||||
LIBFFI_CRIS_TRUE = @LIBFFI_CRIS_TRUE@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
M32R_FALSE = @M32R_FALSE@
|
||||
M32R_TRUE = @M32R_TRUE@
|
||||
M68K_FALSE = @M68K_FALSE@
|
||||
M68K_TRUE = @M68K_TRUE@
|
||||
MAINT = @MAINT@
|
||||
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
NM = @NM@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
MIPS_IRIX_FALSE = @MIPS_IRIX_FALSE@
|
||||
MIPS_IRIX_TRUE = @MIPS_IRIX_TRUE@
|
||||
MIPS_LINUX_FALSE = @MIPS_LINUX_FALSE@
|
||||
MIPS_LINUX_TRUE = @MIPS_LINUX_TRUE@
|
||||
OBJEXT = @OBJEXT@
|
||||
PA64_HPUX_FALSE = @PA64_HPUX_FALSE@
|
||||
PA64_HPUX_TRUE = @PA64_HPUX_TRUE@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PA_HPUX_FALSE = @PA_HPUX_FALSE@
|
||||
PA_HPUX_TRUE = @PA_HPUX_TRUE@
|
||||
PA_LINUX_FALSE = @PA_LINUX_FALSE@
|
||||
PA_LINUX_TRUE = @PA_LINUX_TRUE@
|
||||
POWERPC_AIX_FALSE = @POWERPC_AIX_FALSE@
|
||||
POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@
|
||||
POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@
|
||||
POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@
|
||||
POWERPC_FALSE = @POWERPC_FALSE@
|
||||
POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@
|
||||
POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@
|
||||
POWERPC_TRUE = @POWERPC_TRUE@
|
||||
RANLIB = @RANLIB@
|
||||
S390_FALSE = @S390_FALSE@
|
||||
S390_TRUE = @S390_TRUE@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SH64_FALSE = @SH64_FALSE@
|
||||
SH64_TRUE = @SH64_TRUE@
|
||||
SHELL = @SHELL@
|
||||
SH_FALSE = @SH_FALSE@
|
||||
SH_TRUE = @SH_TRUE@
|
||||
SPARC_FALSE = @SPARC_FALSE@
|
||||
SPARC_TRUE = @SPARC_TRUE@
|
||||
STRIP = @STRIP@
|
||||
TARGET = @TARGET@
|
||||
TARGETDIR = @TARGETDIR@
|
||||
TESTSUBDIR_FALSE = @TESTSUBDIR_FALSE@
|
||||
TESTSUBDIR_TRUE = @TESTSUBDIR_TRUE@
|
||||
VERSION = @VERSION@
|
||||
libffi_basedir = @libffi_basedir@
|
||||
|
||||
X86_64_FALSE = @X86_64_FALSE@
|
||||
X86_64_TRUE = @X86_64_TRUE@
|
||||
X86_DARWIN_FALSE = @X86_DARWIN_FALSE@
|
||||
X86_DARWIN_TRUE = @X86_DARWIN_TRUE@
|
||||
X86_FALSE = @X86_FALSE@
|
||||
X86_TRUE = @X86_TRUE@
|
||||
X86_WIN32_FALSE = @X86_WIN32_FALSE@
|
||||
X86_WIN32_TRUE = @X86_WIN32_TRUE@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
toolexecdir = @toolexecdir@
|
||||
toolexeclibdir = @toolexeclibdir@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
DISTCLEANFILES = ffitarget.h
|
||||
EXTRA_DIST = ffi.h.in ffi_common.h
|
||||
include_HEADERS = ffi.h ffitarget.h
|
||||
all: all-am
|
||||
|
||||
noinst_HEADERS = ffi_private.h
|
||||
include_HEADERS = ffi.h
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../fficonfig.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
HEADERS = $(include_HEADERS) $(noinst_HEADERS)
|
||||
|
||||
DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign include/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
ffi.h: $(top_builddir)/config.status $(srcdir)/ffi.h.in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
install-includeHEADERS: $(include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(includedir)
|
||||
test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)"
|
||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
|
||||
echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \
|
||||
$(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
f=$(am__strip_dir) \
|
||||
echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
|
||||
$(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(include_HEADERS)'; for p in $$list; do \
|
||||
rm -f $(DESTDIR)$(includedir)/$$p; \
|
||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
||||
f=$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(includedir)/$$f"; \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = include
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
here=`cd $(top_builddir) && pwd`; \
|
||||
top_distdir=`cd $(top_distdir) && pwd`; \
|
||||
distdir=`cd $(distdir) && pwd`; \
|
||||
cd $(top_srcdir) \
|
||||
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign include/Makefile
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$/$$file $(distdir)/$$file; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-exec-am:
|
||||
all-am: Makefile $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(includedir)"; do \
|
||||
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am: install-includeHEADERS
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am: uninstall-includeHEADERS
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile $(HEADERS)
|
||||
all-redirect: all-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
$(mkinstalldirs) $(DESTDIR)$(includedir)
|
||||
|
||||
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-tags mostlyclean-generic
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-libtool \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-includeHEADERS
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-tags clean-generic mostlyclean-am
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
clean: clean-am
|
||||
pdf: pdf-am
|
||||
|
||||
distclean-am: distclean-tags distclean-generic clean-am
|
||||
-rm -f libtool
|
||||
pdf-am:
|
||||
|
||||
distclean: distclean-am
|
||||
ps: ps-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
|
||||
distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
ps-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: uninstall-includeHEADERS install-includeHEADERS tags \
|
||||
mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \
|
||||
distdir info-am info dvi-am dvi check check-am installcheck-am \
|
||||
installcheck install-exec-am install-exec install-data-am install-data \
|
||||
install-am install uninstall-am uninstall all-redirect all-am all \
|
||||
installdirs mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
uninstall-am: uninstall-includeHEADERS uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool ctags distclean distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-exec install-exec-am \
|
||||
install-includeHEADERS install-info install-info-am \
|
||||
install-man install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
|
||||
ps ps-am tags uninstall uninstall-am uninstall-includeHEADERS \
|
||||
uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi 2.0.0 - Copyright (C) 1996, 1997, 1998, 1999, 2000,
|
||||
2001 Red Hat, Inc.
|
||||
libffi @VERSION@ - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -16,10 +15,11 @@
|
||||
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 RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
@@ -48,120 +48,90 @@
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
|
||||
-------------------------------------------------------------------- */
|
||||
|
||||
#ifndef FFI_H
|
||||
#define FFI_H
|
||||
|
||||
#if !defined(__ASSEMBLER__) && !defined(__GNUC__)
|
||||
#error --- ffi.h requires GNU C ---
|
||||
#endif
|
||||
#ifndef LIBFFI_H
|
||||
#define LIBFFI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(LIBFFI_ASM)
|
||||
#include <stddef.h>
|
||||
#if defined(FFI_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#endif
|
||||
/* Specify which architecture libffi is configured for. */
|
||||
#define @TARGET@
|
||||
|
||||
/* ---- System configuration information --------------------------------- */
|
||||
|
||||
#include <ffitarget.h>
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef enum ffi_abi {
|
||||
|
||||
/* Leave this for debugging purposes */
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
/* ---- Sparc -------------------- */
|
||||
#ifdef __sparc__
|
||||
FFI_V8,
|
||||
FFI_V8PLUS,
|
||||
FFI_V9,
|
||||
#if defined(__arch64__) || defined(__sparcv9)
|
||||
FFI_DEFAULT_ABI = FFI_V9,
|
||||
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
|
||||
But we can find it either under the correct ANSI name, or under GNU
|
||||
C's internal name. */
|
||||
#ifdef LONG_LONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_V8,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ---- Intel x86 ---------------- */
|
||||
#ifdef __i386__
|
||||
FFI_SYSV,
|
||||
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,
|
||||
FFI_N32,
|
||||
FFI_N64,
|
||||
|
||||
# if defined(__mips_eabi)
|
||||
# define FFI_MIPS_EABI
|
||||
# define FFI_MIPS_O32
|
||||
# ifdef LLONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LLONG_MAX
|
||||
# else
|
||||
# if !defined(_MIPS_SIM)
|
||||
#error -- something is very wrong --
|
||||
# else
|
||||
# if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
|
||||
# define FFI_MIPS_N32
|
||||
# else
|
||||
# define FFI_MIPS_O32
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __GNUC__
|
||||
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# endif
|
||||
# if defined(FFI_MIPS_O32)
|
||||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
#endif
|
||||
|
||||
#if SCHAR_MAX == 127
|
||||
# define ffi_type_uchar ffi_type_uint8
|
||||
# define ffi_type_schar ffi_type_sint8
|
||||
#else
|
||||
#error "char size not supported"
|
||||
#endif
|
||||
|
||||
#if SHRT_MAX == 32767
|
||||
# define ffi_type_ushort ffi_type_uint16
|
||||
# define ffi_type_sshort ffi_type_sint16
|
||||
#elif SHRT_MAX == 2147483647
|
||||
# define ffi_type_ushort ffi_type_uint32
|
||||
# define ffi_type_sshort ffi_type_sint32
|
||||
#else
|
||||
#error "short size not supported"
|
||||
#endif
|
||||
|
||||
#if INT_MAX == 32767
|
||||
# define ffi_type_uint ffi_type_uint16
|
||||
# define ffi_type_sint ffi_type_sint16
|
||||
#elif INT_MAX == 2147483647
|
||||
# define ffi_type_uint ffi_type_uint32
|
||||
# define ffi_type_sint ffi_type_sint32
|
||||
#elif INT_MAX == 9223372036854775807
|
||||
# define ffi_type_uint ffi_type_uint64
|
||||
# define ffi_type_sint ffi_type_sint64
|
||||
#else
|
||||
#error "int size not supported"
|
||||
#endif
|
||||
|
||||
#if LONG_MAX == 2147483647
|
||||
# if FFI_LONG_LONG_MAX != 9223372036854775807
|
||||
#error "no 64-bit data type supported"
|
||||
# endif
|
||||
|
||||
#elif LONG_MAX != 9223372036854775807
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* ---- Alpha -------------------- */
|
||||
#ifdef __alpha__
|
||||
FFI_OSF,
|
||||
FFI_DEFAULT_ABI = FFI_OSF,
|
||||
#if LONG_MAX == 2147483647
|
||||
# define ffi_type_ulong ffi_type_uint32
|
||||
# define ffi_type_slong ffi_type_sint32
|
||||
#elif LONG_MAX == 9223372036854775807
|
||||
# define ffi_type_ulong ffi_type_uint64
|
||||
# define ffi_type_slong ffi_type_sint64
|
||||
#else
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* ---- Motorola m68k ------------ */
|
||||
#ifdef __m68k__
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
/* ---- PowerPC ------------------ */
|
||||
#ifdef __powerpc__
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
#endif
|
||||
|
||||
/* ---- ARM --------------------- */
|
||||
#ifdef __arm__
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
/* ---- S390 --------------------- */
|
||||
#ifdef __S390__
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
/* Leave this for debugging purposes */
|
||||
FFI_LAST_ABI
|
||||
|
||||
} ffi_abi;
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t */
|
||||
/* can hold a pointer. */
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
@@ -171,7 +141,7 @@ typedef struct _ffi_type
|
||||
struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
/* These are defined in ffi.c */
|
||||
/* These are defined in types.c */
|
||||
extern ffi_type ffi_type_void;
|
||||
extern ffi_type ffi_type_uint8;
|
||||
extern ffi_type ffi_type_sint8;
|
||||
@@ -186,16 +156,11 @@ extern ffi_type ffi_type_double;
|
||||
extern ffi_type ffi_type_longdouble;
|
||||
extern ffi_type ffi_type_pointer;
|
||||
|
||||
extern ffi_type ffi_type_ushort;
|
||||
extern ffi_type ffi_type_sint;
|
||||
extern ffi_type ffi_type_uint;
|
||||
extern ffi_type ffi_type_slong;
|
||||
extern ffi_type ffi_type_ulong;
|
||||
|
||||
typedef enum {
|
||||
FFI_OK = 0,
|
||||
FFI_BAD_TYPEDEF,
|
||||
FFI_BAD_ABI
|
||||
FFI_BAD_ABI
|
||||
} ffi_status;
|
||||
|
||||
typedef unsigned FFI_TYPE;
|
||||
@@ -207,115 +172,53 @@ typedef struct {
|
||||
ffi_type *rtype;
|
||||
unsigned bytes;
|
||||
unsigned flags;
|
||||
|
||||
#ifdef __mips__
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
unsigned rstruct_flag;
|
||||
#ifdef FFI_EXTRA_CIF_FIELDS
|
||||
FFI_EXTRA_CIF_FIELDS;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} ffi_cif;
|
||||
|
||||
/* ---- Definitions for the raw API -------------------------------------- */
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
#ifndef FFI_SIZEOF_ARG
|
||||
# if LONG_MAX == 2147483647
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
# elif LONG_MAX == 9223372036854775807
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
#if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
|
||||
long sint;
|
||||
unsigned long uint;
|
||||
#else
|
||||
int sint;
|
||||
unsigned uint;
|
||||
#endif
|
||||
float flt;
|
||||
char data[sizeof(void*)];
|
||||
void* ptr;
|
||||
ffi_sarg sint;
|
||||
ffi_arg uint;
|
||||
float flt;
|
||||
char data[FFI_SIZEOF_ARG];
|
||||
void* ptr;
|
||||
} ffi_raw;
|
||||
|
||||
void ffi_raw_call (ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
void ffi_raw_call (ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
ffi_raw *avalue);
|
||||
|
||||
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 (ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
ffi_raw *avalue);
|
||||
void ffi_java_raw_call (ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
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 */
|
||||
|
||||
/* ---- Return type alignment -------------------------------------------- */
|
||||
|
||||
/* This is more than enough for all supported architectures. */
|
||||
#define FFI_ALIGN_RVALUE __attribute__((aligned(8)))
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
#define FFI_CLOSURES 1 /* x86 supports closures */
|
||||
#define FFI_TRAMPOLINE_SIZE 10
|
||||
#define FFI_NATIVE_RAW_API 1 /* and has native raw api support */
|
||||
|
||||
#elif defined(X86_WIN32)
|
||||
|
||||
#define FFI_CLOSURES 1 /* x86 supports closures */
|
||||
#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
|
||||
|
||||
#elif defined(__alpha__)
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#elif defined(POWERPC)
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#else
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
typedef struct {
|
||||
@@ -323,7 +226,7 @@ typedef struct {
|
||||
ffi_cif *cif;
|
||||
void (*fun)(ffi_cif*,void*,void**,void*);
|
||||
void *user_data;
|
||||
} ffi_closure;
|
||||
} ffi_closure __attribute__((aligned (8)));
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure*,
|
||||
@@ -331,8 +234,6 @@ ffi_prep_closure (ffi_closure*,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data);
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
@@ -360,35 +261,58 @@ 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 */
|
||||
|
||||
/* ---- Public interface definition -------------------------------------- */
|
||||
|
||||
ffi_status ffi_prep_cif (ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes);
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes);
|
||||
|
||||
void ffi_call (ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
void **avalue);
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
void **avalue);
|
||||
|
||||
/* Useful for eliminating compiler warnings */
|
||||
#define FFI_FN(f) ((void (*)())f)
|
||||
|
||||
/* ---- Definitions shared with assembly code ---------------------------- */
|
||||
|
||||
#endif
|
||||
|
||||
/* If these change, update src/mips/ffitarget.h. */
|
||||
#define FFI_TYPE_VOID 0
|
||||
#define FFI_TYPE_INT 1
|
||||
#define FFI_TYPE_FLOAT 2
|
||||
#define FFI_TYPE_DOUBLE 3
|
||||
#if @HAVE_LONG_DOUBLE@
|
||||
#define FFI_TYPE_LONGDOUBLE 4
|
||||
#else
|
||||
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
#define FFI_TYPE_UINT8 5
|
||||
#define FFI_TYPE_SINT8 6
|
||||
#define FFI_TYPE_UINT16 7
|
||||
#define FFI_TYPE_SINT16 8
|
||||
#define FFI_TYPE_UINT32 9
|
||||
#define FFI_TYPE_SINT32 10
|
||||
#define FFI_TYPE_UINT64 11
|
||||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13
|
||||
#define FFI_TYPE_POINTER 14
|
||||
|
||||
/* This should always refer to the last type code (for sanity checks) */
|
||||
#define FFI_TYPE_LAST FFI_TYPE_POINTER
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
95
libffi/include/ffi_common.h
Normal file
95
libffi/include/ffi_common.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
Common internal definitions and macros. Only necessary for building
|
||||
libffi.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef FFI_COMMON_H
|
||||
#define FFI_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <fficonfig.h>
|
||||
|
||||
/* Do not move this. Some versions of AIX are very picky about where
|
||||
this is positioned. */
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
#else
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Check for the existence of memcpy. */
|
||||
#if STDC_HEADERS
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifndef HAVE_MEMCPY
|
||||
# define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(FFI_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef FFI_DEBUG
|
||||
void ffi_assert(char *expr, char *file, int line);
|
||||
void ffi_stop_here(void);
|
||||
void ffi_type_test(ffi_type *a, char *file, int line);
|
||||
|
||||
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
|
||||
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
|
||||
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
|
||||
#else
|
||||
#define FFI_ASSERT(x)
|
||||
#define FFI_ASSERT_AT(x, f, l)
|
||||
#define FFI_ASSERT_VALID_TYPE(x)
|
||||
#endif
|
||||
|
||||
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
||||
#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
|
||||
|
||||
/* Extended cif, used in callback from assembly routine */
|
||||
typedef struct
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void *rvalue;
|
||||
void **avalue;
|
||||
} extended_cif;
|
||||
|
||||
/* Terse sized type definitions. */
|
||||
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
|
||||
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
|
||||
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
|
||||
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
|
||||
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
|
||||
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
|
||||
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
|
||||
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
|
||||
|
||||
typedef float FLOAT32;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi 2.0.0 - Copyright (C) 1996, 1997, 1998, 1999, 2000,
|
||||
2001 Red Hat, Inc.
|
||||
|
||||
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 RED HAT 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 <fficonfig.h>
|
||||
|
||||
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#define FLOAT32 float
|
||||
#define FLOAT64 double
|
||||
#define FLOAT80 long double
|
||||
|
||||
#define UINT8 unsigned char
|
||||
#define SINT8 signed char
|
||||
|
||||
#if SIZEOF_INT == 2
|
||||
|
||||
#define UINT16 unsigned int
|
||||
#define SINT16 int
|
||||
|
||||
#else
|
||||
#if SIZEOF_SHORT == 2
|
||||
|
||||
#define UINT16 unsigned short
|
||||
#define SINT16 short
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT == 4
|
||||
|
||||
#define UINT32 unsigned int
|
||||
#define SINT32 int
|
||||
|
||||
#else
|
||||
#if SIZEOF_SHORT == 4
|
||||
|
||||
#define UINT32 unsigned short
|
||||
#define SINT32 short
|
||||
|
||||
#else
|
||||
#if SIZEOF_LONG == 4
|
||||
|
||||
#define UINT32 unsigned long
|
||||
#define SINT32 long
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT == 8
|
||||
|
||||
#define UINT64 unsigned int
|
||||
#define SINT64 int
|
||||
|
||||
#else
|
||||
#if SIZEOF_LONG == 8
|
||||
|
||||
#define UINT64 unsigned long
|
||||
#define SINT64 long
|
||||
|
||||
#else
|
||||
#if SIZEOF_LONG_LONG == 8
|
||||
|
||||
#define UINT64 unsigned long long
|
||||
#define SINT64 long long
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FFI_TYPE_VOID 0
|
||||
#define FFI_TYPE_INT 1
|
||||
#define FFI_TYPE_FLOAT 2
|
||||
#define FFI_TYPE_DOUBLE 3
|
||||
#if SIZEOF_LONG_DOUBLE == SIZEOF_DOUBLE
|
||||
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
|
||||
#else
|
||||
#define FFI_TYPE_LONGDOUBLE 4
|
||||
#endif
|
||||
#define FFI_TYPE_UINT8 5 /* If this changes, update ffi_mips.h. */
|
||||
#define FFI_TYPE_SINT8 6 /* If this changes, update ffi_mips.h. */
|
||||
#define FFI_TYPE_UINT16 7
|
||||
#define FFI_TYPE_SINT16 8
|
||||
#define FFI_TYPE_UINT32 9
|
||||
#define FFI_TYPE_SINT32 10
|
||||
#define FFI_TYPE_UINT64 11
|
||||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13 /* If this changes, update ffi_mips.h. */
|
||||
#define FFI_TYPE_POINTER 14
|
||||
#define FFI_TYPE_LAST 14
|
||||
|
||||
#if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
|
||||
#define SIZEOF_ARG 8
|
||||
#else
|
||||
#define SIZEOF_ARG SIZEOF_VOID_P
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* This part of the private header file is only for C code. */
|
||||
|
||||
/* Check for the existence of memcpy. */
|
||||
#if STDC_HEADERS
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifndef HAVE_MEMCPY
|
||||
# define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
/* bool is a keyword in C++ */
|
||||
typedef int bool;
|
||||
#endif
|
||||
|
||||
#ifdef FFI_DEBUG
|
||||
/* Debugging functions */
|
||||
void ffi_stop_here(void);
|
||||
bool ffi_type_test(ffi_type *a);
|
||||
#define FFI_ASSERT(x) ((x) ? 0 : ffi_assert(__FILE__,__LINE__))
|
||||
#else
|
||||
#define FFI_ASSERT(x)
|
||||
#endif
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
|
||||
|
||||
/* Extended cif, used in callback from assembly routine */
|
||||
typedef struct
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void *rvalue;
|
||||
void **avalue;
|
||||
} extended_cif;
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
@@ -1,19 +1,38 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
|
||||
scriptversion=2005-05-14.22
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
# 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 THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
@@ -23,13 +42,11 @@
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
@@ -41,211 +58,266 @@ stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dstarg=
|
||||
no_target_directory=
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
Options:
|
||||
-c (ignored)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
while test -n "$1"; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
*) # When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
test -n "$dir_arg$dstarg" && break
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dstarg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dstarg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dstarg=$arg
|
||||
done
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -z "$1"; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
esac
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
src=
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
if test -d "$dst"; then
|
||||
mkdircmd=:
|
||||
chmodcmd=
|
||||
else
|
||||
mkdircmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
if test -z "$dstarg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst/`basename "$src"`
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
# This sed command emulates the dirname command.
|
||||
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
# Make sure that the destination directory exists.
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if test ! -d "$dstdir"; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
pathcomp=
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
while test $# -ne 0 ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
if test ! -d "$pathcomp"; then
|
||||
$mkdirprog "$pathcomp"
|
||||
# mkdir can fail with a `File exist' error in case several
|
||||
# install-sh are creating the directory concurrently. This
|
||||
# is OK.
|
||||
test -d "$pathcomp" || exit
|
||||
fi
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
if test -n "$dir_arg"; then
|
||||
$doit $mkdircmd "$dst" \
|
||||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
else
|
||||
dstfile=`basename "$dst"`
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
fi &&
|
||||
# Copy the file name to the temp name.
|
||||
$doit $cpprog "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||
|
||||
exit 0
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dstdir/$dstfile"; then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
}
|
||||
}
|
||||
fi || { (exit 1); exit 1; }
|
||||
done
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
{
|
||||
(exit 0); exit 0
|
||||
}
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
|
||||
6
libffi/libtool-version
Normal file
6
libffi/libtool-version
Normal file
@@ -0,0 +1,6 @@
|
||||
# This file is used to maintain libtool version info for libffi. See
|
||||
# the libtool manual to understand the meaning of the fields. This is
|
||||
# a separate file so that version updates don't involve re-running
|
||||
# automake.
|
||||
# CURRENT:REVISION:AGE
|
||||
4:1:0
|
||||
5621
libffi/ltmain.sh
5621
libffi/ltmain.sh
File diff suppressed because it is too large
Load Diff
@@ -1,173 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
o32.S - Copyright (c) 1996, 1998, 2001 Red Hat, Inc.
|
||||
|
||||
MIPS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <mips/mips.h>
|
||||
|
||||
/* Only build this code if we are compiling for o32 */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
|
||||
#define SIZEOF_FRAME ( 4 * SIZEOF_ARG + 2 * SIZEOF_ARG )
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_call_O32
|
||||
.ent ffi_call_O32
|
||||
ffi_call_O32:
|
||||
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
|
||||
REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
|
||||
move $fp, $sp
|
||||
|
||||
move t9, callback # callback function pointer
|
||||
REG_S flags, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # flags
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
move v0, bytes
|
||||
bge bytes, 4 * SIZEOF_ARG, bigger
|
||||
LI v0, 4 * SIZEOF_ARG
|
||||
b sixteen
|
||||
|
||||
bigger:
|
||||
ADDU t0, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
|
||||
and v0, t0, -2 * SIZEOF_ARG # to an 8 byte boundry
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 4 * SIZEOF_ARG
|
||||
ADDU a3, $fp, SIZEOF_FRAME + 3*SIZEOF_ARG
|
||||
|
||||
jal t9
|
||||
|
||||
REG_L t0, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # load the flags word
|
||||
add t2, t0, 0 # and copy it into t2
|
||||
|
||||
and t0, ((1<<4)-1) # mask out the return type
|
||||
SRL t2, 4 # shift our arg info
|
||||
|
||||
ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
bnez t0, pass_d # make it quick for int
|
||||
REG_L a0, 0*SIZEOF_ARG($sp) # just go ahead and load the
|
||||
REG_L a1, 1*SIZEOF_ARG($sp) # four regs.
|
||||
REG_L a2, 2*SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d:
|
||||
bne t0, FFI_ARGS_D, pass_f
|
||||
l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a2, 2*SIZEOF_ARG($sp) # passing a double
|
||||
REG_L a3, 3*SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f:
|
||||
bne t0, FFI_ARGS_F, pass_d_d
|
||||
l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a1, 1*SIZEOF_ARG($sp) # passing a float
|
||||
REG_L a2, 2*SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_d:
|
||||
bne t0, FFI_ARGS_DD, pass_f_f
|
||||
l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*SIZEOF_ARG($sp) # passing two doubles
|
||||
b call_it
|
||||
|
||||
pass_f_f:
|
||||
bne t0, FFI_ARGS_FF, pass_d_f
|
||||
l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 1*SIZEOF_ARG($sp) # passing two floats
|
||||
REG_L a2, 2*SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_f:
|
||||
bne t0, FFI_ARGS_DF, pass_f_d
|
||||
l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 2*SIZEOF_ARG($sp) # passing double and float
|
||||
REG_L a3, 3*SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f_d:
|
||||
# assume that the only other combination must be float then double
|
||||
# bne t0, FFI_ARGS_F_D, call_it
|
||||
l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*SIZEOF_ARG($sp) # passing double and float
|
||||
|
||||
call_it:
|
||||
# Load the function pointer
|
||||
REG_L t9, SIZEOF_FRAME + 5*SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t1, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
||||
beqz t1, noretval
|
||||
|
||||
bne t2, FFI_TYPE_INT, retfloat
|
||||
jal t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t2, FFI_TYPE_FLOAT, retdouble
|
||||
jal t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t2, FFI_TYPE_DOUBLE, noretval
|
||||
jal t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
noretval:
|
||||
jal t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
.end ffi_call_O32
|
||||
|
||||
#endif
|
||||
220
libffi/missing
220
libffi/missing
@@ -1,7 +1,11 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
scriptversion=2005-06-08.21
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -15,15 +19,47 @@
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case "$1" in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
@@ -35,6 +71,7 @@ error status if there is no known handling for PROGRAM.
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
@@ -43,13 +80,19 @@ Supported PROGRAM values:
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing - GNU libit 0.0"
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
@@ -58,10 +101,45 @@ Supported PROGRAM values:
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aclocal)
|
||||
esac
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program).
|
||||
case "$1" in
|
||||
lex|yacc)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
tar)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`acinclude.m4' or \`configure.in'. You might want
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
@@ -69,8 +147,8 @@ WARNING: \`$1' is missing on your system. You should only need it if
|
||||
|
||||
autoconf)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`configure.in'. You might want to install the
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
@@ -78,11 +156,11 @@ WARNING: \`$1' is missing on your system. You should only need it if
|
||||
|
||||
autoheader)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`acconfig.h' or \`configure.in'. You might want
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
@@ -95,10 +173,10 @@ WARNING: \`$1' is missing on your system. You should only need it if
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake)
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
@@ -106,9 +184,32 @@ WARNING: \`$1' is missing on your system. You should only need it if
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
@@ -138,7 +239,7 @@ WARNING: \`$1' is missing on your system. You should only need it if
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
@@ -159,28 +260,90 @@ WARNING: \`$1' is missing on your system. You should only need it if
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and you do not seem to have it handy on your
|
||||
system. You might have modified some files without having the
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequirements for installing
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
@@ -188,3 +351,10 @@ WARNING: \`$1' is needed, and you do not seem to have it handy on your
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
|
||||
@@ -1,36 +1,158 @@
|
||||
#! /bin/sh
|
||||
# mkinstalldirs --- make directory hierarchy
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
|
||||
scriptversion=2005-06-29.22
|
||||
|
||||
# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-05-16
|
||||
# Last modified: 1994-03-25
|
||||
# Public domain
|
||||
# Public domain.
|
||||
#
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
errstatus=0
|
||||
dirmode=
|
||||
|
||||
for file in ${1+"$@"} ; do
|
||||
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
|
||||
shift
|
||||
usage="\
|
||||
Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
|
||||
|
||||
pathcomp=
|
||||
for d in ${1+"$@"} ; do
|
||||
pathcomp="$pathcomp$d"
|
||||
case "$pathcomp" in
|
||||
-* ) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
Create each directory DIR (with mode MODE, if specified), including all
|
||||
leading file name components.
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp" 1>&2
|
||||
mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
|
||||
fi
|
||||
Report bugs to <bug-automake@gnu.org>."
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
# process command line arguments
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
-h | --help | --h*) # -h for help
|
||||
echo "$usage"
|
||||
exit $?
|
||||
;;
|
||||
-m) # -m PERM arg
|
||||
shift
|
||||
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
|
||||
dirmode=$1
|
||||
shift
|
||||
;;
|
||||
--version)
|
||||
echo "$0 $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
--) # stop option processing
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*) # unknown option
|
||||
echo "$usage" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
*) # first non-opt arg
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
for file
|
||||
do
|
||||
if test -d "$file"; then
|
||||
shift
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
case $# in
|
||||
0) exit 0 ;;
|
||||
esac
|
||||
|
||||
# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
|
||||
# mkdir -p a/c at the same time, both will detect that a is missing,
|
||||
# one will create a, then the other will try to create a and die with
|
||||
# a "File exists" error. This is a problem when calling mkinstalldirs
|
||||
# from a parallel make. We use --version in the probe to restrict
|
||||
# ourselves to GNU mkdir, which is thread-safe.
|
||||
case $dirmode in
|
||||
'')
|
||||
if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
||||
echo "mkdir -p -- $*"
|
||||
exec mkdir -p -- "$@"
|
||||
else
|
||||
# On NextStep and OpenStep, the `mkdir' command does not
|
||||
# recognize any option. It will interpret all options as
|
||||
# directories to create, and then abort because `.' already
|
||||
# exists.
|
||||
test -d ./-p && rmdir ./-p
|
||||
test -d ./--version && rmdir ./--version
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
|
||||
test ! -d ./--version; then
|
||||
echo "mkdir -m $dirmode -p -- $*"
|
||||
exec mkdir -m "$dirmode" -p -- "$@"
|
||||
else
|
||||
# Clean up after NextStep and OpenStep mkdir.
|
||||
for d in ./-m ./-p ./--version "./$dirmode";
|
||||
do
|
||||
test -d $d && rmdir $d
|
||||
done
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
for file
|
||||
do
|
||||
case $file in
|
||||
/*) pathcomp=/ ;;
|
||||
*) pathcomp= ;;
|
||||
esac
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set fnord $file
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
for d
|
||||
do
|
||||
test "x$d" = x && continue
|
||||
|
||||
pathcomp=$pathcomp$d
|
||||
case $pathcomp in
|
||||
-*) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp"
|
||||
|
||||
mkdir "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
errstatus=$lasterr
|
||||
fi
|
||||
else
|
||||
if test ! -z "$dirmode"; then
|
||||
echo "chmod $dirmode $pathcomp"
|
||||
lasterr=
|
||||
chmod "$dirmode" "$pathcomp" || lasterr=$?
|
||||
|
||||
pathcomp="$pathcomp/"
|
||||
done
|
||||
if test ! -z "$lasterr"; then
|
||||
errstatus=$lasterr
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
done
|
||||
|
||||
exit $errstatus
|
||||
|
||||
# mkinstalldirs ends here
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
|
||||
@@ -1,680 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Geoffrey Keating
|
||||
|
||||
PowerPC Foreign Function Interface
|
||||
|
||||
$Id: ffi.c,v 1.2 2001/04/23 00:32:03 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 THE AUTHOR 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_private.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern void ffi_closure_SYSV(void);
|
||||
|
||||
enum {
|
||||
/* The assembly depends on these exact flags. */
|
||||
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||
FLAG_RETURNS_FP = 1 << (31-29),
|
||||
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||
|
||||
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
||||
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
||||
};
|
||||
|
||||
/* About the SYSV ABI. */
|
||||
enum {
|
||||
NUM_GPR_ARG_REGISTERS = 8,
|
||||
NUM_FPR_ARG_REGISTERS = 8
|
||||
};
|
||||
enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments.
|
||||
|
||||
The stack layout we want looks like this:
|
||||
|
||||
| Return address from ffi_call_SYSV 4bytes | higher addresses
|
||||
|--------------------------------------------|
|
||||
| Previous backchain pointer 4 | stack pointer here
|
||||
|--------------------------------------------|<+ <<< on entry to
|
||||
| Saved r28-r31 4*4 | | ffi_call_SYSV
|
||||
|--------------------------------------------| |
|
||||
| GPR registers r3-r10 8*4 | | ffi_call_SYSV
|
||||
|--------------------------------------------| |
|
||||
| FPR registers f1-f8 (optional) 8*8 | |
|
||||
|--------------------------------------------| | stack |
|
||||
| Space for copied structures | | grows |
|
||||
|--------------------------------------------| | down V
|
||||
| Parameters that didn't fit in registers | |
|
||||
|--------------------------------------------| | lower addresses
|
||||
| Space for callee's LR 4 | |
|
||||
|--------------------------------------------| | stack pointer here
|
||||
| Current backchain pointer 4 |-/ during
|
||||
|--------------------------------------------| <<< ffi_call_SYSV
|
||||
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
||||
/* 'stacktop' points at the previous backchain pointer. */
|
||||
unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
|
||||
|
||||
/* 'gpr_base' points at the space for gpr3, and grows upwards as
|
||||
we use GPR registers. */
|
||||
unsigned *gpr_base = stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
|
||||
int intarg_count = 0;
|
||||
|
||||
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
||||
we use FPR registers. */
|
||||
double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS;
|
||||
int fparg_count = 0;
|
||||
|
||||
/* 'copy_space' grows down as we put structures in it. It should
|
||||
stay 16-byte aligned. */
|
||||
char *copy_space = ((flags & FLAG_FP_ARGUMENTS)
|
||||
? (char *)fpr_base
|
||||
: (char *)gpr_base);
|
||||
|
||||
/* 'next_arg' grows up as we put parameters in it. */
|
||||
unsigned *next_arg = stack + 2;
|
||||
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
double double_tmp;
|
||||
void **p_argv;
|
||||
size_t struct_copy_size;
|
||||
unsigned gprvalue;
|
||||
|
||||
/* Check that everything starts aligned properly. */
|
||||
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
|
||||
FFI_ASSERT(((unsigned)(char *)copy_space & 0xF) == 0);
|
||||
FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
|
||||
FFI_ASSERT((bytes & 0xF) == 0);
|
||||
FFI_ASSERT(copy_space >= (char *)next_arg);
|
||||
|
||||
/* Deal with return values that are actually pass-by-reference. */
|
||||
if (flags & FLAG_RETVAL_REFERENCE)
|
||||
{
|
||||
*gpr_base++ = (unsigned)(char *)ecif->rvalue;
|
||||
intarg_count++;
|
||||
}
|
||||
|
||||
/* Now for the arguments. */
|
||||
p_argv = ecif->avalue;
|
||||
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if ((*ptr)->type == FFI_TYPE_FLOAT)
|
||||
double_tmp = *(float *)*p_argv;
|
||||
else
|
||||
double_tmp = *(double *)*p_argv;
|
||||
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
{
|
||||
if (intarg_count%2 != 0)
|
||||
{
|
||||
intarg_count++;
|
||||
next_arg++;
|
||||
}
|
||||
*(double *)next_arg = double_tmp;
|
||||
next_arg += 2;
|
||||
}
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
|
||||
intarg_count++;
|
||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
|
||||
{
|
||||
if (intarg_count%2 != 0)
|
||||
{
|
||||
intarg_count++;
|
||||
next_arg++;
|
||||
}
|
||||
*(long long *)next_arg = *(long long *)*p_argv;
|
||||
next_arg += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* whoops: abi states only certain register pairs
|
||||
* can be used for passing long long int
|
||||
* specifically (r3,r4), (r5,r6), (r7,r8),
|
||||
* (r9,r10) and if next arg is long long but
|
||||
* not correct starting register of pair then skip
|
||||
* until the proper starting register
|
||||
*/
|
||||
if (intarg_count%2 != 0)
|
||||
{
|
||||
intarg_count ++;
|
||||
gpr_base++;
|
||||
}
|
||||
*(long long *)gpr_base = *(long long *)*p_argv;
|
||||
gpr_base += 2;
|
||||
}
|
||||
intarg_count += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
|
||||
copy_space -= struct_copy_size;
|
||||
memcpy(copy_space, (char *)*p_argv, (*ptr)->size);
|
||||
|
||||
gprvalue = (unsigned)copy_space;
|
||||
|
||||
FFI_ASSERT(copy_space > (char *)next_arg);
|
||||
FFI_ASSERT(flags & FLAG_ARG_NEEDS_COPY);
|
||||
goto putgpr;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
gprvalue = *(unsigned char *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_SINT8:
|
||||
gprvalue = *(signed char *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_UINT16:
|
||||
gprvalue = *(unsigned short *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_SINT16:
|
||||
gprvalue = *(signed short *)*p_argv;
|
||||
goto putgpr;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
gprvalue = *(unsigned *)*p_argv;
|
||||
putgpr:
|
||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
|
||||
*next_arg++ = gprvalue;
|
||||
else
|
||||
*gpr_base++ = gprvalue;
|
||||
intarg_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that we didn't overrun the stack... */
|
||||
FFI_ASSERT(copy_space >= (char *)next_arg);
|
||||
FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
|
||||
FFI_ASSERT((unsigned *)fpr_base
|
||||
<= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||
FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* All this is for the SYSV ABI. */
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fparg_count = 0, intarg_count = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned struct_copy_size = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
Redo the calculation for SYSV. */
|
||||
|
||||
/* Space for the frame pointer, callee's LR, and the asm's temp regs. */
|
||||
bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof(int);
|
||||
|
||||
/* Space for the GPR registers. */
|
||||
bytes += NUM_GPR_ARG_REGISTERS * sizeof(int);
|
||||
|
||||
/* Return value handling. The rules are as follows:
|
||||
- 32-bit (or less) integer values are returned in gpr3;
|
||||
- Structures of size <= 4 bytes also returned in gpr3;
|
||||
- 64-bit integer values and structures between 5 and 8 bytes are returned
|
||||
in gpr3 and gpr4;
|
||||
- Single/double FP values are returned in fpr1;
|
||||
- Larger structures and long double (if not equivalent to double) values
|
||||
are allocated space and a pointer is passed as the first argument. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
/* Fall through. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->abi != FFI_GCC_SYSV)
|
||||
if (cif->rtype->size <= 4)
|
||||
break;
|
||||
else if (cif->rtype->size <= 8)
|
||||
{
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
break;
|
||||
}
|
||||
/* else fall through. */
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
intarg_count++;
|
||||
flags |= FLAG_RETVAL_REFERENCE;
|
||||
/* Fall through. */
|
||||
case FFI_TYPE_VOID:
|
||||
flags |= FLAG_RETURNS_NOTHING;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Returns 32-bit integer, or similar. Nothing to do here. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
||||
first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
|
||||
goes on the stack. Structures and long doubles (if not equivalent
|
||||
to double) are passed as a pointer to a copy of the structure.
|
||||
Stuff on the stack needs to keep proper alignment. */
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fparg_count++;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
8-byte-aligned. */
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
||||
&& intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/* 'long long' arguments are passed as two words, but
|
||||
either both words must fit in registers or both go
|
||||
on the stack. If they go on the stack, they must
|
||||
be 8-byte-aligned. */
|
||||
if (intarg_count == NUM_GPR_ARG_REGISTERS-1
|
||||
|| intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
intarg_count += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
/* We must allocate space for a copy of these to enforce
|
||||
pass-by-value. Pad the space up to a multiple of 16
|
||||
bytes (the maximum alignment required for anything under
|
||||
the SYSV ABI). */
|
||||
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
|
||||
/* Fall through (allocate space for the pointer). */
|
||||
|
||||
default:
|
||||
/* Everything else is passed as a 4-byte word in a GPR, either
|
||||
the object itself or a pointer to it. */
|
||||
intarg_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fparg_count != 0)
|
||||
flags |= FLAG_FP_ARGUMENTS;
|
||||
if (intarg_count > 4)
|
||||
flags |= FLAG_4_GPR_ARGUMENTS;
|
||||
if (struct_copy_size != 0)
|
||||
flags |= FLAG_ARG_NEEDS_COPY;
|
||||
|
||||
/* Space for the FPR registers, if needed. */
|
||||
if (fparg_count != 0)
|
||||
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
||||
|
||||
/* Stack space. */
|
||||
if (intarg_count > NUM_GPR_ARG_REGISTERS)
|
||||
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS)
|
||||
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);
|
||||
|
||||
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
||||
bytes = (bytes + 15) & ~0xF;
|
||||
|
||||
/* Add in the space for the copied structures. */
|
||||
bytes += struct_copy_size;
|
||||
|
||||
cif->flags = flags;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ 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))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
case FFI_GCC_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(&ecif, -cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void flush_icache(char *, int);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
||||
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
|
||||
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[5] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
|
||||
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
|
||||
tramp[8] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[3] = (void *)closure; /* context */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. */
|
||||
flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
#define MIN_CACHE_LINE_SIZE 8
|
||||
|
||||
static void flush_icache(char * addr1, int size)
|
||||
{
|
||||
int i;
|
||||
char * addr;
|
||||
for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) {
|
||||
addr = addr1 + i;
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory");
|
||||
}
|
||||
addr = addr1 + size - 1;
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory");
|
||||
}
|
||||
|
||||
|
||||
int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
|
||||
unsigned long*, unsigned long*);
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_SYSV, and on
|
||||
* entry, r11 holds the address of the closure.
|
||||
* After storing the registers that could possibly contain
|
||||
* parameters to be passed into the stack frame and setting
|
||||
* up space for a return value, ffi_closure_SYSV invokes the
|
||||
* following helper function to do most of the work
|
||||
*/
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
|
||||
unsigned long * pgr, unsigned long * pfr,
|
||||
unsigned long * pst)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
/* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
|
||||
/* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
|
||||
/* pst is the pointer to outgoing parameter stack in original caller */
|
||||
|
||||
void ** avalue;
|
||||
ffi_type ** arg_types;
|
||||
long i, avn;
|
||||
long nf; /* number of floating registers already used */
|
||||
long ng; /* number of general registers already used */
|
||||
ffi_cif * cif;
|
||||
double temp;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
nf = 0;
|
||||
ng = 0;
|
||||
|
||||
/* Copy the caller's structure return value address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = *pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
while (i < avn)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8) {
|
||||
avalue[i] = (((char *)pgr)+3);
|
||||
ng++;
|
||||
pgr++;
|
||||
} else {
|
||||
avalue[i] = (((char *)pst)+3);
|
||||
pst++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8) {
|
||||
avalue[i] = (((char *)pgr)+2);
|
||||
ng++;
|
||||
pgr++;
|
||||
} else {
|
||||
avalue[i] = (((char *)pst)+2);
|
||||
pst++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8) {
|
||||
avalue[i] = pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
} else {
|
||||
avalue[i] = pst;
|
||||
pst++;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
/* passing long long ints are complex, they must
|
||||
* be passed in suitable register pairs such as
|
||||
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
|
||||
* and if the entire pair aren't available then the outgoing
|
||||
* parameter stack is used for both but an alignment of 8
|
||||
* must will be kept. So we must either look in pgr
|
||||
* or pst to find the correct address for this type
|
||||
* of parameter.
|
||||
*/
|
||||
if (ng < 7) {
|
||||
if (ng & 0x01) {
|
||||
/* skip r4, r6, r8 as starting points */
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
avalue[i] = pgr;
|
||||
ng+=2;
|
||||
pgr+=2;
|
||||
} else {
|
||||
if (((long)pst) & 4) pst++;
|
||||
avalue[i] = pst;
|
||||
pst+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* unfortunately float values are stored as doubles
|
||||
* in the ffi_closure_SYSV code (since we don't check
|
||||
* the type in that routine). This is also true
|
||||
* of floats passed on the outgoing parameter stack.
|
||||
* Also, on the outgoing stack all values are aligned
|
||||
* to 8
|
||||
*
|
||||
* Don't you just love the simplicity of this ABI!
|
||||
*/
|
||||
|
||||
/* there are 8 64bit floating point registers */
|
||||
|
||||
if (nf < 8) {
|
||||
temp = *(double*)pfr;
|
||||
*(float*)pfr = (float)temp;
|
||||
avalue[i] = pfr;
|
||||
nf++;
|
||||
pfr+=2;
|
||||
} else {
|
||||
/* FIXME? here we are really changing the values
|
||||
* stored in the original calling routines outgoing
|
||||
* parameter stack. This is probably a really
|
||||
* naughty thing to do but...
|
||||
*/
|
||||
if (((long)pst) & 4) pst++;
|
||||
temp = *(double*)pst;
|
||||
*(float*)pst = (float)temp;
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* On the outgoing stack all values are aligned to 8 */
|
||||
/* there are 8 64bit floating point registers */
|
||||
|
||||
if (nf < 8) {
|
||||
avalue[i] = pfr;
|
||||
nf++;
|
||||
pfr+=2;
|
||||
} else {
|
||||
if (((long)pst) & 4) pst++;
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst+=2;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_osf how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
#define LIBFFI_ASM
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
.globl ffi_closure_helper_SYSV
|
||||
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
stwu %r1,-144(%r1)
|
||||
mflr %r0
|
||||
stw %r31,140(%r1)
|
||||
stw %r0,148(%r1)
|
||||
|
||||
# we want to build up an areas for the parameters passed
|
||||
# in registers (both floating point and integer)
|
||||
|
||||
# so first save gpr 3 to gpr 10 (aligned to 4)
|
||||
stw %r3, 16(%r1)
|
||||
stw %r4, 20(%r1)
|
||||
stw %r5, 24(%r1)
|
||||
stw %r6, 28(%r1)
|
||||
stw %r7, 32(%r1)
|
||||
stw %r8, 36(%r1)
|
||||
stw %r9, 40(%r1)
|
||||
stw %r10,44(%r1)
|
||||
|
||||
# next save fpr 1 to fpr 8 (aligned to 8)
|
||||
stfd %f1, 48(%r1)
|
||||
stfd %f2, 56(%r1)
|
||||
stfd %f3, 64(%r1)
|
||||
stfd %f4, 72(%r1)
|
||||
stfd %f5, 80(%r1)
|
||||
stfd %f6, 88(%r1)
|
||||
stfd %f7, 96(%r1)
|
||||
stfd %f8, 104(%r1)
|
||||
|
||||
# set up registers for the routine that actually does the work
|
||||
# get the context pointer from the trampoline
|
||||
mr %r3,%r11
|
||||
|
||||
# now load up the pointer to the result storage
|
||||
addi %r4,%r1,112
|
||||
|
||||
# now load up the pointer to the saved gpr registers
|
||||
addi %r5,%r1,16
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6,%r1,48
|
||||
|
||||
# now load up the pointer to the outgoing parameter
|
||||
# stack in the previous frame
|
||||
# i.e. the previous frame pointer + 8
|
||||
addi %r7,%r1,152
|
||||
|
||||
# make the call
|
||||
bl JUMPTARGET(ffi_closure_helper_SYSV)
|
||||
|
||||
# now r3 contains the return type
|
||||
# so use it to look up in a table
|
||||
# so we know how to deal with each type
|
||||
|
||||
# look up the proper starting point in table
|
||||
# by using return type as offset
|
||||
addi %r5,%r1,112 # get pointer to results area
|
||||
addis %r4,0,.L60@ha # get address of jump table
|
||||
addi %r4,%r4,.L60@l
|
||||
slwi %r3,%r3,2 # now multiply return type by 4
|
||||
lwzx %r3,%r4,%r3 # get the contents of that table value
|
||||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
.align 2
|
||||
.L60:
|
||||
.long .L44-.L60 # FFI_TYPE_VOID
|
||||
.long .L50-.L60 # FFI_TYPE_INT
|
||||
.long .L47-.L60 # FFI_TYPE_FLOAT
|
||||
.long .L46-.L60 # FFI_TYPE_DOUBLE
|
||||
.long .L46-.L60 # FFI_TYPE_LONGDOUBLE
|
||||
.long .L56-.L60 # FFI_TYPE_UINT8
|
||||
.long .L55-.L60 # FFI_TYPE_SINT8
|
||||
.long .L58-.L60 # FFI_TYPE_UINT16
|
||||
.long .L57-.L60 # FFI_TYPE_SINT16
|
||||
.long .L50-.L60 # FFI_TYPE_UINT32
|
||||
.long .L50-.L60 # FFI_TYPE_SINT32
|
||||
.long .L48-.L60 # FFI_TYPE_UINT64
|
||||
.long .L48-.L60 # FFI_TYPE_SINT64
|
||||
.long .L44-.L60 # FFI_TYPE_STRUCT
|
||||
.long .L50-.L60 # FFI_TYPE_POINTER
|
||||
|
||||
|
||||
# case double
|
||||
.L46:
|
||||
lfd %f1,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case float
|
||||
.L47:
|
||||
lfs %f1,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case long long
|
||||
.L48:
|
||||
lwz %r3,0(%r5)
|
||||
lwz %r4,4(%r5)
|
||||
b .L44
|
||||
|
||||
# case default / int32 / pointer
|
||||
.L50:
|
||||
lwz %r3,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case signed int8
|
||||
.L55:
|
||||
addi %r5,%r5,3
|
||||
lbz %r3,0(%r5)
|
||||
extsb %r3,%r3
|
||||
b .L44
|
||||
|
||||
# case unsigned int8
|
||||
.L56:
|
||||
addi %r5,%r5,3
|
||||
lbz %r3,0(%r5)
|
||||
b .L44
|
||||
|
||||
# case signed int16
|
||||
.L57:
|
||||
addi %r5,%r5,2
|
||||
lhz %r3,0(%r5)
|
||||
extsh %r3,%r3
|
||||
b .L44
|
||||
|
||||
#case unsigned int16
|
||||
.L58:
|
||||
addi %r5,%r5,2
|
||||
lhz %r3,0(%r5)
|
||||
|
||||
# case void / done
|
||||
.L44:
|
||||
|
||||
lwz %r11,0(%r1)
|
||||
lwz %r0,4(%r11)
|
||||
mtlr %r0
|
||||
lwz %r31,-4(%r11)
|
||||
mr %r1,%r11
|
||||
blr
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,589 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2000 Software AG
|
||||
|
||||
S390 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 THE AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
/*====================================================================*/
|
||||
/* Includes */
|
||||
/* -------- */
|
||||
/*====================================================================*/
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*====================== End of Includes =============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Defines */
|
||||
/* ------- */
|
||||
/*====================================================================*/
|
||||
|
||||
#define MAX_GPRARGS 5 /* Max. no. of GPR available */
|
||||
#define MAX_FPRARGS 2 /* Max. no. of FPR available */
|
||||
|
||||
#define STR_GPR 1 /* Structure will fit in 1 or 2 GPR */
|
||||
#define STR_FPR 2 /* Structure will fit in a FPR */
|
||||
#define STR_STACK 3 /* Structure needs to go on stack */
|
||||
|
||||
/*===================== End of Defines ===============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Types */
|
||||
/* ----- */
|
||||
/*====================================================================*/
|
||||
|
||||
typedef struct stackLayout
|
||||
{
|
||||
int *backChain;
|
||||
int *endOfStack;
|
||||
int glue[2];
|
||||
int scratch[2];
|
||||
int gprArgs[MAX_GPRARGS];
|
||||
int notUsed;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} fprArgs[MAX_FPRARGS];
|
||||
int unUsed[8];
|
||||
int outArgs[100];
|
||||
} stackLayout;
|
||||
|
||||
/*======================== End of Types ==============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Prototypes */
|
||||
/* ---------- */
|
||||
/*====================================================================*/
|
||||
|
||||
void ffi_prep_args(stackLayout *, extended_cif *);
|
||||
static int ffi_check_struct(ffi_type *, unsigned int *);
|
||||
static void ffi_insert_int(int, stackLayout *, int *, int *);
|
||||
static void ffi_insert_int64(long long, stackLayout *, int *, int *);
|
||||
static void ffi_insert_double(double, stackLayout *, int *, int *);
|
||||
|
||||
/*====================== End of Prototypes ===========================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Externals */
|
||||
/* --------- */
|
||||
/*====================================================================*/
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)());
|
||||
|
||||
/*====================== End of Externals ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_check_struct. */
|
||||
/* */
|
||||
/* Function - Determine if a structure can be passed within a */
|
||||
/* general or floating point register. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
int
|
||||
ffi_check_struct(ffi_type *arg, unsigned int *strFlags)
|
||||
{
|
||||
ffi_type *element;
|
||||
int i_Element;
|
||||
|
||||
for (i_Element = 0; arg->elements[i_Element]; i_Element++) {
|
||||
element = arg->elements[i_Element];
|
||||
switch (element->type) {
|
||||
case FFI_TYPE_DOUBLE :
|
||||
*strFlags |= STR_FPR;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT :
|
||||
*strFlags |= ffi_check_struct(element, strFlags);
|
||||
break;
|
||||
|
||||
default :
|
||||
*strFlags |= STR_GPR;
|
||||
}
|
||||
}
|
||||
return (*strFlags);
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_insert_int. */
|
||||
/* */
|
||||
/* Function - Insert an integer parameter in a register if there are */
|
||||
/* spares else on the stack. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_insert_int(int gprValue, stackLayout *stack,
|
||||
int *intArgC, int *outArgC)
|
||||
{
|
||||
if (*intArgC < MAX_GPRARGS) {
|
||||
stack->gprArgs[*intArgC] = gprValue;
|
||||
*intArgC += 1;
|
||||
}
|
||||
else {
|
||||
stack->outArgs[*outArgC++] = gprValue;
|
||||
*outArgC += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_insert_int64. */
|
||||
/* */
|
||||
/* Function - Insert a long long parameter in registers if there are */
|
||||
/* spares else on the stack. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_insert_int64(long long llngValue, stackLayout *stack,
|
||||
int *intArgC, int *outArgC)
|
||||
{
|
||||
|
||||
if (*intArgC < (MAX_GPRARGS-1)) {
|
||||
memcpy(&stack->gprArgs[*intArgC],
|
||||
&llngValue, sizeof(long long));
|
||||
*intArgC += 2;
|
||||
}
|
||||
else {
|
||||
memcpy(&stack->outArgs[*outArgC],
|
||||
&llngValue, sizeof(long long));
|
||||
*outArgC += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_insert_double. */
|
||||
/* */
|
||||
/* Function - Insert a double parameter in a FP register if there is */
|
||||
/* a spare else on the stack. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_insert_double(double dblValue, stackLayout *stack,
|
||||
int *fprArgC, int *outArgC)
|
||||
{
|
||||
|
||||
if (*fprArgC < MAX_FPRARGS) {
|
||||
stack->fprArgs[*fprArgC].d = dblValue;
|
||||
*fprArgC += 1;
|
||||
}
|
||||
else {
|
||||
memcpy(&stack->outArgs[*outArgC],
|
||||
&dblValue,sizeof(double));
|
||||
*outArgC += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_args. */
|
||||
/* */
|
||||
/* Function - Prepare parameters for call to function. */
|
||||
/* */
|
||||
/* ffi_prep_args is called by the assembly routine once stack space */
|
||||
/* has been allocated for the function's arguments. */
|
||||
/* */
|
||||
/* The stack layout we want looks like this: */
|
||||
/* *------------------------------------------------------------* */
|
||||
/* | 0 | Back chain (a 0 here signifies end of back chain) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 4 | EOS (end of stack, not used on Linux for S390) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 8 | Glue used in other linkage formats | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 12 | Glue used in other linkage formats | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 16 | Scratch area | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 20 | Scratch area | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 24 | GPR parameter register 1 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 28 | GPR parameter register 2 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 32 | GPR parameter register 3 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 36 | GPR parameter register 4 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 40 | GPR parameter register 5 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 44 | Unused | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 48 | FPR parameter register 1 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 56 | FPR parameter register 2 | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 64 | Unused | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 96 | Outgoing args (length x) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 96+x | Copy area for structures (length y) | */
|
||||
/* +--------+---------------------------------------------------+ */
|
||||
/* | 96+x+y | Possible stack alignment | */
|
||||
/* *------------------------------------------------------------* */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_prep_args(stackLayout *stack, extended_cif *ecif)
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
||||
/*----------------------------------------------------------*/
|
||||
/* Pointer to the copy area on stack for structures */
|
||||
/*----------------------------------------------------------*/
|
||||
char *copySpace = (char *) stack + bytes + sizeof(stackLayout);
|
||||
|
||||
/*----------------------------------------------------------*/
|
||||
/* Count of general and floating point register usage */
|
||||
/*----------------------------------------------------------*/
|
||||
int intArgC = 0,
|
||||
fprArgC = 0,
|
||||
outArgC = 0;
|
||||
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
void **p_argv;
|
||||
size_t structCopySize;
|
||||
unsigned gprValue, strFlags = 0;
|
||||
unsigned long long llngValue;
|
||||
double dblValue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* If we returning a structure then we set the first parameter register */
|
||||
/* to the address of where we are returning this structure */
|
||||
/*----------------------------------------------------------------------*/
|
||||
if (flags == FFI_TYPE_STRUCT)
|
||||
stack->gprArgs[intArgC++] = (int) ecif->rvalue;
|
||||
|
||||
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
switch ((*ptr)->type) {
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (fprArgC < MAX_FPRARGS)
|
||||
stack->fprArgs[fprArgC++].f = *(float *) *p_argv;
|
||||
else
|
||||
stack->outArgs[outArgC++] = *(int *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
dblValue = *(double *) *p_argv;
|
||||
ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
llngValue = *(unsigned long long *) *p_argv;
|
||||
ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
gprValue = *(unsigned char *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
gprValue = *(signed char *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
gprValue = *(unsigned short *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
gprValue = *(signed short *)*p_argv;
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/*--------------------------------------------------*/
|
||||
/* If structure > 8 bytes then it goes on the stack */
|
||||
/*--------------------------------------------------*/
|
||||
if (((*ptr)->size > 8) ||
|
||||
((*ptr)->size > 4 &&
|
||||
(*ptr)->size < 8))
|
||||
strFlags = STR_STACK;
|
||||
else
|
||||
strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags);
|
||||
|
||||
switch (strFlags) {
|
||||
/*-------------------------------------------*/
|
||||
/* Structure that will fit in one or two GPR */
|
||||
/*-------------------------------------------*/
|
||||
case STR_GPR :
|
||||
if ((*ptr)->size <= 4) {
|
||||
gprValue = *(unsigned int *) *p_argv;
|
||||
gprValue = gprValue >> ((4 - (*ptr)->size) * 8);
|
||||
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
|
||||
}
|
||||
else {
|
||||
llngValue = *(unsigned long long *) *p_argv;
|
||||
ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
|
||||
}
|
||||
break;
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/* Structure that will fit in one FPR */
|
||||
/*-------------------------------------------*/
|
||||
case STR_FPR :
|
||||
dblValue = *(double *) *p_argv;
|
||||
ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
|
||||
break;
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/* Structure that must be copied to stack */
|
||||
/*-------------------------------------------*/
|
||||
default :
|
||||
structCopySize = (((*ptr)->size + 15) & ~0xF);
|
||||
copySpace -= structCopySize;
|
||||
memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
|
||||
gprValue = (unsigned) copySpace;
|
||||
if (intArgC < MAX_GPRARGS)
|
||||
stack->gprArgs[intArgC++] = gprValue;
|
||||
else
|
||||
stack->outArgs[outArgC++] = gprValue;
|
||||
}
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
structCopySize = (((*ptr)->size + 15) & ~0xF);
|
||||
copySpace -= structCopySize;
|
||||
memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
|
||||
gprValue = (unsigned) copySpace;
|
||||
if (intArgC < MAX_GPRARGS)
|
||||
stack->gprArgs[intArgC++] = gprValue;
|
||||
else
|
||||
stack->outArgs[outArgC++] = gprValue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
gprValue = *(unsigned *)*p_argv;
|
||||
if (intArgC < MAX_GPRARGS)
|
||||
stack->gprArgs[intArgC++] = gprValue;
|
||||
else
|
||||
stack->outArgs[outArgC++] = gprValue;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_cif_machdep. */
|
||||
/* */
|
||||
/* Function - Perform machine dependent CIF processing. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fpArgC = 0,
|
||||
intArgC = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned structCopySize = 0;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Extra space required in stack for overflow parameters. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
bytes = 0;
|
||||
|
||||
/*--------------------------------------------------------*/
|
||||
/* Return value handling. The rules are as follows: */
|
||||
/* - 32-bit (or less) integer values are returned in gpr2 */
|
||||
/* - Structures are returned as pointers in gpr2 */
|
||||
/* - 64-bit integer values are returned in gpr2 and 3 */
|
||||
/* - Single/double FP values are returned in fpr0 */
|
||||
/*--------------------------------------------------------*/
|
||||
flags = cif->rtype->type;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The first MAX_GPRARGS words of integer arguments, and the */
|
||||
/* first MAX_FPRARGS floating point arguments, go in registers; the rest */
|
||||
/* goes on the stack. Structures and long doubles (if not equivalent */
|
||||
/* to double) are passed as a pointer to a copy of the structure. */
|
||||
/* Stuff on the stack needs to keep proper alignment. */
|
||||
/*------------------------------------------------------------------------*/
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fpArgC++;
|
||||
if (fpArgC > MAX_FPRARGS && intArgC%2 != 0)
|
||||
intArgC++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/*----------------------------------------------------*/
|
||||
/* 'long long' arguments are passed as two words, but */
|
||||
/* either both words must fit in registers or both go */
|
||||
/* on the stack. If they go on the stack, they must */
|
||||
/* be 8-byte-aligned. */
|
||||
/*----------------------------------------------------*/
|
||||
if ((intArgC == MAX_GPRARGS-1) ||
|
||||
(intArgC >= MAX_GPRARGS) &&
|
||||
(intArgC%2 != 0))
|
||||
intArgC++;
|
||||
intArgC += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
/*----------------------------------------------------*/
|
||||
/* We must allocate space for a copy of these to */
|
||||
/* enforce pass-by-value. Pad the space up to a */
|
||||
/* multiple of 16 bytes (the maximum alignment */
|
||||
/* required for anything under the SYSV ABI). */
|
||||
/*----------------------------------------------------*/
|
||||
structCopySize += ((*ptr)->size + 15) & ~0xF;
|
||||
/*----------------------------------------------------*/
|
||||
/* Fall through (allocate space for the pointer). */
|
||||
/*----------------------------------------------------*/
|
||||
|
||||
default:
|
||||
/*----------------------------------------------------*/
|
||||
/* Everything else is passed as a 4-byte word in a */
|
||||
/* GPR either the object itself or a pointer to it. */
|
||||
/*----------------------------------------------------*/
|
||||
intArgC++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Stack space. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
if (intArgC > MAX_GPRARGS)
|
||||
bytes += (intArgC - MAX_GPRARGS) * sizeof(int);
|
||||
if (fpArgC > MAX_FPRARGS)
|
||||
bytes += (fpArgC - MAX_FPRARGS) * sizeof(double);
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
bytes = (bytes + 15) & ~0xF;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/* Add in the space for the copied structures. */
|
||||
/*-----------------------------------------------------------------*/
|
||||
bytes += structCopySize;
|
||||
|
||||
cif->flags = flags;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_call. */
|
||||
/* */
|
||||
/* Function - Call the FFI routine. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
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_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args,
|
||||
&ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
@@ -1,161 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2000 Software AG
|
||||
|
||||
S390 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
# r2: ffi_prep_args
|
||||
# r3: &ecif
|
||||
# r4: cif->bytes
|
||||
# r5: fig->flags
|
||||
# r6: ecif.rvalue
|
||||
# sp+0: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,%function
|
||||
ffi_call_SYSV:
|
||||
# Save registers
|
||||
stm %r7,%r15,28(%r15)
|
||||
l %r7,96(%r15) # Get A(fn)
|
||||
lr %r0,%r15
|
||||
ahi %r15,-128 # Make room for my args
|
||||
st %r0,0(%r15) # Set backchain
|
||||
lr %r11,%r15 # Establish my stack register
|
||||
sr %r15,%r4 # Make room for fn args
|
||||
ahi %r15,-96 # Make room for new frame
|
||||
lr %r10,%r15 # Establish stack build area
|
||||
ahi %r15,-96 # Stack for next call
|
||||
lr %r1,%r7
|
||||
stm %r2,%r7,96(%r11) # Save args on my stack
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# move first 3 parameters in registers
|
||||
#------------------------------------------------------------------
|
||||
lr %r9,%r2 # r9: &ffi_prep_args
|
||||
lr %r2,%r10 # Parm 1: &stack Parm 2: &ecif
|
||||
basr %r14,%r9 # call ffi_prep_args
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# load first 5 parameter registers
|
||||
#------------------------------------------------------------------
|
||||
lm %r2,%r6,24(%r10)
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# load fp parameter registers
|
||||
#------------------------------------------------------------------
|
||||
ld %f0,48(%r10)
|
||||
ld %f2,56(%r10)
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# call function
|
||||
#------------------------------------------------------------------
|
||||
lr %r15,%r10 # Set new stack
|
||||
l %r9,116(%r11) # Get &fn
|
||||
basr %r14,%r9 # Call function
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# On return:
|
||||
# r2: Return value (r3: Return value + 4 for long long)
|
||||
#------------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
#------------------------------------------------------------------
|
||||
icm %r6,15,112(%r11)
|
||||
jz .Lepilogue
|
||||
|
||||
l %r5,108(%r11) # Get return type
|
||||
#------------------------------------------------------------------
|
||||
# return INT
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_INT
|
||||
jne .Lchk64
|
||||
|
||||
st %r2,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.Lchk64:
|
||||
#------------------------------------------------------------------
|
||||
# return LONG LONG (signed/unsigned)
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_UINT64
|
||||
je .LdoLongLong
|
||||
|
||||
chi %r5,FFI_TYPE_SINT64
|
||||
jne .LchkFloat
|
||||
|
||||
.LdoLongLong:
|
||||
stm %r2,%r3,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.LchkFloat:
|
||||
#------------------------------------------------------------------
|
||||
# return FLOAT
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_FLOAT
|
||||
jne .LchkDouble
|
||||
|
||||
std %f0,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.LchkDouble:
|
||||
#------------------------------------------------------------------
|
||||
# return DOUBLE or LONGDOUBLE
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_DOUBLE
|
||||
jne .LchkStruct
|
||||
|
||||
std %f0,0(%r6)
|
||||
std %f2,8(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.LchkStruct:
|
||||
#------------------------------------------------------------------
|
||||
# Structure - rvalue already set as sent as 1st parm to routine
|
||||
#------------------------------------------------------------------
|
||||
chi %r5,FFI_TYPE_STRUCT
|
||||
je .Lepilogue
|
||||
|
||||
.Ldefault:
|
||||
#------------------------------------------------------------------
|
||||
# return a pointer
|
||||
#------------------------------------------------------------------
|
||||
st %r2,0(%r6)
|
||||
j .Lepilogue
|
||||
|
||||
.Lepilogue:
|
||||
l %r15,0(%r11)
|
||||
l %r4,56(%r15)
|
||||
lm %r7,%r15,28(%r15)
|
||||
br %r4
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
@@ -1,94 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
v8.S - Copyright (c) 1996, 1997 Cygnus Solutions
|
||||
|
||||
Sparc 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.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
|
||||
nop ! STRUCT returning functions skip 12 instead of 8 bytes
|
||||
|
||||
! 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_SINT64
|
||||
be longlong
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
bne done
|
||||
nop
|
||||
st %f0, [%i4+0]
|
||||
st %f1, [%i4+4]
|
||||
|
||||
done:
|
||||
ret
|
||||
restore
|
||||
|
||||
longlong:
|
||||
st %o0, [%i4+0]
|
||||
st %o1, [%i4+4]
|
||||
ret
|
||||
restore
|
||||
|
||||
.ffi_call_V8_end:
|
||||
.size ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
v9.S - Copyright (c) 2000 Cygnus Solutions
|
||||
|
||||
Sparc 64bit 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
|
||||
#if defined(__arch64__) || defined(__sparcv9)
|
||||
/* Only compile this in for 64bit builds, because otherwise the object file
|
||||
will have inproper architecture due to used instructions. */
|
||||
|
||||
#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
|
||||
#define STACK_BIAS 2047
|
||||
#define ARGS (128) /* Offset of register area in frame */
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_call_V9
|
||||
.globl _ffi_call_V9
|
||||
|
||||
ffi_call_V9:
|
||||
_ffi_call_V9:
|
||||
save %sp, -STACKFRAME, %sp
|
||||
|
||||
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
|
||||
add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
|
||||
! frame to set up
|
||||
|
||||
mov %l0, %o0 ! call routine to set up frame
|
||||
call %i0
|
||||
mov %i1, %o1 ! (delay)
|
||||
brz,pt %o0, 1f
|
||||
ldx [%l0+ARGS], %o0 ! call foreign function
|
||||
|
||||
ldd [%l0+ARGS], %f0
|
||||
ldd [%l0+ARGS+8], %f2
|
||||
ldd [%l0+ARGS+16], %f4
|
||||
ldd [%l0+ARGS+24], %f6
|
||||
ldd [%l0+ARGS+32], %f8
|
||||
ldd [%l0+ARGS+40], %f10
|
||||
ldd [%l0+ARGS+48], %f12
|
||||
ldd [%l0+ARGS+56], %f14
|
||||
ldd [%l0+ARGS+64], %f16
|
||||
ldd [%l0+ARGS+72], %f18
|
||||
ldd [%l0+ARGS+80], %f20
|
||||
ldd [%l0+ARGS+88], %f22
|
||||
ldd [%l0+ARGS+96], %f24
|
||||
ldd [%l0+ARGS+104], %f26
|
||||
ldd [%l0+ARGS+112], %f28
|
||||
ldd [%l0+ARGS+120], %f30
|
||||
|
||||
1: ldx [%l0+ARGS+8], %o1
|
||||
ldx [%l0+ARGS+16], %o2
|
||||
ldx [%l0+ARGS+24], %o3
|
||||
ldx [%l0+ARGS+32], %o4
|
||||
ldx [%l0+ARGS+40], %o5
|
||||
call %i5
|
||||
sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
|
||||
|
||||
! If the return value pointer is NULL, assume no return value.
|
||||
brz,pn %i4, done
|
||||
nop
|
||||
|
||||
cmp %i3, FFI_TYPE_INT
|
||||
be,a,pt %icc, done
|
||||
stx %o0, [%i4] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_FLOAT
|
||||
be,a,pn %icc, done
|
||||
st %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
be,a,pn %icc, done
|
||||
std %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_STRUCT
|
||||
be,pn %icc, dostruct
|
||||
|
||||
cmp %i3, FFI_TYPE_LONGDOUBLE
|
||||
bne,pt %icc, done
|
||||
nop
|
||||
std %f0, [%i4+0]
|
||||
std %f2, [%i4+8]
|
||||
|
||||
done: ret
|
||||
restore
|
||||
|
||||
dostruct:
|
||||
/* This will not work correctly for unions. */
|
||||
stx %o0, [%i4+0]
|
||||
stx %o1, [%i4+8]
|
||||
stx %o2, [%i4+16]
|
||||
stx %o3, [%i4+24]
|
||||
std %f0, [%i4+32]
|
||||
std %f2, [%i4+40]
|
||||
std %f4, [%i4+48]
|
||||
std %f6, [%i4+56]
|
||||
ret
|
||||
restore
|
||||
|
||||
.ffi_call_V9_end:
|
||||
.size ffi_call_V9,.ffi_call_V9_end-ffi_call_V9
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
ffi.c - Copyright (c) 1998, 2001 Red Hat, Inc.
|
||||
|
||||
Alpha Foreign Function Interface
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -37,8 +37,8 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
|
||||
register argument loading area. */
|
||||
if (cif->bytes < 6*SIZEOF_ARG)
|
||||
cif->bytes = 6*SIZEOF_ARG;
|
||||
if (cif->bytes < 6*FFI_SIZEOF_ARG)
|
||||
cif->bytes = 6*FFI_SIZEOF_ARG;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
@@ -73,7 +73,7 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
|
||||
/* Allocate the space for the arguments, plus 4 words of temp
|
||||
space for ffi_call_osf. */
|
||||
argp = stack = alloca(cif->bytes + 4*SIZEOF_ARG);
|
||||
argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
*(void **) argp++ = rvalue;
|
||||
@@ -137,7 +137,7 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argp += ALIGN((*arg_types)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
argp += ALIGN((*arg_types)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++, arg_types++, avalue++;
|
||||
}
|
||||
|
||||
@@ -166,8 +166,13 @@ ffi_prep_closure (ffi_closure* closure,
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the Icache. */
|
||||
asm volatile ("imb" : : : "memory");
|
||||
/* Flush the Icache.
|
||||
|
||||
Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
|
||||
instead, since both Compaq as and gas can handle it.
|
||||
|
||||
0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>. */
|
||||
asm volatile ("call_pal 0x86" : : : "memory");
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
@@ -235,7 +240,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++;
|
||||
}
|
||||
|
||||
48
libffi/src/alpha/ffitarget.h
Normal file
48
libffi/src/alpha/ffitarget.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for Alpha.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_OSF,
|
||||
FFI_DEFAULT_ABI = FFI_OSF,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
osf.S - Copyright (c) 1998 Cygnus Solutions
|
||||
osf.S - Copyright (c) 1998, 2001 Red Hat
|
||||
|
||||
Alpha/OSF Foreign Function Interface
|
||||
|
||||
$Id: osf.S,v 1.5 2008/01/29 12:28:14 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
|
||||
@@ -24,9 +26,9 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
|
||||
|
||||
.arch ev6
|
||||
.text
|
||||
|
||||
@@ -43,12 +45,14 @@
|
||||
ffi_call_osf:
|
||||
.frame $15, 32, $26, 0
|
||||
.mask 0x4008000, -32
|
||||
$LFB1:
|
||||
addq $16,$17,$1
|
||||
mov $16, $30
|
||||
stq $26, 0($1)
|
||||
stq $15, 8($1)
|
||||
stq $18, 16($1)
|
||||
mov $1, $15
|
||||
$LCFI1:
|
||||
.prologue 0
|
||||
|
||||
stq $19, 24($1)
|
||||
@@ -78,6 +82,7 @@ ffi_call_osf:
|
||||
ldq $19, 24($15)
|
||||
ldq $18, 16($15)
|
||||
ldq $26, 0($15)
|
||||
$LCFI2:
|
||||
beq $19, $noretval
|
||||
|
||||
# Store the return value out in the proper type.
|
||||
@@ -88,27 +93,32 @@ ffi_call_osf:
|
||||
cmpeq $18, FFI_TYPE_DOUBLE, $3
|
||||
bne $3, $retdouble
|
||||
|
||||
.align 3
|
||||
$noretval:
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retint:
|
||||
stq $0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retfloat:
|
||||
sts $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retdouble:
|
||||
stt $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
$LFE1:
|
||||
|
||||
.end ffi_call_osf
|
||||
|
||||
@@ -122,9 +132,12 @@ $retdouble:
|
||||
ffi_closure_osf:
|
||||
.frame $30, 16*8, $26, 0
|
||||
.mask 0x4000000, -16*8
|
||||
$LFB2:
|
||||
ldgp $29, 0($27)
|
||||
subq $30, 16*8, $30
|
||||
$LCFI5:
|
||||
stq $26, 0($30)
|
||||
$LCFI6:
|
||||
.prologue 1
|
||||
|
||||
# Store all of the potential argument registers in va_list format.
|
||||
@@ -238,10 +251,15 @@ $load_64:
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
$LFE2:
|
||||
|
||||
.end ffi_closure_osf
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .rodata
|
||||
#else
|
||||
.rdata
|
||||
#endif
|
||||
$load_table:
|
||||
.gprel32 $load_none # FFI_TYPE_VOID
|
||||
.gprel32 $load_32 # FFI_TYPE_INT
|
||||
@@ -276,3 +294,66 @@ $load_table:
|
||||
|| FFI_TYPE_LAST != 14
|
||||
#error "osf.S out of sync with ffi.h"
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte $LECIE1-$LSCIE1 # Length of Common Information Entry
|
||||
$LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 26 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 30 # uleb128 column 30
|
||||
.byte 0 # uleb128 offset 0
|
||||
.align 3
|
||||
$LECIE1:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
|
||||
.4byte $LFB1-. # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI1-$LFB1
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 4 # uleb128 4*-8
|
||||
.byte 0x8f # DW_CFA_offset, column 15
|
||||
.byte 0x3 # uleb128 3*-8
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 15 # uleb128 column 15
|
||||
.byte 32 # uleb128 offset 32
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI1
|
||||
.byte 0xda # DW_CFA_restore, column 26
|
||||
.align 3
|
||||
$LEFDE1:
|
||||
|
||||
$LSFDE3:
|
||||
.4byte $LEFDE3-$LASFDE3 # FDE Length
|
||||
$LASFDE3:
|
||||
.4byte $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
|
||||
.4byte $LFB2-. # FDE initial location
|
||||
.4byte $LFE2-$LFB2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI5-$LFB2
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x80,0x1 # uleb128 128
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI5
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 16 # uleb128 offset 16*-8
|
||||
.align 3
|
||||
$LEFDE3:
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
ffi.c - Copyright (c) 1998 Red Hat, Inc.
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
@@ -24,25 +24,20 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.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 */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register int tmp;
|
||||
register unsigned int avn;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
|
||||
@@ -50,11 +45,10 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0) && (avn != 0);
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
@@ -64,9 +58,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
||||
}
|
||||
|
||||
if (avn != 0)
|
||||
{
|
||||
avn--;
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
@@ -107,7 +98,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -116,6 +106,11 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Round the stack up to a multiple of 8 bytes. This isn't needed
|
||||
everywhere, but it is on some platforms, and it doesn't harm anything
|
||||
when it isn't needed. */
|
||||
cif->bytes = (cif->bytes + 7) & ~7;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
@@ -126,6 +121,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
@@ -134,20 +134,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)());
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
@@ -160,9 +150,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
@@ -171,10 +159,9 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
47
libffi/src/arm/ffitarget.h
Normal file
47
libffi/src/arm/ffitarget.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for ARM.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
209
libffi/src/arm/sysv.S
Normal file
209
libffi/src/arm/sysv.S
Normal file
@@ -0,0 +1,209 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998 Red Hat, Inc.
|
||||
|
||||
ARM 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
/* Use the right prefix for global labels. */
|
||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define LSYM(x) .x
|
||||
#else
|
||||
#define LSYM(x) x
|
||||
#endif
|
||||
|
||||
/* We need a better way of testing for this, but for now, this is all
|
||||
we can do. */
|
||||
@ This selects the minimum architecture level required.
|
||||
#define __ARM_ARCH__ 3
|
||||
|
||||
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 4
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 5
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 6
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH__ >= 5
|
||||
# define call_reg(x) blx x
|
||||
#elif defined (__ARM_ARCH_4T__)
|
||||
# define call_reg(x) mov lr, pc ; bx x
|
||||
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
|
||||
# define __INTERWORKING__
|
||||
# endif
|
||||
#else
|
||||
# define call_reg(x) mov lr, pc ; mov pc, x
|
||||
#endif
|
||||
|
||||
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.thumb
|
||||
.thumb_func
|
||||
ENTRY(\name)
|
||||
bx pc
|
||||
nop
|
||||
.arm
|
||||
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
||||
directly from other local arm routines. */
|
||||
_L__\name:
|
||||
.endm
|
||||
#else
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.arm
|
||||
ENTRY(\name)
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.macro RETLDM regs=, cond=, dirn=ia
|
||||
#if defined (__INTERWORKING__)
|
||||
.ifc "\regs",""
|
||||
ldr\cond lr, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, lr}
|
||||
.endif
|
||||
bx\cond lr
|
||||
#else
|
||||
.ifc "\regs",""
|
||||
ldr\cond pc, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, pc}
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
|
||||
@ r0: ffi_prep_args
|
||||
@ r1: &ecif
|
||||
@ r2: cif->bytes
|
||||
@ r3: fig->flags
|
||||
@ sp+0: ecif.rvalue
|
||||
@ sp+4: fn
|
||||
|
||||
@ This assumes we are using gas.
|
||||
ARM_FUNC_START ffi_call_SYSV
|
||||
@ Save registers
|
||||
stmfd sp!, {r0-r3, fp, lr}
|
||||
mov fp, sp
|
||||
|
||||
@ Make room for all of the new args.
|
||||
sub sp, fp, r2
|
||||
|
||||
@ Place all of the ffi_prep_args in position
|
||||
mov ip, r0
|
||||
mov r0, sp
|
||||
@ r1 already set
|
||||
|
||||
@ Call ffi_prep_args(stack, &ecif)
|
||||
call_reg(ip)
|
||||
|
||||
@ move first 4 parameters in registers
|
||||
ldmia sp, {r0-r3}
|
||||
|
||||
@ and adjust stack
|
||||
ldr ip, [fp, #8]
|
||||
cmp ip, #16
|
||||
movhs ip, #16
|
||||
add sp, sp, ip
|
||||
|
||||
@ call (fn) (...)
|
||||
ldr ip, [fp, #28]
|
||||
call_reg(ip)
|
||||
|
||||
@ Remove the space we pushed for the args
|
||||
mov sp, fp
|
||||
|
||||
@ Load r2 with the pointer to storage for the return value
|
||||
ldr r2, [sp, #24]
|
||||
|
||||
@ Load r3 with the return type code
|
||||
ldr r3, [sp, #12]
|
||||
|
||||
@ If the return value pointer is NULL, assume no return value.
|
||||
cmp r2, #0
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT
|
||||
cmp r3, #FFI_TYPE_INT
|
||||
#ifdef __SOFTFP__
|
||||
cmpne r3, #FFI_TYPE_FLOAT
|
||||
#endif
|
||||
streq r0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT64
|
||||
cmp r3, #FFI_TYPE_SINT64
|
||||
#ifdef __SOFTFP__
|
||||
cmpne r3, #FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
stmeqia r2, {r0, r1}
|
||||
|
||||
#ifndef __SOFTFP__
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return FLOAT
|
||||
cmp r3, #FFI_TYPE_FLOAT
|
||||
stfeqs f0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return DOUBLE or LONGDOUBLE
|
||||
cmp r3, #FFI_TYPE_DOUBLE
|
||||
stfeqd f0, [r2]
|
||||
#endif
|
||||
|
||||
LSYM(Lepilogue):
|
||||
RETLDM "r0-r3,fp"
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
381
libffi/src/cris/ffi.c
Normal file
381
libffi/src/cris/ffi.c
Normal file
@@ -0,0 +1,381 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
|
||||
CRIS 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 SIMON POSNJAK 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>
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
static ffi_status
|
||||
initialize_aggregate_packed_struct (ffi_type * arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT (arg != NULL);
|
||||
|
||||
FFI_ASSERT (arg->elements != NULL);
|
||||
FFI_ASSERT (arg->size == 0);
|
||||
FFI_ASSERT (arg->alignment == 0);
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0)
|
||||
&& (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT (ffi_type_test ((*ptr)));
|
||||
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_prep_args (char *stack, extended_cif * ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int struct_count = 0;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
if (z <= 4)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
z = 4;
|
||||
}
|
||||
else if (z <= 8)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
z = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int uiLocOnStack;
|
||||
z = sizeof (void *);
|
||||
uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
|
||||
struct_count = struct_count + (*p_arg)->size;
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) (UINT32 *) (stack + uiLocOnStack);
|
||||
memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) *(UINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp =
|
||||
(unsigned int) *(UINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
z = sizeof (int);
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
|
||||
else
|
||||
memcpy (argp, *p_argv, z);
|
||||
break;
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return (struct_count);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif (ffi_cif * cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
ffi_type * rtype, ffi_type ** atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT (cif != NULL);
|
||||
FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
if ((cif->rtype->size == 0)
|
||||
&& (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT_VALID_TYPE (cif->rtype);
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
if (((*ptr)->size == 0)
|
||||
&& (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
FFI_ASSERT_VALID_TYPE (*ptr);
|
||||
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN (bytes, (*ptr)->alignment);
|
||||
if ((*ptr)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if ((*ptr)->size > 8)
|
||||
{
|
||||
bytes += (*ptr)->size;
|
||||
bytes += sizeof (void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*ptr)->size > 4)
|
||||
bytes += 8;
|
||||
else
|
||||
bytes += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
bytes += STACK_ARG_SIZE ((*ptr)->size);
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
return ffi_prep_cif_machdep (cif);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif * cif)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn) ())
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Because the following variables are not exported outside libffi, we
|
||||
mark them hidden. */
|
||||
|
||||
/* Assembly code for the jump stub. */
|
||||
extern const char ffi_cris_trampoline_template[]
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* Offset into ffi_cris_trampoline_template of where to put the
|
||||
ffi_prep_closure_inner function. */
|
||||
extern const int ffi_cris_trampoline_fn_offset
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* Offset into ffi_cris_trampoline_template of where to put the
|
||||
closure data. */
|
||||
extern const int ffi_cris_trampoline_closure_offset
|
||||
__attribute__ ((__visibility__ ("hidden")));
|
||||
|
||||
/* This function is sibling-called (jumped to) by the closure
|
||||
trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
|
||||
PARAMS[4] to simplify handling of a straddling parameter. A copy
|
||||
of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are
|
||||
put at the appropriate place in CLOSURE which is then executed and
|
||||
the return value is passed back to the caller. */
|
||||
|
||||
static unsigned long long
|
||||
ffi_prep_closure_inner (void **params, ffi_closure* closure)
|
||||
{
|
||||
char *register_args = (char *) params;
|
||||
void *struct_ret = params[5];
|
||||
char *stack_args = params[6];
|
||||
char *ptr = register_args;
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
|
||||
/* Max room needed is number of arguments as 64-bit values. */
|
||||
void **avalue = alloca (closure->cif->nargs * sizeof(void *));
|
||||
int i;
|
||||
int doing_regs;
|
||||
long long llret = 0;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0, doing_regs = 1; i < cif->nargs; i++)
|
||||
{
|
||||
/* Types up to and including 8 bytes go by-value. */
|
||||
if (arg_types[i]->size <= 4)
|
||||
{
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
else if (arg_types[i]->size <= 8)
|
||||
{
|
||||
avalue[i] = ptr;
|
||||
ptr += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
|
||||
|
||||
/* Passed by-reference, so copy the pointer. */
|
||||
avalue[i] = *(void **) ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
/* If we've handled more arguments than fit in registers, start
|
||||
looking at the those passed on the stack. Step over the
|
||||
first one if we had a straddling parameter. */
|
||||
if (doing_regs && ptr >= register_args + 4*4)
|
||||
{
|
||||
ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
|
||||
doing_regs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif,
|
||||
|
||||
cif->rtype->type == FFI_TYPE_STRUCT
|
||||
/* The caller allocated space for the return
|
||||
structure, and passed a pointer to this space in
|
||||
R9. */
|
||||
? struct_ret
|
||||
|
||||
/* We take advantage of being able to ignore that
|
||||
the high part isn't set if the return value is
|
||||
not in R10:R11, but in R10 only. */
|
||||
: (void *) &llret,
|
||||
|
||||
avalue, closure->user_data);
|
||||
|
||||
return llret;
|
||||
}
|
||||
|
||||
/* API function: Prepare the trampoline. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void*),
|
||||
void *user_data)
|
||||
{
|
||||
void *innerfn = ffi_prep_closure_inner;
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
memcpy (closure->tramp, ffi_cris_trampoline_template,
|
||||
FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
|
||||
&innerfn, sizeof (void *));
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
|
||||
&closure, sizeof (void *));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
50
libffi/src/cris/ffitarget.h
Normal file
50
libffi/src/cris/ffitarget.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for CRIS.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE 36
|
||||
#define FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE (7*4)
|
||||
#define FFI_TRAMPOLINE_SIZE \
|
||||
(FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE + FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE)
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
215
libffi/src/cris/sysv.S
Normal file
215
libffi/src/cris/sysv.S
Normal file
@@ -0,0 +1,215 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
|
||||
CRIS 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 SIMON POSNJAK 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 CONCAT(x,y) x ## y
|
||||
#define XCONCAT(x,y) CONCAT (x, y)
|
||||
#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
|
||||
|
||||
.text
|
||||
|
||||
;; OK, when we get called we should have this (according to
|
||||
;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
|
||||
;;
|
||||
;; R10: ffi_prep_args (func. pointer)
|
||||
;; R11: &ecif
|
||||
;; R12: cif->bytes
|
||||
;; R13: fig->flags
|
||||
;; sp+0: ecif.rvalue
|
||||
;; sp+4: fn (function pointer to the function that we need to call)
|
||||
|
||||
.globl L(ffi_call_SYSV)
|
||||
.type L(ffi_call_SYSV),@function
|
||||
.hidden L(ffi_call_SYSV)
|
||||
|
||||
L(ffi_call_SYSV):
|
||||
;; Save the regs to the stack.
|
||||
push $srp
|
||||
;; Used for stack pointer saving.
|
||||
push $r6
|
||||
;; Used for function address pointer.
|
||||
push $r7
|
||||
;; Used for stack pointer saving.
|
||||
push $r8
|
||||
;; We save fig->flags to stack we will need them after we
|
||||
;; call The Function.
|
||||
push $r13
|
||||
|
||||
;; Saving current stack pointer.
|
||||
move.d $sp,$r8
|
||||
move.d $sp,$r6
|
||||
|
||||
;; Move address of ffi_prep_args to r13.
|
||||
move.d $r10,$r13
|
||||
|
||||
;; Make room on the stack for the args of fn.
|
||||
sub.d $r12,$sp
|
||||
|
||||
;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
|
||||
;; r10 <-- stack pointer
|
||||
;; r11 <-- &ecif (already there)
|
||||
move.d $sp,$r10
|
||||
|
||||
;; Call the function.
|
||||
jsr $r13
|
||||
|
||||
;; Save the size of the structures which are passed on stack.
|
||||
move.d $r10,$r7
|
||||
|
||||
;; Move first four args in to r10..r13.
|
||||
move.d [$sp+0],$r10
|
||||
move.d [$sp+4],$r11
|
||||
move.d [$sp+8],$r12
|
||||
move.d [$sp+12],$r13
|
||||
|
||||
;; Adjust the stack and check if any parameters are given on stack.
|
||||
addq 16,$sp
|
||||
sub.d $r7,$r6
|
||||
cmp.d $sp,$r6
|
||||
|
||||
bpl go_on
|
||||
nop
|
||||
|
||||
go_on_no_params_on_stack:
|
||||
move.d $r6,$sp
|
||||
|
||||
go_on:
|
||||
;; Discover if we need to put rval address in to r9.
|
||||
move.d [$r8+0],$r7
|
||||
cmpq FFI_TYPE_STRUCT,$r7
|
||||
bne call_now
|
||||
nop
|
||||
|
||||
;; Move rval address to $r9.
|
||||
move.d [$r8+20],$r9
|
||||
|
||||
call_now:
|
||||
;; Move address of The Function in to r7.
|
||||
move.d [$r8+24],$r7
|
||||
|
||||
;; Call The Function.
|
||||
jsr $r7
|
||||
|
||||
;; Reset stack.
|
||||
move.d $r8,$sp
|
||||
|
||||
;; Load rval type (fig->flags) in to r13.
|
||||
pop $r13
|
||||
|
||||
;; Detect rval type.
|
||||
cmpq FFI_TYPE_VOID,$r13
|
||||
beq epilogue
|
||||
|
||||
cmpq FFI_TYPE_STRUCT,$r13
|
||||
beq epilogue
|
||||
|
||||
cmpq FFI_TYPE_DOUBLE,$r13
|
||||
beq return_double_or_longlong
|
||||
|
||||
cmpq FFI_TYPE_UINT64,$r13
|
||||
beq return_double_or_longlong
|
||||
|
||||
cmpq FFI_TYPE_SINT64,$r13
|
||||
beq return_double_or_longlong
|
||||
nop
|
||||
|
||||
;; Just return the 32 bit value.
|
||||
ba return
|
||||
nop
|
||||
|
||||
return_double_or_longlong:
|
||||
;; Load half of the rval to r10 and the other half to r11.
|
||||
move.d [$sp+16],$r13
|
||||
move.d $r10,[$r13]
|
||||
addq 4,$r13
|
||||
move.d $r11,[$r13]
|
||||
ba epilogue
|
||||
nop
|
||||
|
||||
return:
|
||||
;; Load the rval to r10.
|
||||
move.d [$sp+16],$r13
|
||||
move.d $r10,[$r13]
|
||||
|
||||
epilogue:
|
||||
pop $r8
|
||||
pop $r7
|
||||
pop $r6
|
||||
Jump [$sp+]
|
||||
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
/* Save R10..R13 into an array, somewhat like varargs. Copy the next
|
||||
argument too, to simplify handling of any straddling parameter.
|
||||
Save R9 and SP after those. Jump to function handling the rest.
|
||||
Since this is a template, copied and the main function filled in by
|
||||
the user. */
|
||||
|
||||
.globl L(ffi_cris_trampoline_template)
|
||||
.type L(ffi_cris_trampoline_template),@function
|
||||
.hidden L(ffi_cris_trampoline_template)
|
||||
|
||||
L(ffi_cris_trampoline_template):
|
||||
0:
|
||||
/* The value we get for "PC" is right after the prefix instruction,
|
||||
two bytes from the beginning, i.e. 0b+2. */
|
||||
move.d $r10,[$pc+2f-(0b+2)]
|
||||
move.d $pc,$r10
|
||||
1:
|
||||
addq 2f-1b+4,$r10
|
||||
move.d $r11,[$r10+]
|
||||
move.d $r12,[$r10+]
|
||||
move.d $r13,[$r10+]
|
||||
move.d [$sp],$r11
|
||||
move.d $r11,[$r10+]
|
||||
move.d $r9,[$r10+]
|
||||
move.d $sp,[$r10+]
|
||||
subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
|
||||
move.d 0,$r11
|
||||
3:
|
||||
jump 0
|
||||
2:
|
||||
.size ffi_cris_trampoline_template,.-0b
|
||||
|
||||
/* This macro create a constant usable as "extern const int \name" in
|
||||
C from within libffi, when \name has no prefix decoration. */
|
||||
|
||||
.macro const name,value
|
||||
.globl \name
|
||||
.type \name,@object
|
||||
.hidden \name
|
||||
\name:
|
||||
.dword \value
|
||||
.size \name,4
|
||||
.endm
|
||||
|
||||
/* Constants for offsets within the trampoline. We could do this with
|
||||
just symbols, avoiding memory contents and memory accesses, but the
|
||||
C usage code would look a bit stranger. */
|
||||
|
||||
const L(ffi_cris_trampoline_fn_offset),2b-4-0b
|
||||
const L(ffi_cris_trampoline_closure_offset),3b-4-0b
|
||||
@@ -15,14 +15,14 @@
|
||||
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 RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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_private.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -31,35 +31,28 @@
|
||||
void ffi_stop_here(void)
|
||||
{
|
||||
/* This function is only useful for debugging purposes.
|
||||
Place a breakpoint on ffi_stop_here to be notified of
|
||||
Place a breakpoint on ffi_stop_here to be notified of
|
||||
significant events. */
|
||||
}
|
||||
|
||||
/* This function should only be called via the FFI_ASSERT() macro */
|
||||
|
||||
int ffi_assert(char *file, int line)
|
||||
void ffi_assert(char *expr, char *file, int line)
|
||||
{
|
||||
fprintf(stderr, "ASSERTION FAILURE: %s line %d\n", file, line);
|
||||
fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
|
||||
ffi_stop_here();
|
||||
abort();
|
||||
|
||||
/* This has to return something for the compiler not to complain */
|
||||
/*@notreached@*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform a sanity check on an ffi_type structure */
|
||||
|
||||
bool ffi_type_test(ffi_type *a)
|
||||
void ffi_type_test(ffi_type *a, char *file, int line)
|
||||
{
|
||||
/*@-usedef@*/
|
||||
FFI_ASSERT(a->type <= FFI_TYPE_LAST);
|
||||
FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->size > 0 : 1);
|
||||
FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->alignment > 0 : 1);
|
||||
FFI_ASSERT(a->type == FFI_TYPE_STRUCT ? a->elements != NULL : 1);
|
||||
/*@=usedef@*/
|
||||
FFI_ASSERT_AT(a != NULL, file, line);
|
||||
|
||||
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
|
||||
|
||||
/* This is a silly thing to return, but it keeps the compiler from
|
||||
issuing warnings about "a" not being used in non-debug builds. */
|
||||
return (a != NULL);
|
||||
}
|
||||
130
libffi/src/frv/eabi.S
Normal file
130
libffi/src/frv/eabi.S
Normal file
@@ -0,0 +1,130 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
eabi.S - Copyright (c) 2004 Anthony Green
|
||||
|
||||
FR-V Assembly glue.
|
||||
|
||||
$Id: eabi.S,v 1.2 2008/01/29 12:28:14 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 THE AUTHOR 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.globl ffi_prep_args_EABI
|
||||
|
||||
.text
|
||||
.p2align 4
|
||||
.globl ffi_call_EABI
|
||||
.type ffi_call_EABI, @function
|
||||
|
||||
# gr8 : ffi_prep_args
|
||||
# gr9 : &ecif
|
||||
# gr10: cif->bytes
|
||||
# gr11: fig->flags
|
||||
# gr12: ecif.rvalue
|
||||
# gr13: fn
|
||||
|
||||
ffi_call_EABI:
|
||||
addi sp, #-80, sp
|
||||
sti fp, @(sp, #24)
|
||||
addi sp, #24, fp
|
||||
movsg lr, gr5
|
||||
|
||||
/* Make room for the new arguments. */
|
||||
/* subi sp, fp, gr10 */
|
||||
|
||||
/* Store return address and incoming args on stack. */
|
||||
sti gr5, @(fp, #8)
|
||||
sti gr8, @(fp, #-4)
|
||||
sti gr9, @(fp, #-8)
|
||||
sti gr10, @(fp, #-12)
|
||||
sti gr11, @(fp, #-16)
|
||||
sti gr12, @(fp, #-20)
|
||||
sti gr13, @(fp, #-24)
|
||||
|
||||
sub sp, gr10, sp
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
ldi @(fp, #-4), gr4
|
||||
addi sp, #0, gr8
|
||||
ldi @(fp, #-8), gr9
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* ffi_prep_args returns the new stack pointer. */
|
||||
mov gr8, gr4
|
||||
|
||||
ldi @(sp, #0), gr8
|
||||
ldi @(sp, #4), gr9
|
||||
ldi @(sp, #8), gr10
|
||||
ldi @(sp, #12), gr11
|
||||
ldi @(sp, #16), gr12
|
||||
ldi @(sp, #20), gr13
|
||||
|
||||
/* Always copy the return value pointer into the hidden
|
||||
parameter register. This is only strictly necessary
|
||||
when we're returning an aggregate type, but it doesn't
|
||||
hurt to do this all the time, and it saves a branch. */
|
||||
ldi @(fp, #-20), gr3
|
||||
|
||||
/* Use the ffi_prep_args return value for the new sp. */
|
||||
mov gr4, sp
|
||||
|
||||
/* Call the target function. */
|
||||
ldi @(fp, -24), gr4
|
||||
#ifdef __FRV_FDPIC__
|
||||
ldd @(gr4, gr0), gr14
|
||||
calll @(gr14, gr0)
|
||||
#else
|
||||
calll @(gr4, gr0)
|
||||
#endif
|
||||
|
||||
/* Store the result. */
|
||||
ldi @(fp, #-16), gr10 /* fig->flags */
|
||||
ldi @(fp, #-20), gr4 /* ecif.rvalue */
|
||||
|
||||
/* Is the return value stored in two registers? */
|
||||
cmpi gr10, #8, icc0
|
||||
bne icc0, 0, .L2
|
||||
/* Yes, save them. */
|
||||
sti gr8, @(gr4, #0)
|
||||
sti gr9, @(gr4, #4)
|
||||
bra .L3
|
||||
.L2:
|
||||
/* Is the return value a structure? */
|
||||
cmpi gr10, #-1, icc0
|
||||
beq icc0, 0, .L3
|
||||
/* No, save a 4 byte return value. */
|
||||
sti gr8, @(gr4, #0)
|
||||
.L3:
|
||||
|
||||
/* Restore the stack, and return. */
|
||||
ldi @(fp, 8), gr5
|
||||
ld @(fp, gr0), fp
|
||||
addi sp,#80,sp
|
||||
jmpl @(gr5,gr0)
|
||||
.size ffi_call_EABI, .-ffi_call_EABI
|
||||
|
||||
287
libffi/src/frv/ffi.c
Normal file
287
libffi/src/frv/ffi.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2004 Anthony Green
|
||||
|
||||
FR-V 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>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
register int count = 0;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
argp = stack;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
z = sizeof(void*);
|
||||
*(void **) argp = *p_argv;
|
||||
}
|
||||
/* if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (count > 24)
|
||||
{
|
||||
// This is going on the stack. Turn it into a double.
|
||||
*(double *) argp = (double) *(float*)(* p_argv);
|
||||
z = sizeof(double);
|
||||
}
|
||||
else
|
||||
*(void **) argp = *(void **)(* p_argv);
|
||||
} */
|
||||
else if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
count += z;
|
||||
}
|
||||
|
||||
return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
cif->flags = -1;
|
||||
else
|
||||
cif->flags = cif->rtype->size;
|
||||
|
||||
cif->bytes = ALIGN (cif->bytes, 8);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
|
||||
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_EABI:
|
||||
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
|
||||
unsigned arg4, unsigned arg5, unsigned arg6)
|
||||
{
|
||||
/* This function is called by a trampoline. The trampoline stows a
|
||||
pointer to the ffi_closure object in gr7. We must save this
|
||||
pointer in a place that will persist while we do our work. */
|
||||
register ffi_closure *creg __asm__ ("gr7");
|
||||
ffi_closure *closure = creg;
|
||||
|
||||
/* Arguments that don't fit in registers are found on the stack
|
||||
at a fixed offset above the current frame pointer. */
|
||||
register char *frame_pointer __asm__ ("fp");
|
||||
char *stack_args = frame_pointer + 16;
|
||||
|
||||
/* Lay the register arguments down in a continuous chunk of memory. */
|
||||
unsigned register_args[6] =
|
||||
{ arg1, arg2, arg3, arg4, arg5, arg6 };
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
void **avalue = alloca (cif->nargs * sizeof(void *));
|
||||
char *ptr = (char *) register_args;
|
||||
int i;
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = ptr + 3;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = ptr + 2;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = *(void**)ptr;
|
||||
break;
|
||||
default:
|
||||
/* This is an 8-byte value. */
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
break;
|
||||
}
|
||||
ptr += 4;
|
||||
|
||||
/* If we've handled more arguments than fit in registers,
|
||||
start looking at the those passed on the stack. */
|
||||
if (ptr == ((char *)register_args + (6*4)))
|
||||
ptr = stack_args;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* The caller allocates space for the return structure, and
|
||||
passes a pointer to this space in gr3. Use this value directly
|
||||
as the return value. */
|
||||
register void *return_struct_ptr __asm__("gr3");
|
||||
(closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for the return value and call the function. */
|
||||
long long rvalue;
|
||||
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Functions return 4-byte or smaller results in gr8. 8-byte
|
||||
values also use gr9. We fill the both, even for small return
|
||||
values, just to avoid a branch. */
|
||||
asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue));
|
||||
asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn = (long) ffi_closure_eabi;
|
||||
unsigned long cls = (long) closure;
|
||||
#ifdef __FRV_FDPIC__
|
||||
register void *got __asm__("gr15");
|
||||
#endif
|
||||
int i;
|
||||
|
||||
fn = (unsigned long) ffi_closure_eabi;
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
tramp[0] = &tramp[2];
|
||||
tramp[1] = got;
|
||||
tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[4] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[5] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[6] = 0x9cc86000; /* ldi @(gr6, #0), gr14 */
|
||||
tramp[7] = 0x8030e000; /* jmpl @(gr14, gr0) */
|
||||
#else
|
||||
tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
|
||||
tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
|
||||
tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Cache flushing. */
|
||||
for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
|
||||
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%0,%1)" :: "r" (tramp), "r" (i));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
60
libffi/src/frv/ffitarget.h
Normal file
60
libffi/src/frv/ffitarget.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2004 Red Hat, Inc.
|
||||
Target configuration macros for FR-V
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef FRV
|
||||
FFI_EABI,
|
||||
FFI_DEFAULT_ABI = FFI_EABI,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
/* Trampolines are 8 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (8*4)
|
||||
#else
|
||||
/* Trampolines are 5 4-byte instructions long. */
|
||||
#define FFI_TRAMPOLINE_SIZE (5*4)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
578
libffi/src/ia64/ffi.c
Normal file
578
libffi/src/ia64/ffi.c
Normal file
@@ -0,0 +1,578 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Red Hat, Inc.
|
||||
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 <stdbool.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "ia64_flags.h"
|
||||
|
||||
/* A 64-bit pointer value. In LP64 mode, this is effectively a plain
|
||||
pointer. In ILP32 mode, it's a pointer that's been extended to
|
||||
64 bits by "addp4". */
|
||||
typedef void *PTR64 __attribute__((mode(DI)));
|
||||
|
||||
/* Memory image of fp register contents. This is the implementation
|
||||
specific format used by ldf.fill/stf.spill. All we care about is
|
||||
that it wants a 16 byte aligned slot. */
|
||||
typedef struct
|
||||
{
|
||||
UINT64 x[2] __attribute__((aligned(16)));
|
||||
} fpreg;
|
||||
|
||||
|
||||
/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */
|
||||
|
||||
struct ia64_args
|
||||
{
|
||||
fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */
|
||||
UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */
|
||||
UINT64 other_args[]; /* Arguments passed on stack, variable size. */
|
||||
};
|
||||
|
||||
|
||||
/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */
|
||||
|
||||
static inline void *
|
||||
endian_adjust (void *addr, size_t len)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
return addr + (8 - len);
|
||||
#else
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
|
||||
This is a macro instead of a function, so that it works for all 3 floating
|
||||
point types without type conversions. Type conversion to long double breaks
|
||||
the denorm support. */
|
||||
|
||||
#define stf_spill(addr, value) \
|
||||
asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
|
||||
|
||||
/* Load a value from ADDR, which is in the current cpu implementation's
|
||||
fp spill format. As above, this must also be a macro. */
|
||||
|
||||
#define ldf_fill(result, addr) \
|
||||
asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
|
||||
|
||||
/* Return the size of the C type associated with with TYPE. Which will
|
||||
be one of the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static size_t
|
||||
hfa_type_size (int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
return sizeof(float);
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
return sizeof(double);
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
return sizeof(__float80);
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load from ADDR a value indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_load (fpreg *fpaddr, int type, void *addr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
stf_spill (fpaddr, *(float *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
stf_spill (fpaddr, *(double *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
stf_spill (fpaddr, *(__float80 *) addr);
|
||||
return;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load VALUE into ADDR as indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_store (int type, void *addr, fpreg *fpaddr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
{
|
||||
float result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(float *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
{
|
||||
double result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(double *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
{
|
||||
__float80 result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(__float80 *) addr = result;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Is TYPE a struct containing floats, doubles, or extended doubles,
|
||||
all of the same fp type? If so, return the element type. Return
|
||||
FFI_TYPE_VOID if not. */
|
||||
|
||||
static int
|
||||
hfa_element_type (ffi_type *type, int nested)
|
||||
{
|
||||
int element = FFI_TYPE_VOID;
|
||||
|
||||
switch (type->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* We want to return VOID for raw floating-point types, but the
|
||||
synthetic HFA type if we're nested within an aggregate. */
|
||||
if (nested)
|
||||
element = FFI_IA64_TYPE_HFA_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Similarly. */
|
||||
if (nested)
|
||||
element = FFI_IA64_TYPE_HFA_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Similarly, except that that HFA is true for double extended,
|
||||
but not quad precision. Both have sizeof == 16, so tell the
|
||||
difference based on the precision. */
|
||||
if (LDBL_MANT_DIG == 64 && nested)
|
||||
element = FFI_IA64_TYPE_HFA_LDOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
ffi_type **ptr = &type->elements[0];
|
||||
|
||||
for (ptr = &type->elements[0]; *ptr ; ptr++)
|
||||
{
|
||||
int sub_element = hfa_element_type (*ptr, 1);
|
||||
if (sub_element == FFI_TYPE_VOID)
|
||||
return FFI_TYPE_VOID;
|
||||
|
||||
if (element == FFI_TYPE_VOID)
|
||||
element = sub_element;
|
||||
else if (element != sub_element)
|
||||
return FFI_TYPE_VOID;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FFI_TYPE_VOID;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int flags;
|
||||
|
||||
/* Adjust cif->bytes to include space for the bits of the ia64_args frame
|
||||
that preceeds the integer register portion. The estimate that the
|
||||
generic bits did for the argument space required is good enough for the
|
||||
integer component. */
|
||||
cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
|
||||
if (cif->bytes < sizeof(struct ia64_args))
|
||||
cif->bytes = sizeof(struct ia64_args);
|
||||
|
||||
/* Set the return type flag. */
|
||||
flags = cif->rtype->type;
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
|
||||
and encode quad precision as a two-word integer structure. */
|
||||
if (LDBL_MANT_DIG != 64)
|
||||
flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = cif->rtype->size;
|
||||
int hfa_type = hfa_element_type (cif->rtype, 0);
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t nelts = size / hfa_type_size (hfa_type);
|
||||
if (nelts <= 8)
|
||||
flags = hfa_type | (size << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size <= 32)
|
||||
flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cif->flags = flags;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(), UINT64);
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
struct ia64_args *stack;
|
||||
long i, avn, gpcount, fpcount;
|
||||
ffi_type **p_arg;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
/* If we have no spot for a return value, make one. */
|
||||
if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
|
||||
rvalue = alloca (cif->rtype->size);
|
||||
|
||||
/* Allocate the stack frame. */
|
||||
stack = alloca (cif->bytes);
|
||||
|
||||
gpcount = fpcount = 0;
|
||||
avn = cif->nargs;
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_UINT32:
|
||||
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
|
||||
stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
|
||||
stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (gpcount & 1)
|
||||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
|
||||
memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
|
||||
gpcount += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
size_t align = (*p_arg)->alignment;
|
||||
int hfa_type = hfa_element_type (*p_arg, 0);
|
||||
|
||||
FFI_ASSERT (align <= 16);
|
||||
if (align == 16 && (gpcount & 1))
|
||||
gpcount++;
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t hfa_size = hfa_type_size (hfa_type);
|
||||
size_t offset = 0;
|
||||
size_t gp_offset = gpcount * 8;
|
||||
|
||||
while (fpcount < 8
|
||||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
|
||||
avalue[i] + offset);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (&stack->gp_regs[gpcount], avalue[i], size);
|
||||
gpcount += (size + 7) / 8;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
ffi_call_unix (stack, rvalue, fn, cif->flags);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
||||
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. */
|
||||
|
||||
extern void ffi_closure_unix ();
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
/* The layout of a function descriptor. A C function pointer really
|
||||
points to one of these. */
|
||||
struct ia64_fd
|
||||
{
|
||||
UINT64 code_pointer;
|
||||
UINT64 gp;
|
||||
};
|
||||
|
||||
struct ffi_ia64_trampoline_struct
|
||||
{
|
||||
UINT64 code_pointer; /* Pointer to ffi_closure_unix. */
|
||||
UINT64 fake_gp; /* Pointer to closure, installed as gp. */
|
||||
UINT64 real_gp; /* Real gp value. */
|
||||
};
|
||||
|
||||
struct ffi_ia64_trampoline_struct *tramp;
|
||||
struct ia64_fd *fd;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX);
|
||||
|
||||
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
|
||||
fd = (struct ia64_fd *)(void *)ffi_closure_unix;
|
||||
|
||||
tramp->code_pointer = fd->code_pointer;
|
||||
tramp->real_gp = fd->gp;
|
||||
tramp->fake_gp = (UINT64)(PTR64)closure;
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
UINT64
|
||||
ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
||||
void *rvalue, void *r8)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **p_arg;
|
||||
long i, avn, gpcount, fpcount;
|
||||
|
||||
cif = closure->cif;
|
||||
avn = cif->nargs;
|
||||
avalue = alloca (avn * sizeof (void *));
|
||||
|
||||
/* If the structure return value is passed in memory get that location
|
||||
from r8 so as to pass the value directly back to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = r8;
|
||||
|
||||
gpcount = fpcount = 0;
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
avalue[i] = &stack->gp_regs[gpcount++];
|
||||
break;
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
float result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(float *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
|
||||
gpcount++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
double result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(double *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
gpcount++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (gpcount & 1)
|
||||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
__float80 result;
|
||||
avalue[i] = addr;
|
||||
ldf_fill (result, addr);
|
||||
*(__float80 *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
gpcount += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
size_t align = (*p_arg)->alignment;
|
||||
int hfa_type = hfa_element_type (*p_arg, 0);
|
||||
|
||||
FFI_ASSERT (align <= 16);
|
||||
if (align == 16 && (gpcount & 1))
|
||||
gpcount++;
|
||||
|
||||
if (hfa_type != FFI_TYPE_VOID)
|
||||
{
|
||||
size_t hfa_size = hfa_type_size (hfa_type);
|
||||
size_t offset = 0;
|
||||
size_t gp_offset = gpcount * 8;
|
||||
void *addr = alloca (size);
|
||||
|
||||
avalue[i] = addr;
|
||||
|
||||
while (fpcount < 8
|
||||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_store (hfa_type, addr + offset,
|
||||
&stack->fp_regs[fpcount]);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
}
|
||||
|
||||
if (offset < size)
|
||||
memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
|
||||
size - offset);
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
|
||||
gpcount += (size + 7) / 8;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
49
libffi/src/ia64/ffitarget.h
Normal file
49
libffi/src/ia64/ffitarget.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for IA-64.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef signed long long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_UNIX, /* Linux and all Unix variants use the same conventions */
|
||||
FFI_DEFAULT_ABI = FFI_UNIX,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */
|
||||
/* can be interpreted as a C function */
|
||||
/* descriptor: */
|
||||
|
||||
#endif
|
||||
|
||||
39
libffi/src/ia64/ia64_flags.h
Normal file
39
libffi/src/ia64/ia64_flags.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* "Type" codes used between assembly and C. When used as a part of
|
||||
a cfi->flags value, the low byte will be these extra type codes,
|
||||
and bits 8-31 will be the actual size of the type. */
|
||||
|
||||
/* Small structures containing N words in integer registers. */
|
||||
#define FFI_IA64_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 1)
|
||||
|
||||
/* Homogeneous Floating Point Aggregates (HFAs) which are returned
|
||||
in FP registers. */
|
||||
#define FFI_IA64_TYPE_HFA_FLOAT (FFI_TYPE_LAST + 2)
|
||||
#define FFI_IA64_TYPE_HFA_DOUBLE (FFI_TYPE_LAST + 3)
|
||||
#define FFI_IA64_TYPE_HFA_LDOUBLE (FFI_TYPE_LAST + 4)
|
||||
555
libffi/src/ia64/unix.S
Normal file
555
libffi/src/ia64/unix.S
Normal file
@@ -0,0 +1,555 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
unix.S - Copyright (c) 1998 Red Hat, Inc.
|
||||
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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include "ia64_flags.h"
|
||||
|
||||
.pred.safe_across_calls p1-p5,p16-p63
|
||||
.text
|
||||
|
||||
/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
|
||||
void (*fn)(), int flags);
|
||||
*/
|
||||
|
||||
.align 16
|
||||
.global ffi_call_unix
|
||||
.proc ffi_call_unix
|
||||
ffi_call_unix:
|
||||
.prologue
|
||||
/* Bit o trickiness. We actually share a stack frame with ffi_call.
|
||||
Rely on the fact that ffi_call uses a vframe and don't bother
|
||||
tracking one here at all. */
|
||||
.fframe 0
|
||||
.save ar.pfs, r36 // loc0
|
||||
alloc loc0 = ar.pfs, 4, 3, 8, 0
|
||||
.save rp, loc1
|
||||
mov loc1 = b0
|
||||
.body
|
||||
add r16 = 16, in0
|
||||
mov loc2 = gp
|
||||
mov r8 = in1
|
||||
;;
|
||||
|
||||
/* Load up all of the argument registers. */
|
||||
ldf.fill f8 = [in0], 32
|
||||
ldf.fill f9 = [r16], 32
|
||||
;;
|
||||
ldf.fill f10 = [in0], 32
|
||||
ldf.fill f11 = [r16], 32
|
||||
;;
|
||||
ldf.fill f12 = [in0], 32
|
||||
ldf.fill f13 = [r16], 32
|
||||
;;
|
||||
ldf.fill f14 = [in0], 32
|
||||
ldf.fill f15 = [r16], 24
|
||||
;;
|
||||
ld8 out0 = [in0], 16
|
||||
ld8 out1 = [r16], 16
|
||||
;;
|
||||
ld8 out2 = [in0], 16
|
||||
ld8 out3 = [r16], 16
|
||||
;;
|
||||
ld8 out4 = [in0], 16
|
||||
ld8 out5 = [r16], 16
|
||||
;;
|
||||
ld8 out6 = [in0]
|
||||
ld8 out7 = [r16]
|
||||
;;
|
||||
|
||||
/* Deallocate the register save area from the stack frame. */
|
||||
mov sp = in0
|
||||
|
||||
/* Call the target function. */
|
||||
ld8 r16 = [in2], 8
|
||||
;;
|
||||
ld8 gp = [in2]
|
||||
mov b6 = r16
|
||||
br.call.sptk.many b0 = b6
|
||||
;;
|
||||
|
||||
/* Dispatch to handle return value. */
|
||||
mov gp = loc2
|
||||
zxt1 r16 = in3
|
||||
;;
|
||||
mov ar.pfs = loc0
|
||||
addl r18 = @ltoffx(.Lst_table), gp
|
||||
;;
|
||||
ld8.mov r18 = [r18], .Lst_table
|
||||
mov b0 = loc1
|
||||
;;
|
||||
shladd r18 = r16, 3, r18
|
||||
;;
|
||||
ld8 r17 = [r18]
|
||||
shr in3 = in3, 8
|
||||
;;
|
||||
add r17 = r17, r18
|
||||
;;
|
||||
mov b6 = r17
|
||||
br b6
|
||||
;;
|
||||
|
||||
.Lst_void:
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint8:
|
||||
zxt1 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint8:
|
||||
sxt1 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint16:
|
||||
zxt2 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint16:
|
||||
sxt2 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_uint32:
|
||||
zxt4 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_sint32:
|
||||
sxt4 r8 = r8
|
||||
;;
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_int64:
|
||||
st8 [in1] = r8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_float:
|
||||
stfs [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_double:
|
||||
stfd [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lst_ldouble:
|
||||
stfe [in1] = f8
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_small_struct:
|
||||
add sp = -16, sp
|
||||
cmp.lt p6, p0 = 8, in3
|
||||
cmp.lt p7, p0 = 16, in3
|
||||
cmp.lt p8, p0 = 24, in3
|
||||
;;
|
||||
add r16 = 8, sp
|
||||
add r17 = 16, sp
|
||||
add r18 = 24, sp
|
||||
;;
|
||||
st8 [sp] = r8
|
||||
(p6) st8 [r16] = r9
|
||||
mov out0 = in1
|
||||
(p7) st8 [r17] = r10
|
||||
(p8) st8 [r18] = r11
|
||||
mov out1 = sp
|
||||
mov out2 = in3
|
||||
br.call.sptk.many b0 = memcpy#
|
||||
;;
|
||||
mov ar.pfs = loc0
|
||||
mov b0 = loc1
|
||||
mov gp = loc2
|
||||
br.ret.sptk.many b0
|
||||
|
||||
.Lst_hfa_float:
|
||||
add r16 = 4, in1
|
||||
cmp.lt p6, p0 = 4, in3
|
||||
;;
|
||||
stfs [in1] = f8, 8
|
||||
(p6) stfs [r16] = f9, 8
|
||||
cmp.lt p7, p0 = 8, in3
|
||||
cmp.lt p8, p0 = 12, in3
|
||||
;;
|
||||
(p7) stfs [in1] = f10, 8
|
||||
(p8) stfs [r16] = f11, 8
|
||||
cmp.lt p9, p0 = 16, in3
|
||||
cmp.lt p10, p0 = 20, in3
|
||||
;;
|
||||
(p9) stfs [in1] = f12, 8
|
||||
(p10) stfs [r16] = f13, 8
|
||||
cmp.lt p6, p0 = 24, in3
|
||||
cmp.lt p7, p0 = 28, in3
|
||||
;;
|
||||
(p6) stfs [in1] = f14
|
||||
(p7) stfs [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_hfa_double:
|
||||
add r16 = 8, in1
|
||||
cmp.lt p6, p0 = 8, in3
|
||||
;;
|
||||
stfd [in1] = f8, 16
|
||||
(p6) stfd [r16] = f9, 16
|
||||
cmp.lt p7, p0 = 16, in3
|
||||
cmp.lt p8, p0 = 24, in3
|
||||
;;
|
||||
(p7) stfd [in1] = f10, 16
|
||||
(p8) stfd [r16] = f11, 16
|
||||
cmp.lt p9, p0 = 32, in3
|
||||
cmp.lt p10, p0 = 40, in3
|
||||
;;
|
||||
(p9) stfd [in1] = f12, 16
|
||||
(p10) stfd [r16] = f13, 16
|
||||
cmp.lt p6, p0 = 48, in3
|
||||
cmp.lt p7, p0 = 56, in3
|
||||
;;
|
||||
(p6) stfd [in1] = f14
|
||||
(p7) stfd [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lst_hfa_ldouble:
|
||||
add r16 = 16, in1
|
||||
cmp.lt p6, p0 = 16, in3
|
||||
;;
|
||||
stfe [in1] = f8, 32
|
||||
(p6) stfe [r16] = f9, 32
|
||||
cmp.lt p7, p0 = 32, in3
|
||||
cmp.lt p8, p0 = 48, in3
|
||||
;;
|
||||
(p7) stfe [in1] = f10, 32
|
||||
(p8) stfe [r16] = f11, 32
|
||||
cmp.lt p9, p0 = 64, in3
|
||||
cmp.lt p10, p0 = 80, in3
|
||||
;;
|
||||
(p9) stfe [in1] = f12, 32
|
||||
(p10) stfe [r16] = f13, 32
|
||||
cmp.lt p6, p0 = 96, in3
|
||||
cmp.lt p7, p0 = 112, in3
|
||||
;;
|
||||
(p6) stfe [in1] = f14
|
||||
(p7) stfe [r16] = f15
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.endp ffi_call_unix
|
||||
|
||||
.align 16
|
||||
.global ffi_closure_unix
|
||||
.proc ffi_closure_unix
|
||||
|
||||
#define FRAME_SIZE (8*16 + 8*8 + 8*16)
|
||||
|
||||
ffi_closure_unix:
|
||||
.prologue
|
||||
.save ar.pfs, r40 // loc0
|
||||
alloc loc0 = ar.pfs, 8, 4, 4, 0
|
||||
.fframe FRAME_SIZE
|
||||
add r12 = -FRAME_SIZE, r12
|
||||
.save rp, loc1
|
||||
mov loc1 = b0
|
||||
.save ar.unat, loc2
|
||||
mov loc2 = ar.unat
|
||||
.body
|
||||
|
||||
/* Retrieve closure pointer and real gp. */
|
||||
#ifdef _ILP32
|
||||
addp4 out0 = 0, gp
|
||||
addp4 gp = 16, gp
|
||||
#else
|
||||
mov out0 = gp
|
||||
add gp = 16, gp
|
||||
#endif
|
||||
;;
|
||||
ld8 gp = [gp]
|
||||
|
||||
/* Spill all of the possible argument registers. */
|
||||
add r16 = 16 + 8*16, sp
|
||||
add r17 = 16 + 8*16 + 16, sp
|
||||
;;
|
||||
stf.spill [r16] = f8, 32
|
||||
stf.spill [r17] = f9, 32
|
||||
mov loc3 = gp
|
||||
;;
|
||||
stf.spill [r16] = f10, 32
|
||||
stf.spill [r17] = f11, 32
|
||||
;;
|
||||
stf.spill [r16] = f12, 32
|
||||
stf.spill [r17] = f13, 32
|
||||
;;
|
||||
stf.spill [r16] = f14, 32
|
||||
stf.spill [r17] = f15, 24
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in0, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in1, 16
|
||||
add out1 = 16 + 8*16, sp
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in2, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in3, 16
|
||||
add out2 = 16, sp
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in4, 16
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in5, 16
|
||||
mov out3 = r8
|
||||
;;
|
||||
.mem.offset 0, 0
|
||||
st8.spill [r16] = in6
|
||||
.mem.offset 8, 0
|
||||
st8.spill [r17] = in7
|
||||
|
||||
/* Invoke ffi_closure_unix_inner for the hard work. */
|
||||
br.call.sptk.many b0 = ffi_closure_unix_inner
|
||||
;;
|
||||
|
||||
/* Dispatch to handle return value. */
|
||||
mov gp = loc3
|
||||
zxt1 r16 = r8
|
||||
;;
|
||||
addl r18 = @ltoffx(.Lld_table), gp
|
||||
mov ar.pfs = loc0
|
||||
;;
|
||||
ld8.mov r18 = [r18], .Lld_table
|
||||
mov b0 = loc1
|
||||
;;
|
||||
shladd r18 = r16, 3, r18
|
||||
mov ar.unat = loc2
|
||||
;;
|
||||
ld8 r17 = [r18]
|
||||
shr r8 = r8, 8
|
||||
;;
|
||||
add r17 = r17, r18
|
||||
add r16 = 16, sp
|
||||
;;
|
||||
mov b6 = r17
|
||||
br b6
|
||||
;;
|
||||
.label_state 1
|
||||
|
||||
.Lld_void:
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_int:
|
||||
.body
|
||||
.copy_state 1
|
||||
ld8 r8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_float:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfs f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_double:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfd f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
.Lld_ldouble:
|
||||
.body
|
||||
.copy_state 1
|
||||
ldfe f8 = [r16]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_small_struct:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 8, r16
|
||||
cmp.lt p6, p0 = 8, r8
|
||||
cmp.lt p7, p0 = 16, r8
|
||||
cmp.lt p8, p0 = 24, r8
|
||||
;;
|
||||
ld8 r8 = [r16], 16
|
||||
(p6) ld8 r9 = [r17], 16
|
||||
;;
|
||||
(p7) ld8 r10 = [r16]
|
||||
(p8) ld8 r11 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_float:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 4, r16
|
||||
cmp.lt p6, p0 = 4, r8
|
||||
;;
|
||||
ldfs f8 = [r16], 8
|
||||
(p6) ldfs f9 = [r17], 8
|
||||
cmp.lt p7, p0 = 8, r8
|
||||
cmp.lt p8, p0 = 12, r8
|
||||
;;
|
||||
(p7) ldfs f10 = [r16], 8
|
||||
(p8) ldfs f11 = [r17], 8
|
||||
cmp.lt p9, p0 = 16, r8
|
||||
cmp.lt p10, p0 = 20, r8
|
||||
;;
|
||||
(p9) ldfs f12 = [r16], 8
|
||||
(p10) ldfs f13 = [r17], 8
|
||||
cmp.lt p6, p0 = 24, r8
|
||||
cmp.lt p7, p0 = 28, r8
|
||||
;;
|
||||
(p6) ldfs f14 = [r16]
|
||||
(p7) ldfs f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_double:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 8, r16
|
||||
cmp.lt p6, p0 = 8, r8
|
||||
;;
|
||||
ldfd f8 = [r16], 16
|
||||
(p6) ldfd f9 = [r17], 16
|
||||
cmp.lt p7, p0 = 16, r8
|
||||
cmp.lt p8, p0 = 24, r8
|
||||
;;
|
||||
(p7) ldfd f10 = [r16], 16
|
||||
(p8) ldfd f11 = [r17], 16
|
||||
cmp.lt p9, p0 = 32, r8
|
||||
cmp.lt p10, p0 = 40, r8
|
||||
;;
|
||||
(p9) ldfd f12 = [r16], 16
|
||||
(p10) ldfd f13 = [r17], 16
|
||||
cmp.lt p6, p0 = 48, r8
|
||||
cmp.lt p7, p0 = 56, r8
|
||||
;;
|
||||
(p6) ldfd f14 = [r16]
|
||||
(p7) ldfd f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.Lld_hfa_ldouble:
|
||||
.body
|
||||
.copy_state 1
|
||||
add r17 = 16, r16
|
||||
cmp.lt p6, p0 = 16, r8
|
||||
;;
|
||||
ldfe f8 = [r16], 32
|
||||
(p6) ldfe f9 = [r17], 32
|
||||
cmp.lt p7, p0 = 32, r8
|
||||
cmp.lt p8, p0 = 48, r8
|
||||
;;
|
||||
(p7) ldfe f10 = [r16], 32
|
||||
(p8) ldfe f11 = [r17], 32
|
||||
cmp.lt p9, p0 = 64, r8
|
||||
cmp.lt p10, p0 = 80, r8
|
||||
;;
|
||||
(p9) ldfe f12 = [r16], 32
|
||||
(p10) ldfe f13 = [r17], 32
|
||||
cmp.lt p6, p0 = 96, r8
|
||||
cmp.lt p7, p0 = 112, r8
|
||||
;;
|
||||
(p6) ldfe f14 = [r16]
|
||||
(p7) ldfe f15 = [r17]
|
||||
.restore sp
|
||||
add sp = FRAME_SIZE, sp
|
||||
br.ret.sptk.many b0
|
||||
;;
|
||||
|
||||
.endp ffi_closure_unix
|
||||
|
||||
.section .rodata
|
||||
.align 8
|
||||
.Lst_table:
|
||||
data8 @pcrel(.Lst_void) // FFI_TYPE_VOID
|
||||
data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT
|
||||
data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT
|
||||
data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE
|
||||
data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE
|
||||
data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8
|
||||
data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8
|
||||
data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16
|
||||
data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16
|
||||
data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32
|
||||
data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64
|
||||
data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT
|
||||
data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER
|
||||
data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
|
||||
data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
|
||||
.Lld_table:
|
||||
data8 @pcrel(.Lld_void) // FFI_TYPE_VOID
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_INT
|
||||
data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT
|
||||
data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE
|
||||
data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64
|
||||
data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT
|
||||
data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER
|
||||
data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
|
||||
data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
@@ -1,11 +1,13 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
java_raw_api.c - Copyright (c) 1999 Cygnus Solutions
|
||||
java_raw_api.c - Copyright (c) 1999 Red Hat, Inc.
|
||||
|
||||
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
|
||||
@@ -20,20 +22,21 @@
|
||||
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 RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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 */
|
||||
/* 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. */
|
||||
/* 64 bits are actually used. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
|
||||
|
||||
@@ -50,13 +53,14 @@ ffi_java_raw_size (ffi_cif *cif)
|
||||
switch((*at) -> type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
result += 2 * SIZEOF_ARG;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
result += 2 * FFI_SIZEOF_ARG;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
default:
|
||||
result += SIZEOF_ARG;
|
||||
result += FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,27 +77,20 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
#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);
|
||||
*args = (void*) ((char*)(raw++) + 3);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + 2);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_ARG == 8
|
||||
|
||||
#if FFI_SIZEOF_ARG == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
@@ -105,10 +102,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +116,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if SIZEOF_ARG == 8
|
||||
#if FFI_SIZEOF_ARG == 8
|
||||
switch((*tp)->type) {
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
@@ -130,10 +127,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
#else /* SIZEOF_ARG != 8 */
|
||||
#else /* FFI_SIZEOF_ARG != 8 */
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
#endif /* SIZEOF_ARG == 8 */
|
||||
#endif /* FFI_SIZEOF_ARG == 8 */
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -150,39 +147,62 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT8*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT8*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT16*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT16*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(UINT32*)(raw++) = *(UINT32*) (*args);
|
||||
#else
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
#if WORDS_BIGENDIAN
|
||||
*(SINT32*)(raw++) = *(SINT32*) (*args);
|
||||
#else
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_FLOAT:
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
(raw++)->flt = *(FLOAT32*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG == 8
|
||||
#if FFI_SIZEOF_ARG == 8
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
@@ -196,11 +216,11 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
break;
|
||||
|
||||
default:
|
||||
#if SIZEOF_ARG == 8
|
||||
FFI_ASSERT(FALSE); /* Should have covered all cases */
|
||||
#else
|
||||
#if FFI_SIZEOF_ARG == 8
|
||||
FFI_ASSERT(0); /* Should have covered all cases */
|
||||
#else
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -208,6 +228,55 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
static void
|
||||
ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
|
||||
{
|
||||
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_INT:
|
||||
*(SINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
|
||||
{
|
||||
#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(UINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_INT:
|
||||
*(SINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
@@ -216,19 +285,17 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
* 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 ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, 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);
|
||||
ffi_java_rvalue_to_raw (cif, rvalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
static void
|
||||
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
@@ -237,6 +304,7 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue,
|
||||
|
||||
ffi_java_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
ffi_java_raw_to_rvalue (cif, rvalue);
|
||||
}
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
@@ -251,7 +319,7 @@ ffi_prep_java_raw_closure (ffi_raw_closure* cl,
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_java_translate_args,
|
||||
(void*)cl);
|
||||
231
libffi/src/m32r/ffi.c
Normal file
231
libffi/src/m32r/ffi.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2004 Renesas Technology
|
||||
|
||||
M32R 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 RENESAS TECHNOLOGY 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)
|
||||
{
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
unsigned int avn;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0) && (avn != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary. */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, (*p_arg)->alignment);
|
||||
|
||||
if (avn != 0)
|
||||
{
|
||||
avn--;
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
z = sizeof (int);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
z = (*p_arg)->size;
|
||||
if ((*p_arg)->alignment != 1)
|
||||
memcpy (argp, *p_argv, z);
|
||||
else
|
||||
memcpy (argp + 4 - z, *p_argv, z);
|
||||
z = sizeof (int);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (z > 8)
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
|
||||
z = sizeof(void *);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
z = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Double or long long 64bit. */
|
||||
memcpy (argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size <= 4)
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
|
||||
else if (cif->rtype->size <= 8)
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
|
||||
else
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 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_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
int size = cif->rtype->size;
|
||||
int align = cif->rtype->alignment;
|
||||
|
||||
if (size < 4)
|
||||
{
|
||||
if (align == 1)
|
||||
*(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
|
||||
}
|
||||
else if (4 < size && size < 8)
|
||||
{
|
||||
if (align == 1)
|
||||
{
|
||||
memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
|
||||
}
|
||||
else if (align == 2)
|
||||
{
|
||||
if (size & 1)
|
||||
size += 1;
|
||||
|
||||
if (size != 8)
|
||||
memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
48
libffi/src/m32r/ffitarget.h
Normal file
48
libffi/src/m32r/ffitarget.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2004 Renesas Technology.
|
||||
Target configuration macros for M32R.
|
||||
|
||||
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 RENESAS TECHNOLOGY 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi
|
||||
{
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
121
libffi/src/m32r/sysv.S
Normal file
121
libffi/src/m32r/sysv.S
Normal file
@@ -0,0 +1,121 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2004 Renesas Technology
|
||||
|
||||
M32R 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 RENESAS TECHNOLOGY 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
/* XXX these lose for some platforms, I'm sure. */
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/* R0: ffi_prep_args */
|
||||
/* R1: &ecif */
|
||||
/* R2: cif->bytes */
|
||||
/* R3: fig->flags */
|
||||
/* sp+0: ecif.rvalue */
|
||||
/* sp+4: fn */
|
||||
|
||||
/* This assumes we are using gas. */
|
||||
ENTRY(ffi_call_SYSV)
|
||||
/* Save registers. */
|
||||
push fp
|
||||
push lr
|
||||
push r3
|
||||
push r2
|
||||
push r1
|
||||
push r0
|
||||
mv fp, sp
|
||||
|
||||
/* Make room for all of the new args. */
|
||||
sub sp, r2
|
||||
|
||||
/* Place all of the ffi_prep_args in position. */
|
||||
mv lr, r0
|
||||
mv r0, sp
|
||||
/* R1 already set. */
|
||||
|
||||
/* And call. */
|
||||
jl lr
|
||||
|
||||
/* Move first 4 parameters in registers... */
|
||||
ld r0, @(0,sp)
|
||||
ld r1, @(4,sp)
|
||||
ld r2, @(8,sp)
|
||||
ld r3, @(12,sp)
|
||||
|
||||
/* ...and adjust the stack. */
|
||||
ld lr, @(8,fp)
|
||||
cmpi lr, #16
|
||||
bc adjust_stack
|
||||
ldi lr, #16
|
||||
adjust_stack:
|
||||
add sp, lr
|
||||
|
||||
/* Call the function. */
|
||||
ld lr, @(28,fp)
|
||||
jl lr
|
||||
|
||||
/* Remove the space we pushed for the args. */
|
||||
mv sp, fp
|
||||
|
||||
/* Load R2 with the pointer to storage for the return value. */
|
||||
ld r2, @(24,sp)
|
||||
|
||||
/* Load R3 with the return type code. */
|
||||
ld r3, @(12,sp)
|
||||
|
||||
/* If the return value pointer is NULL, assume no return value. */
|
||||
beqz r2, epilogue
|
||||
|
||||
/* Return INT. */
|
||||
ldi r4, #FFI_TYPE_INT
|
||||
bne r3, r4, return_double
|
||||
st r0, @r2
|
||||
bra epilogue
|
||||
|
||||
return_double:
|
||||
/* Return DOUBLE or LONGDOUBLE. */
|
||||
ldi r4, #FFI_TYPE_DOUBLE
|
||||
bne r3, r4, epilogue
|
||||
st r0, @r2
|
||||
st r1, @(4,r2)
|
||||
|
||||
epilogue:
|
||||
pop r0
|
||||
pop r1
|
||||
pop r2
|
||||
pop r3
|
||||
pop lr
|
||||
pop fp
|
||||
jmp lr
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
@@ -5,7 +5,7 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -16,14 +16,11 @@ static void *
|
||||
ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
unsigned int avn;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
void *struct_value_ptr;
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
||||
@@ -32,11 +29,10 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
else
|
||||
struct_value_ptr = NULL;
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0 && avn != 0;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
@@ -45,9 +41,6 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, (*p_arg)->alignment);
|
||||
|
||||
if (avn != 0)
|
||||
{
|
||||
avn--;
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
@@ -82,7 +75,6 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
memcpy (argp, *p_argv, z);
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
return struct_value_ptr;
|
||||
47
libffi/src/m68k/ffitarget.h
Normal file
47
libffi/src/m68k/ffitarget.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for Motorola 68K.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.text
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996, 2001 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <mips/mips.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cachectl.h>
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#define FIX_ARGP \
|
||||
FFI_ASSERT(argp <= &stack[bytes]); \
|
||||
if (argp == &stack[bytes]) \
|
||||
{ \
|
||||
argp = stack; \
|
||||
ffi_stop_here(); \
|
||||
}
|
||||
#else
|
||||
#define FIX_ARGP
|
||||
@@ -49,18 +50,17 @@ static void ffi_prep_args(char *stack,
|
||||
int bytes,
|
||||
int flags)
|
||||
{
|
||||
register int i;
|
||||
register int avn;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
/* If more than 8 double words are used, the remainder go
|
||||
on the stack. We reorder stuff on the stack here to
|
||||
support this easily. */
|
||||
if (bytes > 8 * SIZEOF_ARG)
|
||||
argp = &stack[bytes - (8 * SIZEOF_ARG)];
|
||||
if (bytes > 8 * sizeof(ffi_arg))
|
||||
argp = &stack[bytes - (8 * sizeof(ffi_arg))];
|
||||
else
|
||||
argp = stack;
|
||||
#else
|
||||
@@ -69,123 +69,112 @@ static void ffi_prep_args(char *stack,
|
||||
|
||||
memset(stack, 0, bytes);
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
if ( ecif->cif->rstruct_flag != 0 )
|
||||
#else
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
|
||||
#endif
|
||||
{
|
||||
*(SLOT_TYPE_UNSIGNED *) argp = (SLOT_TYPE_UNSIGNED) ecif->rvalue;
|
||||
argp += sizeof(SLOT_TYPE_UNSIGNED);
|
||||
*(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
|
||||
argp += sizeof(ffi_arg);
|
||||
FIX_ARGP;
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i && avn;
|
||||
i--, p_arg++)
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
unsigned int a;
|
||||
|
||||
/* Align if necessary */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
||||
FIX_ARGP;
|
||||
}
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
#define OFFSET 0
|
||||
#else
|
||||
#define OFFSET sizeof(int)
|
||||
#endif
|
||||
|
||||
if (avn)
|
||||
/* Align if necessary. */
|
||||
a = (*p_arg)->alignment;
|
||||
if (a < sizeof(ffi_arg))
|
||||
a = sizeof(ffi_arg);
|
||||
|
||||
if ((a - 1) & (unsigned int) argp)
|
||||
{
|
||||
avn--;
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(SLOT_TYPE_UNSIGNED))
|
||||
{
|
||||
z = sizeof(SLOT_TYPE_UNSIGNED);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
/* This can only happen with 64bit slots */
|
||||
case FFI_TYPE_FLOAT:
|
||||
*(float *) argp = *(float *)(* p_argv);
|
||||
break;
|
||||
|
||||
/* Handle small structures */
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
memcpy(argp, *p_argv, z);
|
||||
#else
|
||||
{
|
||||
unsigned end = (unsigned) argp+z;
|
||||
unsigned cap = (unsigned) stack+bytes;
|
||||
|
||||
/* Check if the data will fit within the register
|
||||
space. Handle it if it doesn't. */
|
||||
|
||||
if (end <= cap)
|
||||
memcpy(argp, *p_argv, z);
|
||||
else
|
||||
{
|
||||
unsigned portion = end - cap;
|
||||
|
||||
memcpy(argp, *p_argv, portion);
|
||||
argp = stack;
|
||||
memcpy(argp,
|
||||
(void*)((unsigned)(*p_argv)+portion), z - portion);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
argp = (char *) ALIGN(argp, a);
|
||||
FIX_ARGP;
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z <= sizeof(ffi_arg))
|
||||
{
|
||||
z = sizeof(ffi_arg);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(ffi_arg *)argp = *(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(ffi_arg *)argp = *(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(ffi_arg *)argp = *(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
/* This can only happen with 64bit slots. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
*(float *) argp = *(float *)(* p_argv);
|
||||
break;
|
||||
|
||||
/* Handle small structures. */
|
||||
case FFI_TYPE_STRUCT:
|
||||
default:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
memcpy(argp, *p_argv, z);
|
||||
#else
|
||||
{
|
||||
unsigned end = (unsigned) argp+z;
|
||||
unsigned cap = (unsigned) stack+bytes;
|
||||
|
||||
/* Check if the data will fit within the register space.
|
||||
Handle it if it doesn't. */
|
||||
|
||||
if (end <= cap)
|
||||
memcpy(argp, *p_argv, z);
|
||||
else
|
||||
{
|
||||
unsigned portion = end - cap;
|
||||
|
||||
memcpy(argp, *p_argv, portion);
|
||||
argp = stack;
|
||||
memcpy(argp,
|
||||
(void*)((unsigned)(*p_argv)+portion), z - portion);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
FIX_ARGP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
|
||||
/* The n32 spec says that if "a chunk consists solely of a double
|
||||
float field (but not a double, which is part of a union), it
|
||||
@@ -193,7 +182,7 @@ static void ffi_prep_args(char *stack,
|
||||
passed in an integer register". This code traverses structure
|
||||
definitions and generates the appropriate flags. */
|
||||
|
||||
static unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
|
||||
unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
unsigned index = 0;
|
||||
@@ -274,10 +263,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
cif->flags = 0;
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
/* Set the flags necessary for O32 processing */
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
/* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
|
||||
* does not have special handling for floating point args.
|
||||
*/
|
||||
|
||||
if (cif->rtype->type != FFI_TYPE_STRUCT)
|
||||
if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
|
||||
{
|
||||
if (cif->nargs > 0)
|
||||
{
|
||||
@@ -314,22 +305,53 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
}
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
|
||||
if (cif->abi == FFI_O32_SOFT_FLOAT)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FFI_O32 */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
/* Set the flags necessary for N32 processing */
|
||||
{
|
||||
unsigned shift = 0;
|
||||
@@ -448,14 +470,15 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
case FFI_O32:
|
||||
case FFI_O32_SOFT_FLOAT:
|
||||
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
case FFI_N32:
|
||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
@@ -467,3 +490,159 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* N32 not implemented yet, FFI_CLOSURES not defined */
|
||||
#if defined(FFI_MIPS_O32)
|
||||
extern void ffi_closure_O32(void);
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned int fn;
|
||||
unsigned int ctx = (unsigned int) closure;
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
|
||||
fn = (unsigned int) ffi_closure_O32;
|
||||
#else /* FFI_MIPS_N32 */
|
||||
FFI_ASSERT(cif->abi == FFI_N32);
|
||||
FFI_ASSERT(!"not implemented");
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
tramp[0] = 0x3c190000 | (fn >> 16); /* lui $25,high(fn) */
|
||||
tramp[1] = 0x37390000 | (fn & 0xffff); /* ori $25,low(fn) */
|
||||
tramp[2] = 0x3c080000 | (ctx >> 16); /* lui $8,high(ctx) */
|
||||
tramp[3] = 0x03200008; /* jr $25 */
|
||||
tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori $8,low(ctx) */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* XXX this is available on Linux, but anything else? */
|
||||
cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes the arguments to a function, which will be stored on the
|
||||
* stack. AR is the pointer to the beginning of the integer arguments
|
||||
* (and, depending upon the arguments, some floating-point arguments
|
||||
* as well). FPR is a pointer to the area where floating point
|
||||
* registers have been saved, if any.
|
||||
*
|
||||
* RVALUE is the location where the function return value will be
|
||||
* stored. CLOSURE is the prepared closure to invoke.
|
||||
*
|
||||
* This function should only be called from assembly, which is in
|
||||
* turn called from a trampoline.
|
||||
*
|
||||
* Returns the function return type.
|
||||
*
|
||||
* Based on the similar routine for sparc.
|
||||
*/
|
||||
int
|
||||
ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
void *rvalue, ffi_arg *ar,
|
||||
double *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avaluep;
|
||||
ffi_arg *avalue;
|
||||
ffi_type **arg_types;
|
||||
int i, avn, argn, seen_int;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
avaluep = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
|
||||
seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
|
||||
argn = 0;
|
||||
|
||||
if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) ar[0];
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
if (i < 2 && !seen_int &&
|
||||
(arg_types[i]->type == FFI_TYPE_FLOAT ||
|
||||
arg_types[i]->type == FFI_TYPE_DOUBLE))
|
||||
{
|
||||
#ifdef __MIPSEB__
|
||||
if (arg_types[i]->type == FFI_TYPE_FLOAT)
|
||||
avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
|
||||
else
|
||||
#endif
|
||||
avaluep[i] = (char *) &fpr[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arg_types[i]->alignment == 8 && (argn & 0x1))
|
||||
argn++;
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT8 *) &avalue[i] = (SINT8) ar[argn];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT8 *) &avalue[i] = (UINT8) ar[argn];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT16 *) &avalue[i] = (SINT16) ar[argn];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT16 *) &avalue[i] = (UINT16) ar[argn];
|
||||
break;
|
||||
|
||||
default:
|
||||
avaluep[i] = (char *) &ar[argn];
|
||||
break;
|
||||
}
|
||||
seen_int = 1;
|
||||
}
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
|
||||
|
||||
if (cif->abi == FFI_O32_SOFT_FLOAT)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
return FFI_TYPE_INT;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
return FFI_TYPE_UINT64;
|
||||
default:
|
||||
return cif->rtype->type;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return cif->rtype->type;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
@@ -1,7 +1,6 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi-mips.h - Copyright (c) 1996, 2001 Red Hat, Inc.
|
||||
|
||||
MIPS FFI Definitions
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for MIPS.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -17,37 +16,71 @@
|
||||
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 SUPPORT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef MIPS_H
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#if defined(__mips_eabi)
|
||||
# define FFI_MIPS_EABI
|
||||
# define FFI_MIPS_O32
|
||||
#else
|
||||
# if !defined(_MIPS_SIM)
|
||||
#if !defined(_MIPS_SIM)
|
||||
-- something is very wrong --
|
||||
#else
|
||||
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
|
||||
# define FFI_MIPS_N32
|
||||
# else
|
||||
# if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
|
||||
# define FFI_MIPS_N32
|
||||
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
|
||||
# define FFI_MIPS_O32
|
||||
# else
|
||||
# if defined(__GNUC__)
|
||||
# define FFI_MIPS_O32
|
||||
# else
|
||||
# if _MIPS_SIM==_ABIO32
|
||||
# define FFI_MIPS_O32
|
||||
# else
|
||||
-- this is an unsupported platform --
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
#define FFI_SIZEOF_ARG 4
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
#endif
|
||||
|
||||
#define FFI_FLAG_BITS 2
|
||||
|
||||
/* SGI's strange assembler requires that we multiply by 4 rather
|
||||
than shift left by FFI_FLAG_BITS */
|
||||
|
||||
#define FFI_ARGS_D FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_F FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_FF FFI_TYPE_FLOAT * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_FD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DF FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
|
||||
|
||||
/* Needed for N32 structure returns */
|
||||
#define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8
|
||||
#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
|
||||
|
||||
#if 0
|
||||
/* The SGI assembler can't handle this.. */
|
||||
#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
|
||||
/* (and so on) */
|
||||
#else
|
||||
/* ...so we calculate these by hand! */
|
||||
#define FFI_TYPE_STRUCT_D 61
|
||||
#define FFI_TYPE_STRUCT_F 45
|
||||
#define FFI_TYPE_STRUCT_DD 253
|
||||
#define FFI_TYPE_STRUCT_FF 173
|
||||
#define FFI_TYPE_STRUCT_FD 237
|
||||
#define FFI_TYPE_STRUCT_DF 189
|
||||
#define FFI_TYPE_STRUCT_SMALL 93
|
||||
#define FFI_TYPE_STRUCT_SMALL2 109
|
||||
#endif
|
||||
|
||||
#ifdef LIBFFI_ASM
|
||||
#define v0 $2
|
||||
#define v1 $3
|
||||
#define a0 $4
|
||||
@@ -70,75 +103,65 @@
|
||||
#define t9 $25
|
||||
#define ra $31
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
|
||||
#define FFI_DEFAULT_ABI FFI_O32
|
||||
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
#define SLOT_TYPE_UNSIGNED UINT32
|
||||
#define SLOT_TYPE_SIGNED SINT32
|
||||
#define SIZEOF_ARG 4
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
#define REG_L lw
|
||||
#define REG_S sw
|
||||
#define SUBU subu
|
||||
#define ADDU addu
|
||||
#define SRL srl
|
||||
#define LI li
|
||||
|
||||
#else
|
||||
|
||||
#define FFI_DEFAULT_ABI FFI_N32
|
||||
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
#define SLOT_TYPE_UNSIGNED UINT64
|
||||
#define SLOT_TYPE_SIGNED SINT64
|
||||
#define SIZEOF_ARG 8
|
||||
|
||||
#else /* !FFI_MIPS_O32 */
|
||||
#define REG_L ld
|
||||
#define REG_S sd
|
||||
#define SUBU dsubu
|
||||
#define ADDU daddu
|
||||
#define SRL dsrl
|
||||
#define LI dli
|
||||
|
||||
#endif
|
||||
|
||||
#define FFI_FLAG_BITS 2
|
||||
|
||||
/* SGI's strange assembler requires that we multiply by 4 rather
|
||||
than shift left by FFI_FLAG_BITS */
|
||||
|
||||
#define FFI_ARGS_D FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_F FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
|
||||
#define FFI_ARGS_FF FFI_TYPE_FLOAT * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_FD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
|
||||
#define FFI_ARGS_DF FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
|
||||
|
||||
/* Needed for N32 structure returns */
|
||||
#define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8
|
||||
#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
|
||||
|
||||
#if 0
|
||||
|
||||
/* The SGI assembler can't handle this.. */
|
||||
|
||||
#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
|
||||
|
||||
#endif /* !FFI_MIPS_O32 */
|
||||
#else /* !LIBFFI_ASM */
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
typedef unsigned int ffi_arg __attribute__((__mode__(__SI__)));
|
||||
typedef signed int ffi_sarg __attribute__((__mode__(__SI__)));
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
typedef unsigned int ffi_arg __attribute__((__mode__(__DI__)));
|
||||
typedef signed int ffi_sarg __attribute__((__mode__(__DI__)));
|
||||
#endif
|
||||
|
||||
/* ...so we calculate these by hand! */
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_O32,
|
||||
FFI_N32,
|
||||
FFI_N64,
|
||||
FFI_O32_SOFT_FLOAT,
|
||||
|
||||
#define FFI_TYPE_STRUCT_D 61
|
||||
#define FFI_TYPE_STRUCT_F 45
|
||||
#define FFI_TYPE_STRUCT_DD 253
|
||||
#define FFI_TYPE_STRUCT_FF 173
|
||||
#define FFI_TYPE_STRUCT_FD 237
|
||||
#define FFI_TYPE_STRUCT_DF 189
|
||||
#define FFI_TYPE_STRUCT_SMALL 93
|
||||
#define FFI_TYPE_STRUCT_SMALL2 109
|
||||
#ifdef FFI_MIPS_O32
|
||||
#ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
#endif
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
|
||||
#endif /* !LIBFFI_ASM */
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* N32/N64 not implemented yet. */
|
||||
#define FFI_CLOSURES 0
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
n32.S - Copyright (c) 1996, 1998, 2001 Red Hat, Inc.
|
||||
n32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <mips/mips.h>
|
||||
|
||||
|
||||
/* Only build this code if we are compiling for n32 */
|
||||
|
||||
#if defined(FFI_MIPS_N32)
|
||||
@@ -38,8 +37,9 @@
|
||||
#define raddr a4
|
||||
#define fn a5
|
||||
|
||||
#define SIZEOF_FRAME ( 8 * SIZEOF_ARG )
|
||||
#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
|
||||
|
||||
.abicalls
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_call_N32
|
||||
@@ -48,37 +48,37 @@ ffi_call_N32:
|
||||
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
|
||||
REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
|
||||
REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
|
||||
REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
|
||||
move $fp, $sp
|
||||
|
||||
move t9, callback # callback function pointer
|
||||
REG_S bytes, 2*SIZEOF_ARG($fp) # bytes
|
||||
REG_S flags, 3*SIZEOF_ARG($fp) # flags
|
||||
REG_S raddr, 4*SIZEOF_ARG($fp) # raddr
|
||||
REG_S fn, 5*SIZEOF_ARG($fp) # fn
|
||||
REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
|
||||
REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
|
||||
REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
||||
REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
move v0, bytes
|
||||
bge bytes, 4 * SIZEOF_ARG, bigger
|
||||
LI v0, 4 * SIZEOF_ARG
|
||||
bge bytes, 4 * FFI_SIZEOF_ARG, bigger
|
||||
LI v0, 4 * FFI_SIZEOF_ARG
|
||||
b sixteen
|
||||
|
||||
bigger:
|
||||
ADDU t4, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
|
||||
and v0, t4, -2 * SIZEOF_ARG # to a proper boundry.
|
||||
ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
|
||||
and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry.
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 0 # 4 * SIZEOF_ARG
|
||||
ADDU a3, $fp, 3 * SIZEOF_ARG
|
||||
ADDU a0, $sp, 0 # 4 * FFI_SIZEOF_ARG
|
||||
ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
|
||||
|
||||
# Call ffi_prep_args
|
||||
jal t9
|
||||
|
||||
# ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
|
||||
# ADDU $sp, $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
# Copy the stack pointer to t9
|
||||
move t9, $sp
|
||||
@@ -87,10 +87,10 @@ sixteen:
|
||||
# of arguments.
|
||||
|
||||
# Load the number of bytes
|
||||
REG_L t6, 2*SIZEOF_ARG($fp)
|
||||
REG_L t6, 2*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# Is it bigger than 8 * SIZEOF_ARG?
|
||||
dadd t7, $0, 8 * SIZEOF_ARG
|
||||
# Is it bigger than 8 * FFI_SIZEOF_ARG?
|
||||
dadd t7, $0, 8 * FFI_SIZEOF_ARG
|
||||
dsub t8, t6, t7
|
||||
bltz t8, loadregs
|
||||
|
||||
@@ -98,125 +98,125 @@ sixteen:
|
||||
|
||||
loadregs:
|
||||
|
||||
REG_L t4, 3*SIZEOF_ARG($fp) # load the flags word
|
||||
REG_L t4, 3*FFI_SIZEOF_ARG($fp) # load the flags word
|
||||
add t6, t4, 0 # and copy it into t6
|
||||
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg1_floatp
|
||||
REG_L a0, 0*SIZEOF_ARG(t9)
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg1_doublep
|
||||
l.s $f12, 0*SIZEOF_ARG(t9)
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_doublep:
|
||||
l.d $f12, 0*SIZEOF_ARG(t9)
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
arg1_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 1*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg2_floatp
|
||||
REG_L a1, 1*SIZEOF_ARG(t9)
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg2_doublep
|
||||
l.s $f13, 1*SIZEOF_ARG(t9)
|
||||
l.s $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_doublep:
|
||||
l.d $f13, 1*SIZEOF_ARG(t9)
|
||||
l.d $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
arg2_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 2*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg3_floatp
|
||||
REG_L a2, 2*SIZEOF_ARG(t9)
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg3_doublep
|
||||
l.s $f14, 2*SIZEOF_ARG(t9)
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_doublep:
|
||||
l.d $f14, 2*SIZEOF_ARG(t9)
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
arg3_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 3*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg4_floatp
|
||||
REG_L a3, 3*SIZEOF_ARG(t9)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg4_doublep
|
||||
l.s $f15, 3*SIZEOF_ARG(t9)
|
||||
l.s $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_doublep:
|
||||
l.d $f15, 3*SIZEOF_ARG(t9)
|
||||
l.d $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
arg4_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 4*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg5_floatp
|
||||
REG_L a4, 4*SIZEOF_ARG(t9)
|
||||
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg5_doublep
|
||||
l.s $f16, 4*SIZEOF_ARG(t9)
|
||||
l.s $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_doublep:
|
||||
l.d $f16, 4*SIZEOF_ARG(t9)
|
||||
l.d $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
arg5_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 5*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg6_floatp
|
||||
REG_L a5, 5*SIZEOF_ARG(t9)
|
||||
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg6_doublep
|
||||
l.s $f17, 5*SIZEOF_ARG(t9)
|
||||
l.s $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_doublep:
|
||||
l.d $f17, 5*SIZEOF_ARG(t9)
|
||||
l.d $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
arg6_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 6*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg7_floatp
|
||||
REG_L a6, 6*SIZEOF_ARG(t9)
|
||||
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg7_doublep
|
||||
l.s $f18, 6*SIZEOF_ARG(t9)
|
||||
l.s $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_doublep:
|
||||
l.d $f18, 6*SIZEOF_ARG(t9)
|
||||
l.d $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
arg7_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 7*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg8_floatp
|
||||
REG_L a7, 7*SIZEOF_ARG(t9)
|
||||
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_floatp:
|
||||
bne t4, FFI_TYPE_FLOAT, arg8_doublep
|
||||
l.s $f19, 7*SIZEOF_ARG(t9)
|
||||
l.s $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_doublep:
|
||||
l.d $f19, 7*SIZEOF_ARG(t9)
|
||||
l.d $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
arg8_next:
|
||||
|
||||
callit:
|
||||
# Load the function pointer
|
||||
REG_L t9, 5*SIZEOF_ARG($fp)
|
||||
REG_L t9, 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t5, 4*SIZEOF_ARG($fp)
|
||||
REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t5, noretval
|
||||
|
||||
# Shift the return type flag over
|
||||
@@ -224,42 +224,42 @@ callit:
|
||||
|
||||
bne t6, FFI_TYPE_INT, retfloat
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t6, FFI_TYPE_FLOAT, retdouble
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t6, FFI_TYPE_DOUBLE, retstruct_d
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d:
|
||||
bne t6, FFI_TYPE_STRUCT_D, retstruct_f
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_f:
|
||||
bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_d_d:
|
||||
bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
@@ -267,7 +267,7 @@ retstruct_d_d:
|
||||
retstruct_f_f:
|
||||
bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.s $f2, 4(t4)
|
||||
b epilogue
|
||||
@@ -275,7 +275,7 @@ retstruct_f_f:
|
||||
retstruct_d_f:
|
||||
bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t4)
|
||||
s.s $f2, 8(t4)
|
||||
b epilogue
|
||||
@@ -283,7 +283,7 @@ retstruct_d_f:
|
||||
retstruct_f_d:
|
||||
bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t4)
|
||||
s.d $f2, 8(t4)
|
||||
b epilogue
|
||||
@@ -291,14 +291,14 @@ retstruct_f_d:
|
||||
retstruct_small:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
b epilogue
|
||||
|
||||
retstruct_small2:
|
||||
bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
|
||||
jal t9
|
||||
REG_L t4, 4*SIZEOF_ARG($fp)
|
||||
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t4)
|
||||
REG_S v1, 8(t4)
|
||||
b epilogue
|
||||
@@ -310,8 +310,8 @@ noretval:
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
|
||||
REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
377
libffi/src/mips/o32.S
Normal file
377
libffi/src/mips/o32.S
Normal file
@@ -0,0 +1,377 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
o32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
|
||||
|
||||
MIPS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Only build this code if we are compiling for o32 */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
|
||||
#define callback a0
|
||||
#define bytes a2
|
||||
#define flags a3
|
||||
|
||||
#define SIZEOF_FRAME (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
|
||||
#define FP_OFF (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
|
||||
#define RA_OFF (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
|
||||
|
||||
.abicalls
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_call_O32
|
||||
.ent ffi_call_O32
|
||||
ffi_call_O32:
|
||||
$LFB0:
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
$LCFI0:
|
||||
REG_S $fp, FP_OFF($sp) # Save frame pointer
|
||||
$LCFI1:
|
||||
REG_S ra, RA_OFF($sp) # Save return address
|
||||
$LCFI2:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI3:
|
||||
move t9, callback # callback function pointer
|
||||
REG_S flags, A3_OFF($fp) # flags
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
LI v0, 4 * FFI_SIZEOF_ARG
|
||||
blt bytes, v0, sixteen
|
||||
|
||||
ADDU v0, bytes, 7 # make sure it is aligned
|
||||
and v0, -8 # to an 8 byte boundry
|
||||
|
||||
sixteen:
|
||||
SUBU $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 4 * FFI_SIZEOF_ARG
|
||||
|
||||
jalr t9
|
||||
|
||||
REG_L t0, A3_OFF($fp) # load the flags word
|
||||
SRL t2, t0, 4 # shift our arg info
|
||||
and t0, ((1<<4)-1) # mask out the return type
|
||||
|
||||
ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
bnez t0, pass_d # make it quick for int
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs.
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d:
|
||||
bne t0, FFI_ARGS_D, pass_f
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp) # passing a double
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f:
|
||||
bne t0, FFI_ARGS_F, pass_d_d
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # passing a float
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_d:
|
||||
bne t0, FFI_ARGS_DD, pass_f_f
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing two doubles
|
||||
b call_it
|
||||
|
||||
pass_f_f:
|
||||
bne t0, FFI_ARGS_FF, pass_d_f
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 1*FFI_SIZEOF_ARG($sp) # passing two floats
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_d_f:
|
||||
bne t0, FFI_ARGS_DF, pass_f_d
|
||||
l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
|
||||
b call_it
|
||||
|
||||
pass_f_d:
|
||||
# assume that the only other combination must be float then double
|
||||
# bne t0, FFI_ARGS_F_D, call_it
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
|
||||
call_it:
|
||||
# Load the function pointer
|
||||
REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t1, noretval
|
||||
|
||||
bne t2, FFI_TYPE_INT, retlonglong
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retlonglong:
|
||||
# Really any 64-bit int, signed or not.
|
||||
bne t2, FFI_TYPE_UINT64, retfloat
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v1, 4(t0)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t2, FFI_TYPE_FLOAT, retdouble
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
s.s $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retdouble:
|
||||
bne t2, FFI_TYPE_DOUBLE, noretval
|
||||
jalr t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
noretval:
|
||||
jalr t9
|
||||
|
||||
# Epilogue
|
||||
epilogue:
|
||||
move $sp, $fp
|
||||
REG_L $fp, FP_OFF($sp) # Restore frame pointer
|
||||
REG_L ra, RA_OFF($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
$LFE0:
|
||||
.end ffi_call_O32
|
||||
|
||||
|
||||
/* ffi_closure_O32. Expects address of the passed-in ffi_closure
|
||||
in t0. Stores any arguments passed in registers onto the
|
||||
stack, then calls ffi_closure_mips_inner_O32, which
|
||||
then decodes them.
|
||||
|
||||
Stack layout:
|
||||
|
||||
14 - Start of parameters, original sp
|
||||
13 - ra save
|
||||
12 - fp save
|
||||
11 - $16 (s0) save
|
||||
10 - cprestore
|
||||
9 - return value high (v1)
|
||||
8 - return value low (v0)
|
||||
7 - f14 (le high, be low)
|
||||
6 - f14 (le low, be high)
|
||||
5 - f12 (le high, be low)
|
||||
4 - f12 (le low, be high)
|
||||
3 - Called function a3 save
|
||||
2 - Called function a2 save
|
||||
1 - Called function a1 save
|
||||
0 - Called function a0 save our sp, fp point here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
|
||||
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
|
||||
#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
|
||||
#define A0_OFF2 (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
|
||||
#define RA_OFF2 (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
|
||||
#define FP_OFF2 (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
|
||||
#define S0_OFF2 (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
|
||||
#define GP_OFF2 (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
|
||||
#define V1_OFF2 (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
|
||||
#define V0_OFF2 (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
|
||||
#define FA_1_1_OFF2 (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
|
||||
#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_closure_O32
|
||||
.ent ffi_closure_O32
|
||||
ffi_closure_O32:
|
||||
$LFB1:
|
||||
# Prologue
|
||||
.frame $fp, SIZEOF_FRAME2, ra
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.cprestore GP_OFF2
|
||||
$LCFI4:
|
||||
REG_S $16, S0_OFF2($sp) # Save s0
|
||||
REG_S $fp, FP_OFF2($sp) # Save frame pointer
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
$LCFI6:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI7:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# four arguments, then they are stored above where we put a3.
|
||||
REG_S a0, A0_OFF2($fp)
|
||||
REG_S a1, A1_OFF2($fp)
|
||||
REG_S a2, A2_OFF2($fp)
|
||||
REG_S a3, A3_OFF2($fp)
|
||||
|
||||
# Load ABI enum to s0
|
||||
REG_L $16, 20($8) # cif pointer follows tramp.
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, FA_0_0_OFF2($fp)
|
||||
s.d $f14, FA_1_0_OFF2($fp)
|
||||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
la t9, ffi_closure_mips_inner_O32
|
||||
move a0, $8 # Pointer to the ffi_closure
|
||||
addu a1, $fp, V0_OFF2
|
||||
addu a2, $fp, A0_OFF2
|
||||
addu a3, $fp, FA_0_0_OFF2
|
||||
jalr t9
|
||||
|
||||
# Load the return value into the appropriate register.
|
||||
move $8, $2
|
||||
li $9, FFI_TYPE_VOID
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT
|
||||
|
||||
li $9, FFI_TYPE_FLOAT
|
||||
l.s $f0, V0_OFF2($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_DOUBLE
|
||||
l.d $f0, V0_OFF2($fp)
|
||||
beq $8, $9, closure_done
|
||||
1:
|
||||
REG_L $3, V1_OFF2($fp)
|
||||
REG_L $2, V0_OFF2($fp)
|
||||
|
||||
closure_done:
|
||||
# Epilogue
|
||||
move $sp, $fp
|
||||
REG_L $16, S0_OFF2($sp) # Restore s0
|
||||
REG_L $fp, FP_OFF2($sp) # Restore frame pointer
|
||||
REG_L ra, RA_OFF2($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME2
|
||||
j ra
|
||||
$LFE1:
|
||||
.end ffi_closure_O32
|
||||
|
||||
/* DWARF-2 unwind info. */
|
||||
|
||||
.section .eh_frame,"a",@progbits
|
||||
$Lframe0:
|
||||
.4byte $LECIE0-$LSCIE0 # Length of Common Information Entry
|
||||
$LSCIE0:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 4 # CIE Data Alignment Factor
|
||||
.byte 0x1f # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x00 # FDE Encoding (absptr)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1d
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
$LECIE0:
|
||||
$LSFDE0:
|
||||
.4byte $LEFDE0-$LASFDE0 # FDE Length
|
||||
$LASFDE0:
|
||||
.4byte $LASFDE0-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB0 # FDE initial location
|
||||
.4byte $LFE0-$LFB0 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI0-$LFB0
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x18
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI0
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI3-$LCFI2
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x18
|
||||
.align 2
|
||||
$LEFDE0:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB1 # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI4-$LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x38
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI4
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x10 # $16
|
||||
.sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI7-$LCFI6
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x38
|
||||
.align 2
|
||||
$LEFDE1:
|
||||
|
||||
#endif
|
||||
706
libffi/src/pa/ffi.c
Normal file
706
libffi/src/pa/ffi.c
Normal file
@@ -0,0 +1,706 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
|
||||
HPPA Foreign Function Interface
|
||||
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
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 <stdio.h>
|
||||
|
||||
#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
#define MIN_STACK_SIZE 64
|
||||
#define FIRST_ARG_SLOT 9
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
#define fldw(addr, fpreg) \
|
||||
__asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
|
||||
#define fstw(fpreg, addr) \
|
||||
__asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
#define fldd(addr, fpreg) \
|
||||
__asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
|
||||
#define fstd(fpreg, addr) \
|
||||
__asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
|
||||
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
|
||||
|
||||
static inline int ffi_struct_type(ffi_type *t)
|
||||
{
|
||||
size_t sz = t->size;
|
||||
|
||||
/* Small structure results are passed in registers,
|
||||
larger ones are passed by pointer. Note that
|
||||
small structures of size 2, 4 and 8 differ from
|
||||
the corresponding integer types in that they have
|
||||
different alignment requirements. */
|
||||
|
||||
if (sz <= 1)
|
||||
return FFI_TYPE_UINT8;
|
||||
else if (sz == 2)
|
||||
return FFI_TYPE_SMALL_STRUCT2;
|
||||
else if (sz == 3)
|
||||
return FFI_TYPE_SMALL_STRUCT3;
|
||||
else if (sz == 4)
|
||||
return FFI_TYPE_SMALL_STRUCT4;
|
||||
else if (sz == 5)
|
||||
return FFI_TYPE_SMALL_STRUCT5;
|
||||
else if (sz == 6)
|
||||
return FFI_TYPE_SMALL_STRUCT6;
|
||||
else if (sz == 7)
|
||||
return FFI_TYPE_SMALL_STRUCT7;
|
||||
else if (sz <= 8)
|
||||
return FFI_TYPE_SMALL_STRUCT8;
|
||||
else
|
||||
return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
|
||||
}
|
||||
|
||||
/* PA has a downward growing stack, which looks like this:
|
||||
|
||||
Offset
|
||||
[ Variable args ]
|
||||
SP = (4*(n+9)) arg word N
|
||||
...
|
||||
SP-52 arg word 4
|
||||
[ Fixed args ]
|
||||
SP-48 arg word 3
|
||||
SP-44 arg word 2
|
||||
SP-40 arg word 1
|
||||
SP-36 arg word 0
|
||||
[ Frame marker ]
|
||||
...
|
||||
SP-20 RP
|
||||
SP-4 previous SP
|
||||
|
||||
The first four argument words on the stack are reserved for use by
|
||||
the callee. Instead, the general and floating registers replace
|
||||
the first four argument slots. Non FP arguments are passed solely
|
||||
in the general registers. FP arguments are passed in both general
|
||||
and floating registers when using libffi.
|
||||
|
||||
Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
|
||||
Non-FP 64-bit args are passed in register pairs, starting
|
||||
on an odd numbered register (i.e. r25+r26 and r23+r24).
|
||||
FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
|
||||
FP 64-bit arguments are passed in fr5 and fr7.
|
||||
|
||||
The registers are allocated in the same manner as stack slots.
|
||||
This allows the callee to save its arguments on the stack if
|
||||
necessary:
|
||||
|
||||
arg word 3 -> gr23 or fr7L
|
||||
arg word 2 -> gr24 or fr6L or fr7R
|
||||
arg word 1 -> gr25 or fr5L
|
||||
arg word 0 -> gr26 or fr4L or fr5R
|
||||
|
||||
Note that fr4R and fr6R are never used for arguments (i.e.,
|
||||
doubles are not passed in fr4 or fr6).
|
||||
|
||||
The rest of the arguments are passed on the stack starting at SP-52,
|
||||
but 64-bit arguments need to be aligned to an 8-byte boundary
|
||||
|
||||
This means we can have holes either in the register allocation,
|
||||
or in the stack. */
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments
|
||||
|
||||
The following code will put everything into the stack frame
|
||||
(which was allocated by the asm routine), and on return
|
||||
the asm routine will load the arguments that should be
|
||||
passed by register into the appropriate registers
|
||||
|
||||
NOTE: We load floating point args in this function... that means we
|
||||
assume gcc will not mess with fp regs in here. */
|
||||
|
||||
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
||||
{
|
||||
register unsigned int i;
|
||||
register ffi_type **p_arg;
|
||||
register void **p_argv;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
char *dest_cpy;
|
||||
size_t len;
|
||||
|
||||
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
|
||||
ecif, bytes);
|
||||
|
||||
p_arg = ecif->cif->arg_types;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0; i < ecif->cif->nargs; i++)
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
|
||||
slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
debug(3, "Storing UINT32(float) in slot %u\n", slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
case 0: fldw(stack - slot, fr4); break;
|
||||
case 1: fldw(stack - slot, fr5); break;
|
||||
case 2: fldw(stack - slot, fr6); break;
|
||||
case 3: fldw(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
debug(3, "Storing UINT64(double) at slot %u\n", slot);
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 2 args go in fr5, fr7. */
|
||||
case 1: fldd(stack - slot, fr5); break;
|
||||
case 3: fldd(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are passed in the same manner as structures
|
||||
larger than 8 bytes. */
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
|
||||
len = (*p_arg)->size;
|
||||
if (len <= 4)
|
||||
{
|
||||
dest_cpy = (char *)(stack - slot) + 4 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else if (len <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
dest_cpy = (char *)(stack - slot) + 8 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
p_argv++;
|
||||
}
|
||||
|
||||
/* Make sure we didn't mess up and scribble on the stack. */
|
||||
{
|
||||
unsigned int n;
|
||||
|
||||
debug(5, "Stack setup:\n");
|
||||
for (n = 0; n < (bytes + 3) / 4; n++)
|
||||
{
|
||||
if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
|
||||
debug(5, "%08x ", *(stack - n));
|
||||
}
|
||||
debug(5, "\n");
|
||||
}
|
||||
|
||||
FFI_ASSERT(slot * 4 <= bytes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ffi_size_stack_pa32(ffi_cif *cif)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
int z = 0; /* # stack slots */
|
||||
|
||||
for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
|
||||
{
|
||||
int type = (*ptr)->type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
z += 2 + (z & 1); /* must start on even regs, so we may waste one */
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
case FFI_TYPE_STRUCT:
|
||||
z += 1; /* pass by ptr, callee will copy */
|
||||
break;
|
||||
|
||||
default: /* <= 32-bit values */
|
||||
z++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can fit up to 6 args in the default 64-byte stack frame,
|
||||
if we need more, we need more stack. */
|
||||
if (z <= 6)
|
||||
cif->bytes = MIN_STACK_SIZE; /* min stack size */
|
||||
else
|
||||
cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
|
||||
|
||||
debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are treated like a structure. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* For the return type we have to check the size of the structures.
|
||||
If the size is smaller or equal 4 bytes, the result is given back
|
||||
in one register. If the size is smaller or equal 8 bytes than we
|
||||
return the result in two registers. But if the size is bigger than
|
||||
8 bytes, we work with pointers. */
|
||||
cif->flags = ffi_struct_type(cif->rtype);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
cif->flags = FFI_TYPE_UINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Lucky us, because of the unique PA ABI we get to do our
|
||||
own stack sizing. */
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_PA32:
|
||||
ffi_size_stack_pa32(cif);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
|
||||
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
|
||||
#ifdef PA_HPUX
|
||||
&& (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
|| cif->rtype->type == FFI_TYPE_LONGDOUBLE))
|
||||
#else
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
#endif
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_PA32:
|
||||
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
|
||||
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES
|
||||
/* This is more-or-less an inverse of ffi_call -- we have arguments on
|
||||
the stack, and we need to fill them into a cif structure and invoke
|
||||
the user function. This really ought to be in asm to make sure
|
||||
the compiler doesn't do things we don't expect. */
|
||||
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
void *rvalue;
|
||||
UINT32 ret[2]; /* function can return up to 64-bits in registers */
|
||||
ffi_type **p_arg;
|
||||
char *tmp;
|
||||
int i, avn;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
register UINT32 r28 asm("r28");
|
||||
|
||||
cif = closure->cif;
|
||||
|
||||
/* If returning via structure, callee will write to our pointer. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
rvalue = (void *)r28;
|
||||
else
|
||||
rvalue = &ret[0];
|
||||
|
||||
avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
|
||||
avn = cif->nargs;
|
||||
p_arg = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; i++)
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
|
||||
switch (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_POINTER:
|
||||
avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
#ifdef PA_LINUX
|
||||
/* The closure call is indirect. In Linux, floating point
|
||||
arguments in indirect calls with a prototype are passed
|
||||
in the floating point registers instead of the general
|
||||
registers. So, we need to replace what was previously
|
||||
stored in the current slot with the value in the
|
||||
corresponding floating point register. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 0: fstw(fr4, (void *)(stack - slot)); break;
|
||||
case 1: fstw(fr5, (void *)(stack - slot)); break;
|
||||
case 2: fstw(fr6, (void *)(stack - slot)); break;
|
||||
case 3: fstw(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
#ifdef PA_LINUX
|
||||
/* See previous comment for FFI_TYPE_FLOAT. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 1: fstd(fr5, (void *)(stack - slot)); break;
|
||||
case 3: fstd(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
if((*p_arg)->size <= 4)
|
||||
{
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else if ((*p_arg)->size <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else
|
||||
avalue[i] = (void *) *(stack - slot);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
|
||||
ret[1]);
|
||||
|
||||
/* Store the result using the lower 2 bytes of the flags. */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
*(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
*(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
*(stack - FIRST_ARG_SLOT) = ret[0];
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
*(stack - FIRST_ARG_SLOT) = ret[0];
|
||||
*(stack - FIRST_ARG_SLOT - 1) = ret[1];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fldd(rvalue, fr4);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
fldw(rvalue, fr4);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Don't need a return value, done by caller. */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT2:
|
||||
case FFI_TYPE_SMALL_STRUCT3:
|
||||
case FFI_TYPE_SMALL_STRUCT4:
|
||||
tmp = (void*)(stack - FIRST_ARG_SLOT);
|
||||
tmp += 4 - cif->rtype->size;
|
||||
memcpy((void*)tmp, &ret[0], cif->rtype->size);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT5:
|
||||
case FFI_TYPE_SMALL_STRUCT6:
|
||||
case FFI_TYPE_SMALL_STRUCT7:
|
||||
case FFI_TYPE_SMALL_STRUCT8:
|
||||
{
|
||||
unsigned int ret2[2];
|
||||
int off;
|
||||
|
||||
/* Right justify ret[0] and ret[1] */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
|
||||
case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
|
||||
case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
|
||||
default: off = 0; break;
|
||||
}
|
||||
|
||||
memset (ret2, 0, sizeof (ret2));
|
||||
memcpy ((char *)ret2 + off, ret, 8 - off);
|
||||
|
||||
*(stack - FIRST_ARG_SLOT) = ret2[0];
|
||||
*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_VOID:
|
||||
break;
|
||||
|
||||
default:
|
||||
debug(0, "assert with cif->flags: %d\n",cif->flags);
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
extern void ffi_closure_pa32(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
UINT32 *tramp = (UINT32 *)(closure->tramp);
|
||||
#ifdef PA_HPUX
|
||||
UINT32 *tmp;
|
||||
#endif
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_PA32);
|
||||
|
||||
/* Make a small trampoline that will branch to our
|
||||
handler function. Use PC-relative addressing. */
|
||||
|
||||
#ifdef PA_LINUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
|
||||
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush up 2 two lines because of
|
||||
alignment. */
|
||||
__asm__ volatile(
|
||||
"fdc 0(%0)\n\t"
|
||||
"fdc %1(%0)\n\t"
|
||||
"fic 0(%%sr4, %0)\n\t"
|
||||
"fic %1(%%sr4, %0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
:
|
||||
: "r"((unsigned long)tramp & ~31),
|
||||
"r"(32 /* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
|
||||
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
|
||||
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
|
||||
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush three lines because of alignment. */
|
||||
__asm__ volatile(
|
||||
"copy %1,%0\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"ldsid (%1),%0\n\t"
|
||||
"mtsp %0,%%sr0\n\t"
|
||||
"copy %1,%0\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
: "=&r" ((unsigned long)tmp)
|
||||
: "r" ((unsigned long)tramp & ~31),
|
||||
"r" (32/* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
#endif
|
||||
76
libffi/src/pa/ffitarget.h
Normal file
76
libffi/src/pa/ffitarget.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for hppa.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef PA_LINUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA64_HPUX
|
||||
#error "PA64_HPUX FFI is not yet implemented"
|
||||
FFI_PA64,
|
||||
FFI_DEFAULT_ABI = FFI_PA64,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef PA_LINUX
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#define FFI_TYPE_SMALL_STRUCT2 -1
|
||||
#define FFI_TYPE_SMALL_STRUCT3 -2
|
||||
#define FFI_TYPE_SMALL_STRUCT4 -3
|
||||
#define FFI_TYPE_SMALL_STRUCT5 -4
|
||||
#define FFI_TYPE_SMALL_STRUCT6 -5
|
||||
#define FFI_TYPE_SMALL_STRUCT7 -6
|
||||
#define FFI_TYPE_SMALL_STRUCT8 -7
|
||||
#endif
|
||||
367
libffi/src/pa/hpux32.S
Normal file
367
libffi/src/pa/hpux32.S
Normal file
@@ -0,0 +1,367 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
based on src/pa/linux.S
|
||||
|
||||
HP-UX PA 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 THE AUTHOR 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.LEVEL 1.1
|
||||
.SPACE $PRIVATE$
|
||||
.IMPORT $global$,DATA
|
||||
.IMPORT $$dyncall,MILLICODE
|
||||
.SUBSPA $DATA$
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)());
|
||||
*/
|
||||
|
||||
.export ffi_call_pa32,ENTRY,PRIV_LEV=3
|
||||
.import ffi_prep_args_pa32,CODE
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.align 4
|
||||
|
||||
L$FB1
|
||||
ffi_call_pa32
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
L$CFI11
|
||||
copy %sp, %r3
|
||||
L$CFI12
|
||||
|
||||
/* Setup the stack for calling prep_args...
|
||||
We want the stack to look like this:
|
||||
|
||||
[ Previous stack ] <- %r3
|
||||
|
||||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
||||
stwm %r1, 64(%sp)
|
||||
stw %r4, 12(%r3)
|
||||
L$CFI13
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 ; arg stack
|
||||
stw %arg3, -48(%r3) ; save flags we need it later
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
/* now %sp should point where %arg0 was pointing. */
|
||||
|
||||
/* Load the arguments that should be passed in registers
|
||||
The fp args are loaded by the prep_args function. */
|
||||
ldw -36(%sp), %arg0
|
||||
ldw -40(%sp), %arg1
|
||||
ldw -44(%sp), %arg2
|
||||
ldw -48(%sp), %arg3
|
||||
|
||||
/* in case the function is going to return a structure
|
||||
we need to give it a place to put the result. */
|
||||
ldw -52(%r3), %ret0 ; %ret0 <- rvalue
|
||||
ldw -56(%r3), %r22 ; %r22 <- function to call
|
||||
bl $$dyncall, %r31 ; Call the user function
|
||||
copy %r31, %rp
|
||||
|
||||
/* Prepare to store the result; we need to recover flags and rvalue. */
|
||||
ldw -48(%r3), %r21 ; r21 <- flags
|
||||
ldw -52(%r3), %r20 ; r20 <- rvalue
|
||||
|
||||
/* Store the result according to the return type. The most
|
||||
likely types should come first. */
|
||||
|
||||
L$checkint
|
||||
comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
|
||||
b L$done
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
L$checkint8
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checkint16
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
|
||||
b L$done
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
L$checkdbl
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
|
||||
b L$done
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
L$checkfloat
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
|
||||
b L$done
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
L$checkll
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b L$done
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
L$checksmst2
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst3
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst4
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
L$checksmst5
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst6
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst7
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b L$done
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$checksmst8
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
L$done
|
||||
/* all done, return */
|
||||
copy %r4, %sp ; pop arg stack
|
||||
ldw 12(%r3), %r4
|
||||
ldwm -64(%sp), %r3 ; .. and pop stack
|
||||
ldw -20(%sp), %rp
|
||||
bv %r0(%rp)
|
||||
nop
|
||||
.exit
|
||||
.procend
|
||||
L$FE1
|
||||
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
|
||||
.import ffi_closure_inner_pa32,CODE
|
||||
.align 4
|
||||
L$FB2
|
||||
ffi_closure_pa32
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
L$CFI21
|
||||
copy %sp, %r3
|
||||
L$CFI22
|
||||
stwm %r1, 64(%sp)
|
||||
|
||||
/* Put arguments onto the stack and call ffi_closure_inner. */
|
||||
stw %arg0, -36(%r3)
|
||||
stw %arg1, -40(%r3)
|
||||
stw %arg2, -44(%r3)
|
||||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
ldwm -64(%sp), %r3
|
||||
ldw -20(%sp), %rp
|
||||
ldw -36(%sp), %ret0
|
||||
bv %r0(%rp)
|
||||
ldw -40(%sp), %ret1
|
||||
.exit
|
||||
.procend
|
||||
L$FE2:
|
||||
|
||||
.SPACE $PRIVATE$
|
||||
.SUBSPA $DATA$
|
||||
|
||||
.align 4
|
||||
.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
|
||||
_GLOBAL__F_ffi_call_pa32
|
||||
L$frame1:
|
||||
.word L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
|
||||
L$SCIE1:
|
||||
.word 0x0 ;# CIE Identifier Tag
|
||||
.byte 0x1 ;# CIE Version
|
||||
.ascii "\0" ;# CIE Augmentation
|
||||
.uleb128 0x1 ;# CIE Code Alignment Factor
|
||||
.sleb128 4 ;# CIE Data Alignment Factor
|
||||
.byte 0x2 ;# CIE RA Column
|
||||
.byte 0xc ;# DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x0
|
||||
.align 4
|
||||
L$ECIE1:
|
||||
L$SFDE1:
|
||||
.word L$EFDE1-L$ASFDE1 ;# FDE Length
|
||||
L$ASFDE1:
|
||||
.word L$ASFDE1-L$frame1 ;# FDE CIE offset
|
||||
.word L$FB1 ;# FDE initial location
|
||||
.word L$FE1-L$FB1 ;# FDE address range
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI11-L$FB1
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI12-L$CFI11
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI13-L$CFI12
|
||||
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
L$EFDE1:
|
||||
|
||||
L$SFDE2:
|
||||
.word L$EFDE2-L$ASFDE2 ;# FDE Length
|
||||
L$ASFDE2:
|
||||
.word L$ASFDE2-L$frame1 ;# FDE CIE offset
|
||||
.word L$FB2 ;# FDE initial location
|
||||
.word L$FE2-L$FB2 ;# FDE address range
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI21-L$FB2
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word L$CFI22-L$CFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
L$EFDE2:
|
||||
356
libffi/src/pa/linux.S
Normal file
356
libffi/src/pa/linux.S
Normal file
@@ -0,0 +1,356 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
|
||||
HPPA 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.text
|
||||
.level 1.1
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)());
|
||||
*/
|
||||
|
||||
.export ffi_call_pa32,code
|
||||
.import ffi_prep_args_pa32,code
|
||||
|
||||
.type ffi_call_pa32, @function
|
||||
.LFB1:
|
||||
ffi_call_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
stw %rp, -20(%sp)
|
||||
copy %r3, %r1
|
||||
.LCFI11:
|
||||
|
||||
copy %sp, %r3
|
||||
.LCFI12:
|
||||
|
||||
/* Setup the stack for calling prep_args...
|
||||
We want the stack to look like this:
|
||||
|
||||
[ Previous stack ] <- %r3
|
||||
|
||||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
||||
stwm %r1, 64(%sp)
|
||||
stw %r4, 12(%r3)
|
||||
.LCFI13:
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 /* arg stack */
|
||||
stw %arg3, -48(%r3) /* save flags; we need it later */
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
/* now %sp should point where %arg0 was pointing. */
|
||||
|
||||
/* Load the arguments that should be passed in registers
|
||||
The fp args were loaded by the prep_args function. */
|
||||
ldw -36(%sp), %arg0
|
||||
ldw -40(%sp), %arg1
|
||||
ldw -44(%sp), %arg2
|
||||
ldw -48(%sp), %arg3
|
||||
|
||||
/* in case the function is going to return a structure
|
||||
we need to give it a place to put the result. */
|
||||
ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
|
||||
ldw -56(%r3), %r22 /* %r22 <- function to call */
|
||||
bl $$dyncall, %r31 /* Call the user function */
|
||||
copy %r31, %rp
|
||||
|
||||
/* Prepare to store the result; we need to recover flags and rvalue. */
|
||||
ldw -48(%r3), %r21 /* r21 <- flags */
|
||||
ldw -52(%r3), %r20 /* r20 <- rvalue */
|
||||
|
||||
/* Store the result according to the return type. */
|
||||
|
||||
.Lcheckint:
|
||||
comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
|
||||
b .Ldone
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint8:
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint16:
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
|
||||
b .Ldone
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
.Lcheckdbl:
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
|
||||
b .Ldone
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
.Lcheckfloat:
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
|
||||
b .Ldone
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
.Lcheckll:
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b .Ldone
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
.Lchecksmst2:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst3:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst4:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst5:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst6:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst7:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Lchecksmst8:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
.Ldone:
|
||||
/* all done, return */
|
||||
copy %r4, %sp /* pop arg stack */
|
||||
ldw 12(%r3), %r4
|
||||
ldwm -64(%sp), %r3 /* .. and pop stack */
|
||||
ldw -20(%sp), %rp
|
||||
bv %r0(%rp)
|
||||
nop
|
||||
.exit
|
||||
.procend
|
||||
.LFE1:
|
||||
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
.export ffi_closure_pa32,code
|
||||
.import ffi_closure_inner_pa32,code
|
||||
|
||||
.type ffi_closure_pa32, @function
|
||||
.LFB2:
|
||||
ffi_closure_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
||||
stw %rp, -20(%sp)
|
||||
.LCFI20:
|
||||
copy %r3, %r1
|
||||
.LCFI21:
|
||||
copy %sp, %r3
|
||||
.LCFI22:
|
||||
stwm %r1, 64(%sp)
|
||||
|
||||
/* Put arguments onto the stack and call ffi_closure_inner. */
|
||||
stw %arg0, -36(%r3)
|
||||
stw %arg1, -40(%r3)
|
||||
stw %arg2, -44(%r3)
|
||||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
|
||||
ldwm -64(%sp), %r3
|
||||
ldw -20(%sp), %rp
|
||||
ldw -36(%sp), %ret0
|
||||
bv %r0(%r2)
|
||||
ldw -40(%sp), %ret1
|
||||
|
||||
.exit
|
||||
.procend
|
||||
.LFE2:
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.word 0x0 ;# CIE Identifier Tag
|
||||
.byte 0x1 ;# CIE Version
|
||||
.ascii "\0" ;# CIE Augmentation
|
||||
.uleb128 0x1 ;# CIE Code Alignment Factor
|
||||
.sleb128 4 ;# CIE Data Alignment Factor
|
||||
.byte 0x2 ;# CIE RA Column
|
||||
.byte 0xc ;# DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x0
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.word .LEFDE1-.LASFDE1 ;# FDE Length
|
||||
.LASFDE1:
|
||||
.word .LASFDE1-.Lframe1 ;# FDE CIE offset
|
||||
.word .LFB1 ;# FDE initial location
|
||||
.word .LFE1-.LFB1 ;# FDE address range
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI11-.LFB1
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI12-.LCFI11
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI13-.LCFI12
|
||||
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
|
||||
.LSFDE2:
|
||||
.word .LEFDE2-.LASFDE2 ;# FDE Length
|
||||
.LASFDE2:
|
||||
.word .LASFDE2-.Lframe1 ;# FDE CIE offset
|
||||
.word .LFB2 ;# FDE initial location
|
||||
.word .LFE2-.LFB2 ;# FDE address range
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI21-.LFB2
|
||||
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
||||
.uleb128 0x0
|
||||
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
||||
.uleb128 0x2
|
||||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI22-.LCFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
.align 4
|
||||
.LEFDE2:
|
||||
225
libffi/src/powerpc/aix.S
Normal file
225
libffi/src/powerpc/aix.S
Normal file
@@ -0,0 +1,225 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
aix.S - Copyright (c) 2002 Free Software Foundation, Inc.
|
||||
based on darwin.S by John Hornkvist
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 THE AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
.set r0,0
|
||||
.set r1,1
|
||||
.set r2,2
|
||||
.set r3,3
|
||||
.set r4,4
|
||||
.set r5,5
|
||||
.set r6,6
|
||||
.set r7,7
|
||||
.set r8,8
|
||||
.set r9,9
|
||||
.set r10,10
|
||||
.set r11,11
|
||||
.set r12,12
|
||||
.set r13,13
|
||||
.set r14,14
|
||||
.set r15,15
|
||||
.set r16,16
|
||||
.set r17,17
|
||||
.set r18,18
|
||||
.set r19,19
|
||||
.set r20,20
|
||||
.set r21,21
|
||||
.set r22,22
|
||||
.set r23,23
|
||||
.set r24,24
|
||||
.set r25,25
|
||||
.set r26,26
|
||||
.set r27,27
|
||||
.set r28,28
|
||||
.set r29,29
|
||||
.set r30,30
|
||||
.set r31,31
|
||||
.set f0,0
|
||||
.set f1,1
|
||||
.set f2,2
|
||||
.set f3,3
|
||||
.set f4,4
|
||||
.set f5,5
|
||||
.set f6,6
|
||||
.set f7,7
|
||||
.set f8,8
|
||||
.set f9,9
|
||||
.set f10,10
|
||||
.set f11,11
|
||||
.set f12,12
|
||||
.set f13,13
|
||||
.set f14,14
|
||||
.set f15,15
|
||||
.set f16,16
|
||||
.set f17,17
|
||||
.set f18,18
|
||||
.set f19,19
|
||||
.set f20,20
|
||||
.set f21,21
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.file "aix.S"
|
||||
.toc
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_prep_args
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_call_AIX
|
||||
.globl .ffi_call_AIX
|
||||
.csect ffi_call_AIX[DS]
|
||||
ffi_call_AIX:
|
||||
.long .ffi_call_AIX, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_call_AIX:
|
||||
mr r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr r8,r1
|
||||
|
||||
/* Allocate the stack space we need. */
|
||||
stwux r1,r1,r4
|
||||
|
||||
/* Save registers we use. */
|
||||
mflr r9
|
||||
|
||||
stw r28,-16(r8)
|
||||
stw r29,-12(r8)
|
||||
stw r30, -8(r8)
|
||||
stw r31, -4(r8)
|
||||
|
||||
stw r9, 8(r8)
|
||||
stw r2, 20(r1)
|
||||
|
||||
/* Save arguments over call... */
|
||||
mr r31,r5 /* flags, */
|
||||
mr r30,r6 /* rvalue, */
|
||||
mr r29,r7 /* function address, */
|
||||
mr r28,r8 /* our AP. */
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
mr r4,r1
|
||||
li r9,0
|
||||
|
||||
lwz r2,4(r12)
|
||||
lwz r12,0(r12)
|
||||
mtctr r12 // r12 holds address of _ffi_prep_args
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now do the call. */
|
||||
lwz r12,0(r29)
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40,r31
|
||||
stw r2,20(r1)
|
||||
mtctr r12
|
||||
lwz r2,4(r29)
|
||||
/* Load all those argument registers. */
|
||||
// We have set up a nice stack frame, just load it into registers.
|
||||
lwz r3, 20+(1*4)(r1)
|
||||
lwz r4, 20+(2*4)(r1)
|
||||
lwz r5, 20+(3*4)(r1)
|
||||
lwz r6, 20+(4*4)(r1)
|
||||
nop
|
||||
lwz r7, 20+(5*4)(r1)
|
||||
lwz r8, 20+(6*4)(r1)
|
||||
lwz r9, 20+(7*4)(r1)
|
||||
lwz r10,20+(8*4)(r1)
|
||||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 // 2f + 0x18
|
||||
lfd f1,-16-(13*8)(r28)
|
||||
lfd f2,-16-(12*8)(r28)
|
||||
lfd f3,-16-(11*8)(r28)
|
||||
lfd f4,-16-(10*8)(r28)
|
||||
nop
|
||||
lfd f5,-16-(9*8)(r28)
|
||||
lfd f6,-16-(8*8)(r28)
|
||||
lfd f7,-16-(7*8)(r28)
|
||||
lfd f8,-16-(6*8)(r28)
|
||||
nop
|
||||
lfd f9,-16-(5*8)(r28)
|
||||
lfd f10,-16-(4*8)(r28)
|
||||
lfd f11,-16-(3*8)(r28)
|
||||
lfd f12,-16-(2*8)(r28)
|
||||
nop
|
||||
lfd f13,-16-(1*8)(r28)
|
||||
|
||||
L2:
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,r31
|
||||
|
||||
bt 30,L(done_return_value)
|
||||
bt 29,L(fp_return_value)
|
||||
stw r3,0(r30)
|
||||
bf 28,L(done_return_value)
|
||||
stw r4,4(r30)
|
||||
|
||||
/* Fall through... */
|
||||
|
||||
L(done_return_value):
|
||||
/* Restore the registers we used and return. */
|
||||
lwz r9, 8(r28)
|
||||
lwz r31, -4(r28)
|
||||
mtlr r9
|
||||
lwz r30, -8(r28)
|
||||
lwz r29,-12(r28)
|
||||
lwz r28,-16(r28)
|
||||
lwz r1,0(r1)
|
||||
blr
|
||||
|
||||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd f1,0(r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs f1,0(r30)
|
||||
b L(done_return_value)
|
||||
.long 0
|
||||
.byte 0,0,0,1,128,4,0,0
|
||||
//END(ffi_call_AIX)
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_call_DARWIN
|
||||
.globl .ffi_call_DARWIN
|
||||
.csect ffi_call_DARWIN[DS]
|
||||
ffi_call_DARWIN:
|
||||
.long .ffi_call_DARWIN, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_call_DARWIN:
|
||||
blr
|
||||
.long 0
|
||||
.byte 0,0,0,0,0,0,0,0
|
||||
//END(ffi_call_DARWIN)
|
||||
247
libffi/src/powerpc/aix_closure.S
Normal file
247
libffi/src/powerpc/aix_closure.S
Normal file
@@ -0,0 +1,247 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc.
|
||||
based on darwin_closure.S
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 THE AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
.set r0,0
|
||||
.set r1,1
|
||||
.set r2,2
|
||||
.set r3,3
|
||||
.set r4,4
|
||||
.set r5,5
|
||||
.set r6,6
|
||||
.set r7,7
|
||||
.set r8,8
|
||||
.set r9,9
|
||||
.set r10,10
|
||||
.set r11,11
|
||||
.set r12,12
|
||||
.set r13,13
|
||||
.set r14,14
|
||||
.set r15,15
|
||||
.set r16,16
|
||||
.set r17,17
|
||||
.set r18,18
|
||||
.set r19,19
|
||||
.set r20,20
|
||||
.set r21,21
|
||||
.set r22,22
|
||||
.set r23,23
|
||||
.set r24,24
|
||||
.set r25,25
|
||||
.set r26,26
|
||||
.set r27,27
|
||||
.set r28,28
|
||||
.set r29,29
|
||||
.set r30,30
|
||||
.set r31,31
|
||||
.set f0,0
|
||||
.set f1,1
|
||||
.set f2,2
|
||||
.set f3,3
|
||||
.set f4,4
|
||||
.set f5,5
|
||||
.set f6,6
|
||||
.set f7,7
|
||||
.set f8,8
|
||||
.set f9,9
|
||||
.set f10,10
|
||||
.set f11,11
|
||||
.set f12,12
|
||||
.set f13,13
|
||||
.set f14,14
|
||||
.set f15,15
|
||||
.set f16,16
|
||||
.set f17,17
|
||||
.set f18,18
|
||||
.set f19,19
|
||||
.set f20,20
|
||||
.set f21,21
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.file "aix_closure.S"
|
||||
.toc
|
||||
LC..60:
|
||||
.tc L..60[TC],L..60
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
.globl ffi_closure_ASM
|
||||
.globl .ffi_closure_ASM
|
||||
.csect ffi_closure_ASM[DS]
|
||||
|
||||
ffi_closure_ASM:
|
||||
.long .ffi_closure_ASM, TOC[tc0], 0
|
||||
.csect .text[PR]
|
||||
.ffi_closure_ASM:
|
||||
|
||||
mflr r0 /* extract return address */
|
||||
stw r0, 8(r1) /* save the return address */
|
||||
|
||||
/* 24 Bytes (Linkage Area) */
|
||||
/* 32 Bytes (params) */
|
||||
/* 104 Bytes (13*8 from FPR) */
|
||||
/* 8 Bytes (result) */
|
||||
/* 168 Bytes */
|
||||
|
||||
stwu r1,-176(r1) /* skip over caller save area
|
||||
keep stack aligned to 16 */
|
||||
|
||||
/* we want to build up an area for the parameters passed */
|
||||
/* in registers (both floating point and integer) */
|
||||
|
||||
/* we store gpr 3 to gpr 10 (aligned to 4)
|
||||
in the parents outgoing area */
|
||||
stw r3, 200(r1)
|
||||
stw r4, 204(r1)
|
||||
stw r5, 208(r1)
|
||||
stw r6, 212(r1)
|
||||
stw r7, 216(r1)
|
||||
stw r8, 220(r1)
|
||||
stw r9, 224(r1)
|
||||
stw r10, 228(r1)
|
||||
|
||||
/* next save fpr 1 to fpr 13 (aligned to 8) */
|
||||
stfd f1, 56(r1)
|
||||
stfd f2, 64(r1)
|
||||
stfd f3, 72(r1)
|
||||
stfd f4, 80(r1)
|
||||
stfd f5, 88(r1)
|
||||
stfd f6, 96(r1)
|
||||
stfd f7, 104(r1)
|
||||
stfd f8, 112(r1)
|
||||
stfd f9, 120(r1)
|
||||
stfd f10, 128(r1)
|
||||
stfd f11, 136(r1)
|
||||
stfd f12, 144(r1)
|
||||
stfd f13, 152(r1)
|
||||
|
||||
/* set up registers for the routine that actually does the work */
|
||||
/* get the context pointer from the trampoline */
|
||||
mr r3,r11
|
||||
|
||||
/* now load up the pointer to the result storage */
|
||||
addi r4,r1,160
|
||||
|
||||
/* now load up the pointer to the saved gpr registers */
|
||||
addi r5,r1,200
|
||||
|
||||
/* now load up the pointer to the saved fpr registers */
|
||||
addi r6,r1,56
|
||||
|
||||
/* make the call */
|
||||
bl .ffi_closure_helper_DARWIN
|
||||
nop
|
||||
|
||||
/* now r3 contains the return type */
|
||||
/* so use it to look up in a table */
|
||||
/* so we know how to deal with each type */
|
||||
|
||||
/* look up the proper starting point in table */
|
||||
/* by using return type as offset */
|
||||
addi r5,r1,160 /* get pointer to results area */
|
||||
lwz r4,LC..60(2) /* get address of jump table */
|
||||
slwi r3,r3,2 /* now multiply return type by 4 */
|
||||
lwzx r3,r4,r3 /* get the contents of that table value */
|
||||
add r3,r3,r4 /* add contents of table to table address */
|
||||
mtctr r3
|
||||
bctr /* jump to it */
|
||||
|
||||
L..60:
|
||||
.long L..44-L..60 /* FFI_TYPE_VOID */
|
||||
.long L..50-L..60 /* FFI_TYPE_INT */
|
||||
.long L..47-L..60 /* FFI_TYPE_FLOAT */
|
||||
.long L..46-L..60 /* FFI_TYPE_DOUBLE */
|
||||
.long L..46-L..60 /* FFI_TYPE_LONGDOUBLE */
|
||||
.long L..56-L..60 /* FFI_TYPE_UINT8 */
|
||||
.long L..55-L..60 /* FFI_TYPE_SINT8 */
|
||||
.long L..58-L..60 /* FFI_TYPE_UINT16 */
|
||||
.long L..57-L..60 /* FFI_TYPE_SINT16 */
|
||||
.long L..50-L..60 /* FFI_TYPE_UINT32 */
|
||||
.long L..50-L..60 /* FFI_TYPE_SINT32 */
|
||||
.long L..48-L..60 /* FFI_TYPE_UINT64 */
|
||||
.long L..48-L..60 /* FFI_TYPE_SINT64 */
|
||||
.long L..44-L..60 /* FFI_TYPE_STRUCT */
|
||||
.long L..50-L..60 /* FFI_TYPE_POINTER */
|
||||
|
||||
|
||||
/* case double */
|
||||
L..46:
|
||||
lfd f1,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case float */
|
||||
L..47:
|
||||
lfs f1,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case long long */
|
||||
L..48:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b L..44
|
||||
|
||||
/* case default / int32 / pointer */
|
||||
L..50:
|
||||
lwz r3,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case signed int8 */
|
||||
L..55:
|
||||
addi r5,r5,3
|
||||
lbz r3,0(r5)
|
||||
slwi r3,r3,24
|
||||
srawi r3,r3,24
|
||||
b L..44
|
||||
|
||||
/* case unsigned int8 */
|
||||
L..56:
|
||||
addi r5,r5,3
|
||||
lbz r3,0(r5)
|
||||
b L..44
|
||||
|
||||
/* case signed int16 */
|
||||
L..57:
|
||||
addi r5,r5,2
|
||||
lhz r3,0(r5)
|
||||
extsh r3,r3
|
||||
b L..44
|
||||
|
||||
/* case unsigned int16 */
|
||||
L..58:
|
||||
addi r5,r5,2
|
||||
lhz r3,0(r5)
|
||||
|
||||
/* case void / done */
|
||||
L..44:
|
||||
addi r1,r1,176 /* restore stack pointer */
|
||||
lwz r0,8(r1) /* get return address */
|
||||
mtlr r0 /* reset link register */
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
@@ -1,9 +1,7 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
asm.h - Copyright (c) 1998 Geoffrey Keating
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
$Id: asm.h,v 1.1 2001/04/22 18:28:36 green Exp $
|
||||
PowerPC Assembly glue.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -50,12 +48,12 @@
|
||||
#ifdef PIC
|
||||
#define CALL_MCOUNT \
|
||||
.pushsection; \
|
||||
.section ".data"; \
|
||||
.section ".data"; \
|
||||
.align ALIGNARG(2); \
|
||||
0:.long 0; \
|
||||
.previous; \
|
||||
mflr %r0; \
|
||||
stw %r0,4(%r1); \
|
||||
stw %r0,4(%r1); \
|
||||
bl _GLOBAL_OFFSET_TABLE_@local-4; \
|
||||
mflr %r11; \
|
||||
lwz %r0,0b@got(%r11); \
|
||||
@@ -67,8 +65,8 @@
|
||||
0:.long 0; \
|
||||
.previous; \
|
||||
mflr %r0; \
|
||||
lis %r11,0b@ha; \
|
||||
stw %r0,4(%r1); \
|
||||
lis %r11,0b@ha; \
|
||||
stw %r0,4(%r1); \
|
||||
addi %r0,%r11,0b@l; \
|
||||
bl JUMPTARGET(_mcount);
|
||||
#endif /* PIC */
|
||||
@@ -125,4 +123,3 @@
|
||||
|
||||
/* Local labels stripped out by the linker. */
|
||||
#define L(x) .L##x
|
||||
|
||||
245
libffi/src/powerpc/darwin.S
Normal file
245
libffi/src/powerpc/darwin.S
Normal file
@@ -0,0 +1,245 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
||||
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 THE AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if defined(__ppc64__)
|
||||
#define MODE_CHOICE(x, y) y
|
||||
#else
|
||||
#define MODE_CHOICE(x, y) x
|
||||
#endif
|
||||
|
||||
#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
|
||||
|
||||
#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#define JUMPTARGET(name) name
|
||||
#define L(x) x
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_prep_args
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_call_DARWIN
|
||||
.text
|
||||
.align 2
|
||||
_ffi_call_DARWIN:
|
||||
LFB0:
|
||||
mr r12,r8 /* We only need r12 until the call,
|
||||
so it doesn't have to be saved. */
|
||||
LFB1:
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr r8,r1
|
||||
LCFI0:
|
||||
/* Allocate the stack space we need. */
|
||||
stwux r1,r1,r4
|
||||
|
||||
/* Save registers we use. */
|
||||
mflr r9
|
||||
|
||||
stw r28,-16(r8)
|
||||
stw r29,-12(r8)
|
||||
stw r30,-8(r8)
|
||||
stw r31,-4(r8)
|
||||
|
||||
stw r9,8(r8)
|
||||
stw r2,20(r1)
|
||||
LCFI1:
|
||||
|
||||
/* Save arguments over call. */
|
||||
mr r31,r5 /* flags, */
|
||||
mr r30,r6 /* rvalue, */
|
||||
mr r29,r7 /* function address, */
|
||||
mr r28,r8 /* our AP. */
|
||||
LCFI2:
|
||||
/* Call ffi_prep_args. */
|
||||
mr r4,r1
|
||||
li r9,0
|
||||
|
||||
mtctr r12 /* r12 holds address of _ffi_prep_args. */
|
||||
bctrl
|
||||
lwz r2,20(r1)
|
||||
|
||||
/* Now do the call.
|
||||
Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40,r31
|
||||
/* Get the address to call into CTR. */
|
||||
mtctr r29
|
||||
/* Load all those argument registers.
|
||||
We have set up a nice stack frame, just load it into registers. */
|
||||
lwz r3,20+(1*4)(r1)
|
||||
lwz r4,20+(2*4)(r1)
|
||||
lwz r5,20+(3*4)(r1)
|
||||
lwz r6,20+(4*4)(r1)
|
||||
nop
|
||||
lwz r7,20+(5*4)(r1)
|
||||
lwz r8,20+(6*4)(r1)
|
||||
lwz r9,20+(7*4)(r1)
|
||||
lwz r10,20+(8*4)(r1)
|
||||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 /* No floats to load. */
|
||||
lfd f1,-16-(13*8)(r28)
|
||||
lfd f2,-16-(12*8)(r28)
|
||||
lfd f3,-16-(11*8)(r28)
|
||||
lfd f4,-16-(10*8)(r28)
|
||||
nop
|
||||
lfd f5,-16-(9*8)(r28)
|
||||
lfd f6,-16-(8*8)(r28)
|
||||
lfd f7,-16-(7*8)(r28)
|
||||
lfd f8,-16-(6*8)(r28)
|
||||
nop
|
||||
lfd f9,-16-(5*8)(r28)
|
||||
lfd f10,-16-(4*8)(r28)
|
||||
lfd f11,-16-(3*8)(r28)
|
||||
lfd f12,-16-(2*8)(r28)
|
||||
nop
|
||||
lfd f13,-16-(1*8)(r28)
|
||||
|
||||
L2:
|
||||
mr r12,r29 /* Put the target address in r12 as specified. */
|
||||
mtctr r12
|
||||
nop
|
||||
nop
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,r31
|
||||
|
||||
bt 30,L(done_return_value)
|
||||
bt 29,L(fp_return_value)
|
||||
stw r3,0(r30)
|
||||
bf 28,L(done_return_value)
|
||||
stw r4,4(r30)
|
||||
|
||||
/* Fall through. */
|
||||
|
||||
L(done_return_value):
|
||||
/* Restore the registers we used and return. */
|
||||
lwz r9,8(r28)
|
||||
lwz r31,-4(r28)
|
||||
mtlr r9
|
||||
lwz r30,-8(r28)
|
||||
lwz r29,-12(r28)
|
||||
lwz r28,-16(r28)
|
||||
lwz r1,0(r1)
|
||||
blr
|
||||
|
||||
L(fp_return_value):
|
||||
/* Do we have long double to store? */
|
||||
bf 31,L(fd_return_value)
|
||||
stfd f1,0(r30)
|
||||
stfd f2,8(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(fd_return_value):
|
||||
/* Do we have double to store? */
|
||||
bf 28,L(float_return_value)
|
||||
stfd f1,0(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(float_return_value):
|
||||
/* We only have a float to store. */
|
||||
stfs f1,0(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
LFE1:
|
||||
/* END(_ffi_call_DARWIN) */
|
||||
|
||||
/* Provide a null definition of _ffi_call_AIX. */
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_call_AIX
|
||||
.text
|
||||
.align 2
|
||||
_ffi_call_AIX:
|
||||
blr
|
||||
/* END(_ffi_call_AIX) */
|
||||
|
||||
.data
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_call_DARWIN.eh
|
||||
_ffi_call_DARWIN.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB0
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0xd ; DW_CFA_def_cfa_register
|
||||
.byte 0x08 ; uleb128 0x08
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI1-LCFI0
|
||||
.long L$set$5
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.byte 0x9f ; DW_CFA_offset, column 0x1f
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x9e ; DW_CFA_offset, column 0x1e
|
||||
.byte 0x2 ; uleb128 0x2
|
||||
.byte 0x9d ; DW_CFA_offset, column 0x1d
|
||||
.byte 0x3 ; uleb128 0x3
|
||||
.byte 0x9c ; DW_CFA_offset, column 0x1c
|
||||
.byte 0x4 ; uleb128 0x4
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$6,LCFI2-LCFI1
|
||||
.long L$set$6
|
||||
.byte 0xd ; DW_CFA_def_cfa_register
|
||||
.byte 0x1c ; uleb128 0x1c
|
||||
.align LOG2_GPR_BYTES
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB0$non_lazy_ptr:
|
||||
.g_long LFB0
|
||||
317
libffi/src/powerpc/darwin_closure.S
Normal file
317
libffi/src/powerpc/darwin_closure.S
Normal file
@@ -0,0 +1,317 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 THE AUTHOR 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
|
||||
#define L(x) x
|
||||
|
||||
#if defined(__ppc64__)
|
||||
#define MODE_CHOICE(x, y) y
|
||||
#else
|
||||
#define MODE_CHOICE(x, y) x
|
||||
#endif
|
||||
|
||||
#define lgu MODE_CHOICE(lwzu, ldu)
|
||||
|
||||
#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
|
||||
|
||||
#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
|
||||
|
||||
.file "darwin_closure.S"
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
.globl _ffi_closure_ASM
|
||||
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
_ffi_closure_ASM:
|
||||
LFB1:
|
||||
mflr r0 /* extract return address */
|
||||
stw r0,8(r1) /* save the return address */
|
||||
LCFI0:
|
||||
/* 24 Bytes (Linkage Area)
|
||||
32 Bytes (outgoing parameter area, always reserved)
|
||||
104 Bytes (13*8 from FPR)
|
||||
16 Bytes (result)
|
||||
176 Bytes */
|
||||
|
||||
stwu r1,-176(r1) /* skip over caller save area
|
||||
keep stack aligned to 16. */
|
||||
LCFI1:
|
||||
/* We want to build up an area for the parameters passed
|
||||
in registers. (both floating point and integer) */
|
||||
|
||||
/* We store gpr 3 to gpr 10 (aligned to 4)
|
||||
in the parents outgoing area. */
|
||||
stw r3,200(r1)
|
||||
stw r4,204(r1)
|
||||
stw r5,208(r1)
|
||||
stw r6,212(r1)
|
||||
stw r7,216(r1)
|
||||
stw r8,220(r1)
|
||||
stw r9,224(r1)
|
||||
stw r10,228(r1)
|
||||
|
||||
/* We save fpr 1 to fpr 13. (aligned to 8) */
|
||||
stfd f1,56(r1)
|
||||
stfd f2,64(r1)
|
||||
stfd f3,72(r1)
|
||||
stfd f4,80(r1)
|
||||
stfd f5,88(r1)
|
||||
stfd f6,96(r1)
|
||||
stfd f7,104(r1)
|
||||
stfd f8,112(r1)
|
||||
stfd f9,120(r1)
|
||||
stfd f10,128(r1)
|
||||
stfd f11,136(r1)
|
||||
stfd f12,144(r1)
|
||||
stfd f13,152(r1)
|
||||
|
||||
/* Set up registers for the routine that actually does the work
|
||||
get the context pointer from the trampoline. */
|
||||
mr r3,r11
|
||||
|
||||
/* Now load up the pointer to the result storage. */
|
||||
addi r4,r1,160
|
||||
|
||||
/* Now load up the pointer to the saved gpr registers. */
|
||||
addi r5,r1,200
|
||||
|
||||
/* Now load up the pointer to the saved fpr registers. */
|
||||
addi r6,r1,56
|
||||
|
||||
/* Make the call. */
|
||||
bl Lffi_closure_helper_DARWIN$stub
|
||||
|
||||
/* Now r3 contains the return type
|
||||
so use it to look up in a table
|
||||
so we know how to deal with each type. */
|
||||
|
||||
/* Look up the proper starting point in table
|
||||
by using return type as offset. */
|
||||
addi r5,r1,160 /* Get pointer to results area. */
|
||||
bl Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR. */
|
||||
mflr r4 /* Move to r4. */
|
||||
slwi r3,r3,4 /* Now multiply return type by 16. */
|
||||
add r3,r3,r4 /* Add contents of table to table address. */
|
||||
mtctr r3
|
||||
bctr /* Jump to it. */
|
||||
LFE1:
|
||||
/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
(4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
first. */
|
||||
|
||||
.align 4
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
Lget_ret_type0_addr:
|
||||
blrl
|
||||
|
||||
/* case FFI_TYPE_VOID */
|
||||
Lret_type0:
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_INT */
|
||||
Lret_type1:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_FLOAT */
|
||||
Lret_type2:
|
||||
lfs f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_DOUBLE */
|
||||
Lret_type3:
|
||||
lfd f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_LONGDOUBLE */
|
||||
Lret_type4:
|
||||
lfd f1,0(r5)
|
||||
lfd f2,8(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT8 */
|
||||
Lret_type5:
|
||||
lbz r3,3(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT8 */
|
||||
Lret_type6:
|
||||
lbz r3,3(r5)
|
||||
extsb r3,r3
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT16 */
|
||||
Lret_type7:
|
||||
lhz r3,2(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT16 */
|
||||
Lret_type8:
|
||||
lha r3,2(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT32 */
|
||||
Lret_type9:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT32 */
|
||||
Lret_type10:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT64 */
|
||||
Lret_type11:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT64 */
|
||||
Lret_type12:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_STRUCT */
|
||||
Lret_type13:
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_POINTER */
|
||||
Lret_type14:
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case done */
|
||||
Lfinish:
|
||||
addi r1,r1,176 /* Restore stack pointer. */
|
||||
lwz r0,8(r1) /* Get return address. */
|
||||
mtlr r0 /* Reset link register. */
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
|
||||
.data
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_closure_ASM.eh
|
||||
_ffi_closure_ASM.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB1
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI1-LCFI0
|
||||
.long L$set$3
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 176,1 ; uleb128 176
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align LOG2_GPR_BYTES
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LDFCM0:
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
Lffi_closure_helper_DARWIN$stub:
|
||||
#if 1
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi_closure_helper_DARWIN
|
||||
LO$ffi_closure_helper_DARWIN:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
.g_long dyld_stub_binding_helper
|
||||
#endif
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
1298
libffi/src/powerpc/ffi.c
Normal file
1298
libffi/src/powerpc/ffi.c
Normal file
File diff suppressed because it is too large
Load Diff
799
libffi/src/powerpc/ffi_darwin.c
Normal file
799
libffi/src/powerpc/ffi_darwin.c
Normal file
@@ -0,0 +1,799 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi_darwin.c
|
||||
|
||||
Copyright (C) 1998 Geoffrey Keating
|
||||
Copyright (C) 2001 John Hornkvist
|
||||
Copyright (C) 2002, 2006 Free Software Foundation, Inc.
|
||||
|
||||
FFI support for Darwin and AIX.
|
||||
|
||||
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 THE AUTHOR 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>
|
||||
|
||||
extern void ffi_closure_ASM(void);
|
||||
|
||||
enum {
|
||||
/* The assembly depends on these exact flags. */
|
||||
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||
FLAG_RETURNS_FP = 1 << (31-29),
|
||||
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||
FLAG_RETURNS_128BITS = 1 << (31-31),
|
||||
|
||||
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
||||
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
||||
};
|
||||
|
||||
/* About the DARWIN ABI. */
|
||||
enum {
|
||||
NUM_GPR_ARG_REGISTERS = 8,
|
||||
NUM_FPR_ARG_REGISTERS = 13
|
||||
};
|
||||
enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments.
|
||||
|
||||
The stack layout we want looks like this:
|
||||
|
||||
| Return address from ffi_call_DARWIN | higher addresses
|
||||
|--------------------------------------------|
|
||||
| Previous backchain pointer 4 | stack pointer here
|
||||
|--------------------------------------------|<+ <<< on entry to
|
||||
| Saved r28-r31 4*4 | | ffi_call_DARWIN
|
||||
|--------------------------------------------| |
|
||||
| Parameters (at least 8*4=32) | |
|
||||
|--------------------------------------------| |
|
||||
| Space for GPR2 4 | |
|
||||
|--------------------------------------------| | stack |
|
||||
| Reserved 2*4 | | grows |
|
||||
|--------------------------------------------| | down V
|
||||
| Space for callee's LR 4 | |
|
||||
|--------------------------------------------| | lower addresses
|
||||
| Saved CR 4 | |
|
||||
|--------------------------------------------| | stack pointer here
|
||||
| Current backchain pointer 4 |-/ during
|
||||
|--------------------------------------------| <<< ffi_call_DARWIN
|
||||
|
||||
*/
|
||||
|
||||
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
||||
/* 'stacktop' points at the previous backchain pointer. */
|
||||
unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
|
||||
|
||||
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
||||
we use FPR registers. */
|
||||
double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
|
||||
int fparg_count = 0;
|
||||
|
||||
|
||||
/* 'next_arg' grows up as we put parameters in it. */
|
||||
unsigned *next_arg = stack + 6; /* 6 reserved positions. */
|
||||
|
||||
int i = ecif->cif->nargs;
|
||||
double double_tmp;
|
||||
void **p_argv = ecif->avalue;
|
||||
unsigned gprvalue;
|
||||
ffi_type** ptr = ecif->cif->arg_types;
|
||||
char *dest_cpy;
|
||||
unsigned size_al = 0;
|
||||
|
||||
/* Check that everything starts aligned properly. */
|
||||
FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
|
||||
FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
|
||||
FFI_ASSERT((bytes & 0xF) == 0);
|
||||
|
||||
/* Deal with return values that are actually pass-by-reference.
|
||||
Rule:
|
||||
Return values are referenced by r3, so r4 is the first parameter. */
|
||||
|
||||
if (flags & FLAG_RETVAL_REFERENCE)
|
||||
*next_arg++ = (unsigned)(char *)ecif->rvalue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
for (;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
/* If a floating-point parameter appears before all of the general-
|
||||
purpose registers are filled, the corresponding GPRs that match
|
||||
the size of the floating-point parameter are skipped. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
double_tmp = *(float *)*p_argv;
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg++;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
double_tmp = *(double *)*p_argv;
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
double_tmp = ((double *)*p_argv)[0];
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
double_tmp = ((double *)*p_argv)[1];
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
*(double *)next_arg = double_tmp;
|
||||
else
|
||||
*fpr_base++ = double_tmp;
|
||||
next_arg += 2;
|
||||
fparg_count++;
|
||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
*(long long *)next_arg = *(long long *)*p_argv;
|
||||
next_arg+=2;
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
gprvalue = *(unsigned char *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_SINT8:
|
||||
gprvalue = *(signed char *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_UINT16:
|
||||
gprvalue = *(unsigned short *)*p_argv;
|
||||
goto putgpr;
|
||||
case FFI_TYPE_SINT16:
|
||||
gprvalue = *(signed short *)*p_argv;
|
||||
goto putgpr;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
dest_cpy = (char *) next_arg;
|
||||
|
||||
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
||||
SI 4 bytes) are aligned as if they were those modes.
|
||||
Structures with 3 byte in size are padded upwards. */
|
||||
size_al = (*ptr)->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word.
|
||||
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
|
||||
if ((*ptr)->elements[0]->type == 3)
|
||||
size_al = ALIGN((*ptr)->size, 8);
|
||||
if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
|
||||
dest_cpy += 4 - size_al;
|
||||
|
||||
memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
|
||||
next_arg += (size_al + 3) / 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
gprvalue = *(unsigned *)*p_argv;
|
||||
putgpr:
|
||||
*next_arg++ = gprvalue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that we didn't overrun the stack... */
|
||||
//FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
|
||||
//FFI_ASSERT((unsigned *)fpr_base
|
||||
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
}
|
||||
|
||||
/* Adjust the size of S to be correct for Darwin.
|
||||
On Darwin, the first field of a structure has natural alignment. */
|
||||
|
||||
static void
|
||||
darwin_adjust_aggregate_sizes (ffi_type *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->type != FFI_TYPE_STRUCT)
|
||||
return;
|
||||
|
||||
s->size = 0;
|
||||
for (i = 0; s->elements[i] != NULL; i++)
|
||||
{
|
||||
ffi_type *p;
|
||||
int align;
|
||||
|
||||
p = s->elements[i];
|
||||
darwin_adjust_aggregate_sizes (p);
|
||||
if (i == 0
|
||||
&& (p->type == FFI_TYPE_UINT64
|
||||
|| p->type == FFI_TYPE_SINT64
|
||||
|| p->type == FFI_TYPE_DOUBLE
|
||||
|| p->alignment == 8))
|
||||
align = 8;
|
||||
else if (p->alignment == 16 || p->alignment < 4)
|
||||
align = p->alignment;
|
||||
else
|
||||
align = 4;
|
||||
s->size = ALIGN(s->size, align) + p->size;
|
||||
}
|
||||
|
||||
s->size = ALIGN(s->size, s->alignment);
|
||||
|
||||
if (s->elements[0]->type == FFI_TYPE_UINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_SINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_DOUBLE
|
||||
|| s->elements[0]->alignment == 8)
|
||||
s->alignment = s->alignment > 8 ? s->alignment : 8;
|
||||
/* Do not add additional tail padding. */
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* All this is for the DARWIN ABI. */
|
||||
int i;
|
||||
ffi_type **ptr;
|
||||
unsigned bytes;
|
||||
int fparg_count = 0, intarg_count = 0;
|
||||
unsigned flags = 0;
|
||||
unsigned size_al = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
All the calculation of structure sizes will also be wrong.
|
||||
Redo the calculation for DARWIN. */
|
||||
|
||||
if (cif->abi == FFI_DARWIN)
|
||||
{
|
||||
darwin_adjust_aggregate_sizes (cif->rtype);
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
darwin_adjust_aggregate_sizes (cif->arg_types[i]);
|
||||
}
|
||||
|
||||
/* Space for the frame pointer, callee's LR, CR, etc, and for
|
||||
the asm's temp regs. */
|
||||
|
||||
bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
|
||||
|
||||
/* Return value handling. The rules are as follows:
|
||||
- 32-bit (or less) integer values are returned in gpr3;
|
||||
- Structures of size <= 4 bytes also returned in gpr3;
|
||||
- 64-bit integer values and structures between 5 and 8 bytes are returned
|
||||
in gpr3 and gpr4;
|
||||
- Single/double FP values are returned in fpr1;
|
||||
- Long double FP (if not equivalent to double) values are returned in
|
||||
fpr1 and fpr2;
|
||||
- Larger structures values are allocated space and a pointer is passed
|
||||
as the first argument. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
flags |= FLAG_RETURNS_128BITS;
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
/* Fall through. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
flags |= FLAG_RETVAL_REFERENCE;
|
||||
flags |= FLAG_RETURNS_NOTHING;
|
||||
intarg_count++;
|
||||
break;
|
||||
case FFI_TYPE_VOID:
|
||||
flags |= FLAG_RETURNS_NOTHING;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Returns 32-bit integer, or similar. Nothing to do here. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
||||
first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
|
||||
goes on the stack. Structures are passed as a pointer to a copy of
|
||||
the structure. Stuff on the stack needs to keep proper alignment. */
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fparg_count++;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
8-byte-aligned. */
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
||||
&& intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
fparg_count += 2;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
8-byte-aligned. */
|
||||
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
||||
&& intarg_count%2 != 0)
|
||||
intarg_count++;
|
||||
intarg_count +=2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
/* 'long long' arguments are passed as two words, but
|
||||
either both words must fit in registers or both go
|
||||
on the stack. If they go on the stack, they must
|
||||
be 8-byte-aligned. */
|
||||
if (intarg_count == NUM_GPR_ARG_REGISTERS-1
|
||||
|| (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0))
|
||||
intarg_count++;
|
||||
intarg_count += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
size_al = (*ptr)->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word.
|
||||
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
|
||||
if ((*ptr)->elements[0]->type == 3)
|
||||
size_al = ALIGN((*ptr)->size, 8);
|
||||
intarg_count += (size_al + 3) / 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Everything else is passed as a 4-byte word in a GPR, either
|
||||
the object itself or a pointer to it. */
|
||||
intarg_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fparg_count != 0)
|
||||
flags |= FLAG_FP_ARGUMENTS;
|
||||
|
||||
/* Space for the FPR registers, if needed. */
|
||||
if (fparg_count != 0)
|
||||
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
||||
|
||||
/* Stack space. */
|
||||
if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
|
||||
bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
|
||||
else
|
||||
bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
|
||||
|
||||
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
||||
bytes = (bytes + 15) & ~0xF;
|
||||
|
||||
cif->flags = flags;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(), void (*fn2)());
|
||||
extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(), void (*fn2)());
|
||||
|
||||
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_AIX:
|
||||
ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
case FFI_DARWIN:
|
||||
ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_icache(char *);
|
||||
static void flush_range(char *, int);
|
||||
|
||||
/* The layout of a function descriptor. A C function pointer really
|
||||
points to one of these. */
|
||||
|
||||
typedef struct aix_fd_struct {
|
||||
void *code_pointer;
|
||||
void *toc;
|
||||
} aix_fd;
|
||||
|
||||
/* here I'd like to add the stack frame layout we use in darwin_closure.S
|
||||
and aix_clsoure.S
|
||||
|
||||
SP previous -> +---------------------------------------+ <--- child frame
|
||||
| back chain to caller 4 |
|
||||
+---------------------------------------+ 4
|
||||
| saved CR 4 |
|
||||
+---------------------------------------+ 8
|
||||
| saved LR 4 |
|
||||
+---------------------------------------+ 12
|
||||
| reserved for compilers 4 |
|
||||
+---------------------------------------+ 16
|
||||
| reserved for binders 4 |
|
||||
+---------------------------------------+ 20
|
||||
| saved TOC pointer 4 |
|
||||
+---------------------------------------+ 24
|
||||
| always reserved 8*4=32 (previous GPRs)|
|
||||
| according to the linkage convention |
|
||||
| from AIX |
|
||||
+---------------------------------------+ 56
|
||||
| our FPR area 13*8=104 |
|
||||
| f1 |
|
||||
| . |
|
||||
| f13 |
|
||||
+---------------------------------------+ 160
|
||||
| result area 8 |
|
||||
+---------------------------------------+ 168
|
||||
| alignement to the next multiple of 16 |
|
||||
SP current --> +---------------------------------------+ 176 <- parent frame
|
||||
| back chain to caller 4 |
|
||||
+---------------------------------------+ 180
|
||||
| saved CR 4 |
|
||||
+---------------------------------------+ 184
|
||||
| saved LR 4 |
|
||||
+---------------------------------------+ 188
|
||||
| reserved for compilers 4 |
|
||||
+---------------------------------------+ 192
|
||||
| reserved for binders 4 |
|
||||
+---------------------------------------+ 196
|
||||
| saved TOC pointer 4 |
|
||||
+---------------------------------------+ 200
|
||||
| always reserved 8*4=32 we store our |
|
||||
| GPRs here |
|
||||
| r3 |
|
||||
| . |
|
||||
| r10 |
|
||||
+---------------------------------------+ 232
|
||||
| overflow part |
|
||||
+---------------------------------------+ xxx
|
||||
| ???? |
|
||||
+---------------------------------------+ xxx
|
||||
|
||||
*/
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
struct ffi_aix_trampoline_struct *tramp_aix;
|
||||
aix_fd *fd;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_DARWIN:
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_DARWIN);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
||||
tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
|
||||
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
|
||||
tramp[6] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[7] = 0x7d8903a6; /* mtctr r12 */
|
||||
tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
|
||||
tramp[3] = (unsigned long) closure; /* context */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. Only necessary on Darwin. */
|
||||
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
break;
|
||||
|
||||
case FFI_AIX:
|
||||
|
||||
tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
|
||||
fd = (aix_fd *)(void *)ffi_closure_ASM;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_AIX);
|
||||
|
||||
tramp_aix->code_pointer = fd->code_pointer;
|
||||
tramp_aix->toc = fd->toc;
|
||||
tramp_aix->static_chain = closure;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
default:
|
||||
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
flush_icache(char *addr)
|
||||
{
|
||||
#ifndef _AIX
|
||||
__asm__ volatile (
|
||||
"dcbf 0,%0\n"
|
||||
"\tsync\n"
|
||||
"\ticbi 0,%0\n"
|
||||
"\tsync\n"
|
||||
"\tisync"
|
||||
: : "r"(addr) : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
flush_range(char * addr1, int size)
|
||||
{
|
||||
#define MIN_LINE_SIZE 32
|
||||
int i;
|
||||
for (i = 0; i < size; i += MIN_LINE_SIZE)
|
||||
flush_icache(addr1+i);
|
||||
flush_icache(addr1+size-1);
|
||||
}
|
||||
|
||||
typedef union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} ffi_dblfl;
|
||||
|
||||
int ffi_closure_helper_DARWIN (ffi_closure*, void*,
|
||||
unsigned long*, ffi_dblfl*);
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_ASM, and on
|
||||
entry, r11 holds the address of the closure.
|
||||
After storing the registers that could possibly contain
|
||||
parameters to be passed into the stack frame and setting
|
||||
up space for a return value, ffi_closure_ASM invokes the
|
||||
following helper function to do most of the work. */
|
||||
|
||||
int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
||||
unsigned long * pgr, ffi_dblfl * pfr)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly
|
||||
pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
|
||||
pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
|
||||
|
||||
typedef double ldbits[2];
|
||||
|
||||
union ldu
|
||||
{
|
||||
ldbits lb;
|
||||
long double ld;
|
||||
};
|
||||
|
||||
void ** avalue;
|
||||
ffi_type ** arg_types;
|
||||
long i, avn;
|
||||
long nf; /* number of floating registers already used. */
|
||||
long ng; /* number of general registers already used. */
|
||||
ffi_cif * cif;
|
||||
double temp;
|
||||
unsigned size_al;
|
||||
union ldu temp_ld;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
nf = 0;
|
||||
ng = 0;
|
||||
|
||||
/* Copy the caller's structure return value address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) *pgr;
|
||||
pgr++;
|
||||
ng++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
while (i < avn)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = (char *) pgr + 3;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = (char *) pgr + 2;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
||||
SI 4 bytes) are aligned as if they were those modes. */
|
||||
size_al = arg_types[i]->size;
|
||||
/* If the first member of the struct is a double, then align
|
||||
the struct to double-word.
|
||||
Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
|
||||
if (arg_types[i]->elements[0]->type == 3)
|
||||
size_al = ALIGN(arg_types[i]->size, 8);
|
||||
if (size_al < 3 && cif->abi == FFI_DARWIN)
|
||||
avalue[i] = (void*) pgr + 4 - size_al;
|
||||
else
|
||||
avalue[i] = (void*) pgr;
|
||||
ng += (size_al + 3) / 4;
|
||||
pgr += (size_al + 3) / 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
/* Long long ints are passed in two gpr's. */
|
||||
avalue[i] = pgr;
|
||||
ng += 2;
|
||||
pgr += 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* A float value consumes a GPR.
|
||||
There are 13 64bit floating point registers. */
|
||||
if (nf < NUM_FPR_ARG_REGISTERS)
|
||||
{
|
||||
temp = pfr->d;
|
||||
pfr->f = (float)temp;
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
}
|
||||
nf++;
|
||||
ng++;
|
||||
pgr++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* A double value consumes two GPRs.
|
||||
There are 13 64bit floating point registers. */
|
||||
if (nf < NUM_FPR_ARG_REGISTERS)
|
||||
{
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
}
|
||||
nf++;
|
||||
ng += 2;
|
||||
pgr += 2;
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* A long double value consumes four GPRs and two FPRs.
|
||||
There are 13 64bit floating point registers. */
|
||||
if (nf < NUM_FPR_ARG_REGISTERS - 1)
|
||||
{
|
||||
avalue[i] = pfr;
|
||||
pfr += 2;
|
||||
}
|
||||
/* Here we have the situation where one part of the long double
|
||||
is stored in fpr13 and the other part is already on the stack.
|
||||
We use a union to pass the long double to avalue[i]. */
|
||||
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
|
||||
{
|
||||
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
|
||||
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
|
||||
avalue[i] = &temp_ld.ld;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
}
|
||||
nf += 2;
|
||||
ng += 4;
|
||||
pgr += 4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_ASM to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
105
libffi/src/powerpc/ffitarget.h
Normal file
105
libffi/src/powerpc/ffitarget.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for PowerPC.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#if defined (POWERPC) && defined (__powerpc64__)
|
||||
#define POWERPC64
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef POWERPC
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_LINUX,
|
||||
# ifdef POWERPC64
|
||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||
# else
|
||||
# if __LDBL_MANT_DIG__ == 106
|
||||
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_AIX
|
||||
FFI_AIX,
|
||||
FFI_DARWIN,
|
||||
FFI_DEFAULT_ABI = FFI_AIX,
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_DARWIN
|
||||
FFI_AIX,
|
||||
FFI_DARWIN,
|
||||
FFI_DEFAULT_ABI = FFI_DARWIN,
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_FREEBSD
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* Needed for FFI_SYSV small structure returns. */
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST)
|
||||
|
||||
#if defined(POWERPC64) || defined(POWERPC_AIX)
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#else /* POWERPC || POWERPC_AIX */
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
|
||||
struct ffi_aix_trampoline_struct {
|
||||
void * code_pointer; /* Pointer to ffi_closure_ASM */
|
||||
void * toc; /* TOC */
|
||||
void * static_chain; /* Pointer to closure */
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
177
libffi/src/powerpc/linux64.S
Normal file
177
libffi/src/powerpc/linux64.S
Normal file
@@ -0,0 +1,177 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PowerPC64 Assembly glue.
|
||||
|
||||
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 THE AUTHOR 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 <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef __powerpc64__
|
||||
.hidden ffi_call_LINUX64, .ffi_call_LINUX64
|
||||
.globl ffi_call_LINUX64, .ffi_call_LINUX64
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
ffi_call_LINUX64:
|
||||
.quad .ffi_call_LINUX64,.TOC.@tocbase,0
|
||||
.size ffi_call_LINUX64,24
|
||||
.type .ffi_call_LINUX64,@function
|
||||
.text
|
||||
.ffi_call_LINUX64:
|
||||
.LFB1:
|
||||
mflr %r0
|
||||
std %r28, -32(%r1)
|
||||
std %r29, -24(%r1)
|
||||
std %r30, -16(%r1)
|
||||
std %r31, -8(%r1)
|
||||
std %r0, 16(%r1)
|
||||
|
||||
mr %r28, %r1 /* our AP. */
|
||||
stdux %r1, %r1, %r4
|
||||
.LCFI0:
|
||||
mr %r31, %r5 /* flags, */
|
||||
mr %r30, %r6 /* rvalue, */
|
||||
mr %r29, %r7 /* function address. */
|
||||
std %r2, 40(%r1)
|
||||
|
||||
/* Call ffi_prep_args64. */
|
||||
mr %r4, %r1
|
||||
bl .ffi_prep_args64
|
||||
|
||||
ld %r0, 0(%r29)
|
||||
ld %r2, 8(%r29)
|
||||
ld %r11, 16(%r29)
|
||||
|
||||
/* Now do the call. */
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40, %r31
|
||||
|
||||
/* Get the address to call into CTR. */
|
||||
mtctr %r0
|
||||
/* Load all those argument registers. */
|
||||
ld %r3, -32-(8*8)(%r28)
|
||||
ld %r4, -32-(7*8)(%r28)
|
||||
ld %r5, -32-(6*8)(%r28)
|
||||
ld %r6, -32-(5*8)(%r28)
|
||||
bf- 5, 1f
|
||||
ld %r7, -32-(4*8)(%r28)
|
||||
ld %r8, -32-(3*8)(%r28)
|
||||
ld %r9, -32-(2*8)(%r28)
|
||||
ld %r10, -32-(1*8)(%r28)
|
||||
1:
|
||||
|
||||
/* Load all the FP registers. */
|
||||
bf- 6, 2f
|
||||
lfd %f1, -32-(21*8)(%r28)
|
||||
lfd %f2, -32-(20*8)(%r28)
|
||||
lfd %f3, -32-(19*8)(%r28)
|
||||
lfd %f4, -32-(18*8)(%r28)
|
||||
lfd %f5, -32-(17*8)(%r28)
|
||||
lfd %f6, -32-(16*8)(%r28)
|
||||
lfd %f7, -32-(15*8)(%r28)
|
||||
lfd %f8, -32-(14*8)(%r28)
|
||||
lfd %f9, -32-(13*8)(%r28)
|
||||
lfd %f10, -32-(12*8)(%r28)
|
||||
lfd %f11, -32-(11*8)(%r28)
|
||||
lfd %f12, -32-(10*8)(%r28)
|
||||
lfd %f13, -32-(9*8)(%r28)
|
||||
2:
|
||||
|
||||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01, %r31
|
||||
bt- 30, .Ldone_return_value
|
||||
bt- 29, .Lfp_return_value
|
||||
std %r3, 0(%r30)
|
||||
/* Fall through... */
|
||||
|
||||
.Ldone_return_value:
|
||||
/* Restore the registers we used and return. */
|
||||
ld %r2, 40(%r1)
|
||||
mr %r1, %r28
|
||||
ld %r0, 16(%r28)
|
||||
ld %r28, -32(%r1)
|
||||
mtlr %r0
|
||||
ld %r29, -24(%r1)
|
||||
ld %r30, -16(%r1)
|
||||
ld %r31, -8(%r1)
|
||||
blr
|
||||
|
||||
.Lfp_return_value:
|
||||
bf 28, .Lfloat_return_value
|
||||
stfd %f1, 0(%r30)
|
||||
bf 27, .Ldone_return_value
|
||||
stfd %f2, 8(%r30)
|
||||
b .Ldone_return_value
|
||||
.Lfloat_return_value:
|
||||
stfs %f1, 0(%r30)
|
||||
b .Ldone_return_value
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,4,0,0
|
||||
.size .ffi_call_LINUX64,.-.ffi_call_LINUX64
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x14 # FDE Encoding (pcrel udata8)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 3
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.8byte .LFB1-. # FDE initial location
|
||||
.8byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x2 # DW_CFA_advance_loc1
|
||||
.byte .LCFI0-.LFB1
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0x1c
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.byte 0x9f # DW_CFA_offset, column 0x1f
|
||||
.uleb128 0x1
|
||||
.byte 0x9e # DW_CFA_offset, column 0x1e
|
||||
.uleb128 0x2
|
||||
.byte 0x9d # DW_CFA_offset, column 0x1d
|
||||
.uleb128 0x3
|
||||
.byte 0x9c # DW_CFA_offset, column 0x1c
|
||||
.uleb128 0x4
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
||||
206
libffi/src/powerpc/linux64_closure.S
Normal file
206
libffi/src/powerpc/linux64_closure.S
Normal file
@@ -0,0 +1,206 @@
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.file "linux64_closure.S"
|
||||
|
||||
#ifdef __powerpc64__
|
||||
FFI_HIDDEN (ffi_closure_LINUX64)
|
||||
FFI_HIDDEN (.ffi_closure_LINUX64)
|
||||
.globl ffi_closure_LINUX64, .ffi_closure_LINUX64
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
ffi_closure_LINUX64:
|
||||
.quad .ffi_closure_LINUX64,.TOC.@tocbase,0
|
||||
.size ffi_closure_LINUX64,24
|
||||
.type .ffi_closure_LINUX64,@function
|
||||
.text
|
||||
.ffi_closure_LINUX64:
|
||||
.LFB1:
|
||||
# save general regs into parm save area
|
||||
std %r3, 48(%r1)
|
||||
std %r4, 56(%r1)
|
||||
std %r5, 64(%r1)
|
||||
std %r6, 72(%r1)
|
||||
mflr %r0
|
||||
|
||||
std %r7, 80(%r1)
|
||||
std %r8, 88(%r1)
|
||||
std %r9, 96(%r1)
|
||||
std %r10, 104(%r1)
|
||||
std %r0, 16(%r1)
|
||||
|
||||
# mandatory 48 bytes special reg save area + 64 bytes parm save area
|
||||
# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
|
||||
stdu %r1, -240(%r1)
|
||||
.LCFI0:
|
||||
|
||||
# next save fpr 1 to fpr 13
|
||||
stfd %f1, 128+(0*8)(%r1)
|
||||
stfd %f2, 128+(1*8)(%r1)
|
||||
stfd %f3, 128+(2*8)(%r1)
|
||||
stfd %f4, 128+(3*8)(%r1)
|
||||
stfd %f5, 128+(4*8)(%r1)
|
||||
stfd %f6, 128+(5*8)(%r1)
|
||||
stfd %f7, 128+(6*8)(%r1)
|
||||
stfd %f8, 128+(7*8)(%r1)
|
||||
stfd %f9, 128+(8*8)(%r1)
|
||||
stfd %f10, 128+(9*8)(%r1)
|
||||
stfd %f11, 128+(10*8)(%r1)
|
||||
stfd %f12, 128+(11*8)(%r1)
|
||||
stfd %f13, 128+(12*8)(%r1)
|
||||
|
||||
# set up registers for the routine that actually does the work
|
||||
# get the context pointer from the trampoline
|
||||
mr %r3, %r11
|
||||
|
||||
# now load up the pointer to the result storage
|
||||
addi %r4, %r1, 112
|
||||
|
||||
# now load up the pointer to the parameter save area
|
||||
# in the previous frame
|
||||
addi %r5, %r1, 240 + 48
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6, %r1, 128
|
||||
|
||||
# make the call
|
||||
bl .ffi_closure_helper_LINUX64
|
||||
.Lret:
|
||||
|
||||
# now r3 contains the return type
|
||||
# so use it to look up in a table
|
||||
# so we know how to deal with each type
|
||||
|
||||
# look up the proper starting point in table
|
||||
# by using return type as offset
|
||||
mflr %r4 # move address of .Lret to r4
|
||||
sldi %r3, %r3, 4 # now multiply return type by 16
|
||||
addi %r4, %r4, .Lret_type0 - .Lret
|
||||
ld %r0, 240+16(%r1)
|
||||
add %r3, %r3, %r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
|
||||
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
# first.
|
||||
.align 4
|
||||
|
||||
.Lret_type0:
|
||||
# case FFI_TYPE_VOID
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
nop
|
||||
# case FFI_TYPE_INT
|
||||
lwa %r3, 112+4(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1, 112+0(%r1)
|
||||
mtlr %r0
|
||||
lfd %f2, 112+8(%r1)
|
||||
b .Lfinish
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3, 112+7(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3, 112+7(%r1)
|
||||
extsb %r3,%r3
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3, 112+6(%r1)
|
||||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3, 112+6(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3, 112+4(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT32
|
||||
lwa %r3, 112+4(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_UINT64
|
||||
ld %r3, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_SINT64
|
||||
ld %r3, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
nop
|
||||
# case FFI_TYPE_POINTER
|
||||
ld %r3, 112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, 240
|
||||
blr
|
||||
# esac
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,0,0,0
|
||||
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x14 # FDE Encoding (pcrel udata8)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 3
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.8byte .LFB1-. # FDE initial location
|
||||
.8byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x2 # DW_CFA_advance_loc1
|
||||
.byte .LCFI0-.LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 240
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
||||
283
libffi/src/powerpc/ppc_closure.S
Normal file
283
libffi/src/powerpc/ppc_closure.S
Normal file
@@ -0,0 +1,283 @@
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
.file "ppc_closure.S"
|
||||
|
||||
#ifndef __powerpc64__
|
||||
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB1:
|
||||
stwu %r1,-144(%r1)
|
||||
.LCFI0:
|
||||
mflr %r0
|
||||
.LCFI1:
|
||||
stw %r0,148(%r1)
|
||||
|
||||
# we want to build up an areas for the parameters passed
|
||||
# in registers (both floating point and integer)
|
||||
|
||||
# so first save gpr 3 to gpr 10 (aligned to 4)
|
||||
stw %r3, 16(%r1)
|
||||
stw %r4, 20(%r1)
|
||||
stw %r5, 24(%r1)
|
||||
stw %r6, 28(%r1)
|
||||
stw %r7, 32(%r1)
|
||||
stw %r8, 36(%r1)
|
||||
stw %r9, 40(%r1)
|
||||
stw %r10,44(%r1)
|
||||
|
||||
# next save fpr 1 to fpr 8 (aligned to 8)
|
||||
stfd %f1, 48(%r1)
|
||||
stfd %f2, 56(%r1)
|
||||
stfd %f3, 64(%r1)
|
||||
stfd %f4, 72(%r1)
|
||||
stfd %f5, 80(%r1)
|
||||
stfd %f6, 88(%r1)
|
||||
stfd %f7, 96(%r1)
|
||||
stfd %f8, 104(%r1)
|
||||
|
||||
# set up registers for the routine that actually does the work
|
||||
# get the context pointer from the trampoline
|
||||
mr %r3,%r11
|
||||
|
||||
# now load up the pointer to the result storage
|
||||
addi %r4,%r1,112
|
||||
|
||||
# now load up the pointer to the saved gpr registers
|
||||
addi %r5,%r1,16
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6,%r1,48
|
||||
|
||||
# now load up the pointer to the outgoing parameter
|
||||
# stack in the previous frame
|
||||
# i.e. the previous frame pointer + 8
|
||||
addi %r7,%r1,152
|
||||
|
||||
# make the call
|
||||
bl ffi_closure_helper_SYSV@local
|
||||
.Lret:
|
||||
# now r3 contains the return type
|
||||
# so use it to look up in a table
|
||||
# so we know how to deal with each type
|
||||
|
||||
# look up the proper starting point in table
|
||||
# by using return type as offset
|
||||
|
||||
mflr %r4 # move address of .Lret to r4
|
||||
slwi %r3,%r3,4 # now multiply return type by 16
|
||||
addi %r4, %r4, .Lret_type0 - .Lret
|
||||
lwz %r0,148(%r1)
|
||||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
.LFE1:
|
||||
|
||||
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
# first.
|
||||
.align 4
|
||||
# case FFI_TYPE_VOID
|
||||
.Lret_type0:
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_INT
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
lfd %f2,112+8(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
extsb %r3,%r3
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_SINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# The return types below are only used when the ABI type is FFI_SYSV.
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
|
||||
lbz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
lhz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
srwi %r3,%r3,8
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,24
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,16
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,8
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
.Lstruct567:
|
||||
subfic %r6,%r5,32
|
||||
srw %r4,%r4,%r5
|
||||
slw %r6,%r3,%r6
|
||||
srw %r3,%r3,%r5
|
||||
or %r4,%r6,%r4
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
#else
|
||||
.ascii "\0" # CIE Augmentation
|
||||
#endif
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -4 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
#endif
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
#else
|
||||
.4byte .LFB1 # FDE initial location
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x0 # Augmentation size
|
||||
#endif
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 144
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -1
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,7 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 1998 Geoffrey Keating
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
$Id: sysv.S,v 1.1 2001/04/22 18:28:36 green Exp $
|
||||
PowerPC Assembly glue.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -25,34 +23,44 @@
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <powerpc/asm.h>
|
||||
|
||||
.globl ffi_prep_args
|
||||
#ifndef __powerpc64__
|
||||
.globl ffi_prep_args_SYSV
|
||||
ENTRY(ffi_call_SYSV)
|
||||
.LFB1:
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr %r8,%r1
|
||||
|
||||
.LCFI0:
|
||||
/* Allocate the stack space we need. */
|
||||
stwux %r1,%r1,%r4
|
||||
/* Save registers we use. */
|
||||
mflr %r9
|
||||
stw %r28,-16(%r8)
|
||||
.LCFI1:
|
||||
stw %r29,-12(%r8)
|
||||
.LCFI2:
|
||||
stw %r30, -8(%r8)
|
||||
.LCFI3:
|
||||
stw %r31, -4(%r8)
|
||||
.LCFI4:
|
||||
stw %r9, 4(%r8)
|
||||
.LCFI5:
|
||||
|
||||
/* Save arguments over call... */
|
||||
mr %r31,%r5 /* flags, */
|
||||
mr %r30,%r6 /* rvalue, */
|
||||
mr %r29,%r7 /* function address, */
|
||||
mr %r28,%r8 /* our AP. */
|
||||
.LCFI6:
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
/* Call ffi_prep_args_SYSV. */
|
||||
mr %r4,%r1
|
||||
bl JUMPTARGET(ffi_prep_args)
|
||||
bl ffi_prep_args_SYSV@local
|
||||
|
||||
/* Now do the call. */
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
@@ -91,6 +99,7 @@ ENTRY(ffi_call_SYSV)
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,%r31
|
||||
bt- 31,L(small_struct_return_value)
|
||||
bt- 30,L(done_return_value)
|
||||
bt- 29,L(fp_return_value)
|
||||
stw %r3,0(%r30)
|
||||
@@ -112,8 +121,99 @@ L(done_return_value):
|
||||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd %f1,0(%r30)
|
||||
bf 27,L(done_return_value)
|
||||
stfd %f2,8(%r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs %f1,0(%r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(small_struct_return_value):
|
||||
mtcrf 0x10,%r31 /* cr3 */
|
||||
bt- 15,L(smst_one_register)
|
||||
mtcrf 0x08,%r31 /* cr4 */
|
||||
bt- 16,L(smst_two_register)
|
||||
b L(done_return_value)
|
||||
|
||||
L(smst_one_register):
|
||||
rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
|
||||
slw %r3,%r3,%r5
|
||||
stw %r3,0(%r30)
|
||||
b L(done_return_value)
|
||||
L(smst_two_register):
|
||||
rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
|
||||
cmpwi %r5,0
|
||||
subfic %r9,%r5,32
|
||||
slw %r29,%r3,%r5
|
||||
srw %r9,%r4,%r9
|
||||
beq- L(smst_8byte)
|
||||
or %r3,%r9,%r29
|
||||
slw %r4,%r4,%r5
|
||||
L(smst_8byte):
|
||||
stw %r3,0(%r30)
|
||||
stw %r4,4(%r30)
|
||||
b L(done_return_value)
|
||||
|
||||
.LFE1:
|
||||
END(ffi_call_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.4byte 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.ascii "\0" /* CIE Augmentation */
|
||||
#endif
|
||||
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||
.byte 0x41 /* CIE RA Column */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x1 /* Augmentation size */
|
||||
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.4byte .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 /* FDE address range */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0x08
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI5-.LCFI0
|
||||
.byte 0x11 /* DW_CFA_offset_extended_sf */
|
||||
.uleb128 0x41
|
||||
.sleb128 -1
|
||||
.byte 0x9f /* DW_CFA_offset, column 0x1f */
|
||||
.uleb128 0x1
|
||||
.byte 0x9e /* DW_CFA_offset, column 0x1e */
|
||||
.uleb128 0x2
|
||||
.byte 0x9d /* DW_CFA_offset, column 0x1d */
|
||||
.uleb128 0x3
|
||||
.byte 0x9c /* DW_CFA_offset, column 0x1c */
|
||||
.uleb128 0x4
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI6-.LCFI5
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0x1c
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Cygnus Solutions
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -15,32 +15,29 @@
|
||||
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 RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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_private.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Round up to FFI_SIZEOF_ARG. */
|
||||
|
||||
/* Round up to SIZEOF_ARG. */
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, SIZEOF_ARG)
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
||||
static ffi_status initialize_aggregate(ffi_type *arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(arg != NULL);
|
||||
|
||||
/*@-usedef@*/
|
||||
|
||||
FFI_ASSERT(arg->elements != NULL);
|
||||
FFI_ASSERT(arg->size == 0);
|
||||
FFI_ASSERT(arg->alignment == 0);
|
||||
@@ -51,41 +48,51 @@ static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
||||
{
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT(ffi_type_test((*ptr)));
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Structure size includes tail padding. This is important for
|
||||
structures that fit in one register on ABIs like the PowerPC64
|
||||
Linux ABI that right justify small structs in a register.
|
||||
It's also needed for nested structure layout, for example
|
||||
struct A { long a; char b; }; struct B { struct A x; char y; };
|
||||
should find y at an offset of 2*sizeof(long) and result in a
|
||||
total size of 3*sizeof(long). */
|
||||
arg->size = ALIGN (arg->size, arg->alignment);
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
|
||||
/*@=usedef@*/
|
||||
}
|
||||
|
||||
#ifndef __CRIS__
|
||||
/* The CRIS ABI specifies structure elements to have byte
|
||||
alignment only, so it completely overrides this functions,
|
||||
which assumes "natural" alignment and padding. */
|
||||
|
||||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
||||
/*@dependent@*/ ffi_type **atypes)
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(cif != NULL);
|
||||
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi < FFI_LAST_ABI));
|
||||
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
@@ -95,34 +102,39 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
/*@-usedef@*/
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
/*@=usedef@*/
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT(ffi_type_test(cif->rtype));
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
#ifndef M68K
|
||||
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef __sparc__
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
)
|
||||
#ifdef X86_DARWIN
|
||||
&& (cif->rtype->size > 8)
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT(ffi_type_test(*ptr));
|
||||
|
||||
/* Initialize any uninitialized aggregate type definitions */
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifdef __sparc__
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if !defined __x86_64__ && !defined S390 && !defined PA
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
@@ -134,9 +146,10 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
@@ -144,3 +157,4 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
/* Perform machine dependent cif processing */
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
#endif /* not __CRIS__ */
|
||||
@@ -1,8 +1,10 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
raw_api.c - Copyright (c) 1999 Cygnus Solutions
|
||||
raw_api.c - Copyright (c) 1999 Red Hat, Inc.
|
||||
|
||||
Author: Kresten Krab Thorup <krab@gnu.org>
|
||||
|
||||
$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
|
||||
@@ -17,7 +19,7 @@
|
||||
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 RED HAT BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
@@ -26,7 +28,7 @@
|
||||
/* This file defines generic functions for use with the raw api. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
@@ -42,10 +44,10 @@ ffi_raw_size (ffi_cif *cif)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*at)->type == FFI_TYPE_STRUCT)
|
||||
result += ALIGN (sizeof (void*), SIZEOF_ARG);
|
||||
result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
|
||||
else
|
||||
#endif
|
||||
result += ALIGN ((*at)->size, SIZEOF_ARG);
|
||||
result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -66,18 +68,18 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
#if FFI_SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -93,7 +95,7 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
break;
|
||||
|
||||
#if SIZEOF_ARG >= 4
|
||||
#if FFI_SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
break;
|
||||
@@ -172,7 +174,7 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
|
||||
default:
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,10 +189,7 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *raw)
|
||||
void ffi_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_raw_to_ptrarray (cif, raw, avalue);
|
||||
@@ -199,7 +198,7 @@ void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
static void
|
||||
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
@@ -222,7 +221,7 @@ ffi_prep_raw_closure (ffi_raw_closure* cl,
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
status = ffi_prep_closure ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_translate_args,
|
||||
(void*)cl);
|
||||
751
libffi/src/s390/ffi.c
Normal file
751
libffi/src/s390/ffi.c
Normal file
@@ -0,0 +1,751 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2000 Software AG
|
||||
|
||||
S390 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 THE AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
/*====================================================================*/
|
||||
/* Includes */
|
||||
/* -------- */
|
||||
/*====================================================================*/
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*====================== End of Includes =============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Defines */
|
||||
/* ------- */
|
||||
/*====================================================================*/
|
||||
|
||||
/* Maximum number of GPRs available for argument passing. */
|
||||
#define MAX_GPRARGS 5
|
||||
|
||||
/* Maximum number of FPRs available for argument passing. */
|
||||
#ifdef __s390x__
|
||||
#define MAX_FPRARGS 4
|
||||
#else
|
||||
#define MAX_FPRARGS 2
|
||||
#endif
|
||||
|
||||
/* Round to multiple of 16. */
|
||||
#define ROUND_SIZE(size) (((size) + 15) & ~15)
|
||||
|
||||
/* If these values change, sysv.S must be adapted! */
|
||||
#define FFI390_RET_VOID 0
|
||||
#define FFI390_RET_STRUCT 1
|
||||
#define FFI390_RET_FLOAT 2
|
||||
#define FFI390_RET_DOUBLE 3
|
||||
#define FFI390_RET_INT32 4
|
||||
#define FFI390_RET_INT64 5
|
||||
|
||||
/*===================== End of Defines ===============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Prototypes */
|
||||
/* ---------- */
|
||||
/*====================================================================*/
|
||||
|
||||
static void ffi_prep_args (unsigned char *, extended_cif *);
|
||||
void
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
|
||||
__attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
|
||||
unsigned long long *, unsigned long *);
|
||||
|
||||
/*====================== End of Prototypes ===========================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Externals */
|
||||
/* --------- */
|
||||
/*====================================================================*/
|
||||
|
||||
extern void ffi_call_SYSV(unsigned,
|
||||
extended_cif *,
|
||||
void (*)(unsigned char *, extended_cif *),
|
||||
unsigned,
|
||||
void *,
|
||||
void (*fn)());
|
||||
|
||||
extern void ffi_closure_SYSV(void);
|
||||
|
||||
/*====================== End of Externals ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_check_struct_type. */
|
||||
/* */
|
||||
/* Function - Determine if a structure can be passed within a */
|
||||
/* general purpose or floating point register. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
static int
|
||||
ffi_check_struct_type (ffi_type *arg)
|
||||
{
|
||||
size_t size = arg->size;
|
||||
|
||||
/* If the struct has just one element, look at that element
|
||||
to find out whether to consider the struct as floating point. */
|
||||
while (arg->type == FFI_TYPE_STRUCT
|
||||
&& arg->elements[0] && !arg->elements[1])
|
||||
arg = arg->elements[0];
|
||||
|
||||
/* Structs of size 1, 2, 4, and 8 are passed in registers,
|
||||
just like the corresponding int/float types. */
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
return FFI_TYPE_UINT8;
|
||||
|
||||
case 2:
|
||||
return FFI_TYPE_UINT16;
|
||||
|
||||
case 4:
|
||||
if (arg->type == FFI_TYPE_FLOAT)
|
||||
return FFI_TYPE_FLOAT;
|
||||
else
|
||||
return FFI_TYPE_UINT32;
|
||||
|
||||
case 8:
|
||||
if (arg->type == FFI_TYPE_DOUBLE)
|
||||
return FFI_TYPE_DOUBLE;
|
||||
else
|
||||
return FFI_TYPE_UINT64;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Other structs are passed via a pointer to the data. */
|
||||
return FFI_TYPE_POINTER;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_args. */
|
||||
/* */
|
||||
/* Function - Prepare parameters for call to function. */
|
||||
/* */
|
||||
/* 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 (unsigned char *stack, extended_cif *ecif)
|
||||
{
|
||||
/* The stack space will be filled with those areas:
|
||||
|
||||
FPR argument register save area (highest addresses)
|
||||
GPR argument register save area
|
||||
temporary struct copies
|
||||
overflow argument area (lowest addresses)
|
||||
|
||||
We set up the following pointers:
|
||||
|
||||
p_fpr: bottom of the FPR area (growing upwards)
|
||||
p_gpr: bottom of the GPR area (growing upwards)
|
||||
p_ov: bottom of the overflow area (growing upwards)
|
||||
p_struct: top of the struct copy area (growing downwards)
|
||||
|
||||
All areas are kept aligned to twice the word size. */
|
||||
|
||||
int gpr_off = ecif->cif->bytes;
|
||||
int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
|
||||
|
||||
unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
|
||||
unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
|
||||
unsigned char *p_struct = (unsigned char *)p_gpr;
|
||||
unsigned long *p_ov = (unsigned long *)stack;
|
||||
|
||||
int n_fpr = 0;
|
||||
int n_gpr = 0;
|
||||
int n_ov = 0;
|
||||
|
||||
ffi_type **ptr;
|
||||
void **p_argv = ecif->avalue;
|
||||
int i;
|
||||
|
||||
/* If we returning a structure then we set the first parameter register
|
||||
to the address of where we are returning this structure. */
|
||||
|
||||
if (ecif->cif->flags == FFI390_RET_STRUCT)
|
||||
p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
|
||||
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
void *arg = *p_argv;
|
||||
int type = (*ptr)->type;
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, copy the data. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
{
|
||||
p_struct -= ROUND_SIZE ((*ptr)->size);
|
||||
memcpy (p_struct, (char *)arg, (*ptr)->size);
|
||||
arg = &p_struct;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now handle all primitive int/pointer/float data types. */
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
p_fpr[n_fpr++] = *(unsigned long long *) arg;
|
||||
else
|
||||
#ifdef __s390x__
|
||||
p_ov[n_ov++] = *(unsigned long *) arg;
|
||||
#else
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[0],
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[1];
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned int *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
|
||||
else
|
||||
p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#ifdef __s390x__
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned long *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned long *) arg;
|
||||
#else
|
||||
if (n_gpr == MAX_GPRARGS-1)
|
||||
n_gpr = MAX_GPRARGS;
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
|
||||
p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
|
||||
else
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[0],
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[1];
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned int *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned int *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(signed int *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(signed int *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned short *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned short *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(signed short *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(signed short *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned char *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned char *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(signed char *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(signed char *) arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_cif_machdep. */
|
||||
/* */
|
||||
/* Function - Perform machine dependent CIF processing. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
size_t struct_size = 0;
|
||||
int n_gpr = 0;
|
||||
int n_fpr = 0;
|
||||
int n_ov = 0;
|
||||
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
|
||||
/* Determine return value handling. */
|
||||
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
/* Void is easy. */
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = FFI390_RET_VOID;
|
||||
break;
|
||||
|
||||
/* Structures are returned via a hidden pointer. */
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags = FFI390_RET_STRUCT;
|
||||
n_gpr++; /* We need one GPR to pass the pointer. */
|
||||
break;
|
||||
|
||||
/* Floating point values are returned in fpr 0. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
cif->flags = FFI390_RET_FLOAT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI390_RET_DOUBLE;
|
||||
break;
|
||||
|
||||
/* Integer values are returned in gpr 2 (and gpr 3
|
||||
for 64-bit values on 31-bit machines). */
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
cif->flags = FFI390_RET_INT64;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
/* These are to be extended to word size. */
|
||||
#ifdef __s390x__
|
||||
cif->flags = FFI390_RET_INT64;
|
||||
#else
|
||||
cif->flags = FFI390_RET_INT32;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now for the arguments. */
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++)
|
||||
{
|
||||
int type = (*ptr)->type;
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, we must reserve space
|
||||
to copy its data for proper call-by-value semantics. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
struct_size += ROUND_SIZE ((*ptr)->size);
|
||||
}
|
||||
|
||||
/* Now handle all primitive int/float data types. */
|
||||
switch (type)
|
||||
{
|
||||
/* The first MAX_FPRARGS floating point arguments
|
||||
go in FPRs, the rest overflow to the stack. */
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
n_fpr++;
|
||||
else
|
||||
n_ov += sizeof (double) / sizeof (long);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
n_fpr++;
|
||||
else
|
||||
n_ov++;
|
||||
break;
|
||||
|
||||
/* On 31-bit machines, 64-bit integers are passed in GPR pairs,
|
||||
if one is still available, or else on the stack. If only one
|
||||
register is free, skip the register (it won't be used for any
|
||||
subsequent argument either). */
|
||||
|
||||
#ifndef __s390x__
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
if (n_gpr == MAX_GPRARGS-1)
|
||||
n_gpr = MAX_GPRARGS;
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
n_gpr += 2;
|
||||
else
|
||||
n_ov += 2;
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* Everything else is passed in GPRs (until MAX_GPRARGS
|
||||
have been used) or overflows to the stack. */
|
||||
|
||||
default:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
n_gpr++;
|
||||
else
|
||||
n_ov++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Total stack space as required for overflow arguments
|
||||
and temporary structure copies. */
|
||||
|
||||
cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_call. */
|
||||
/* */
|
||||
/* Function - Call the FFI routine. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void *rvalue,
|
||||
void **avalue)
|
||||
{
|
||||
int ret_type = cif->flags;
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
/* If we don't have a return value, we need to fake one. */
|
||||
if (rvalue == NULL)
|
||||
{
|
||||
if (ret_type == FFI390_RET_STRUCT)
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
else
|
||||
ret_type = FFI390_RET_VOID;
|
||||
}
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
|
||||
ret_type, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_closure_helper_SYSV. */
|
||||
/* */
|
||||
/* Function - Call a FFI closure target function. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure,
|
||||
unsigned long *p_gpr,
|
||||
unsigned long long *p_fpr,
|
||||
unsigned long *p_ov)
|
||||
{
|
||||
unsigned long long ret_buffer;
|
||||
|
||||
void *rvalue = &ret_buffer;
|
||||
void **avalue;
|
||||
void **p_arg;
|
||||
|
||||
int n_gpr = 0;
|
||||
int n_fpr = 0;
|
||||
int n_ov = 0;
|
||||
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
|
||||
/* Allocate buffer for argument list pointers. */
|
||||
|
||||
p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
|
||||
|
||||
/* If we returning a structure, pass the structure address
|
||||
directly to the target function. Otherwise, have the target
|
||||
function store the return value to the GPR save area. */
|
||||
|
||||
if (closure->cif->flags == FFI390_RET_STRUCT)
|
||||
rvalue = (void *) p_gpr[n_gpr++];
|
||||
|
||||
/* Now for the arguments. */
|
||||
|
||||
for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
|
||||
i > 0;
|
||||
i--, p_arg++, ptr++)
|
||||
{
|
||||
int deref_struct_pointer = 0;
|
||||
int type = (*ptr)->type;
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, remember to
|
||||
retrieve the pointer later. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
deref_struct_pointer = 1;
|
||||
}
|
||||
|
||||
/* Pointers are passed like UINTs of the same size. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
#ifdef __s390x__
|
||||
type = FFI_TYPE_UINT64;
|
||||
#else
|
||||
type = FFI_TYPE_UINT32;
|
||||
#endif
|
||||
|
||||
/* Now handle all primitive int/float data types. */
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
*p_arg = &p_fpr[n_fpr++];
|
||||
else
|
||||
*p_arg = &p_ov[n_ov],
|
||||
n_ov += sizeof (double) / sizeof (long);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
*p_arg = &p_fpr[n_fpr++];
|
||||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#ifdef __s390x__
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
*p_arg = &p_gpr[n_gpr++];
|
||||
else
|
||||
*p_arg = &p_ov[n_ov++];
|
||||
#else
|
||||
if (n_gpr == MAX_GPRARGS-1)
|
||||
n_gpr = MAX_GPRARGS;
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
*p_arg = &p_gpr[n_gpr], n_gpr += 2;
|
||||
else
|
||||
*p_arg = &p_ov[n_ov], n_ov += 2;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
*p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
|
||||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
*p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
|
||||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
*p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
|
||||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this is a struct passed via pointer, we need to
|
||||
actually retrieve that pointer. */
|
||||
if (deref_struct_pointer)
|
||||
*p_arg = *(void **)*p_arg;
|
||||
}
|
||||
|
||||
|
||||
/* Call the target function. */
|
||||
(closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Convert the return value. */
|
||||
switch (closure->cif->rtype->type)
|
||||
{
|
||||
/* Void is easy, and so is struct. */
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
break;
|
||||
|
||||
/* Floating point values are returned in fpr 0. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
p_fpr[0] = *(unsigned long long *) rvalue;
|
||||
break;
|
||||
|
||||
/* Integer values are returned in gpr 2 (and gpr 3
|
||||
for 64-bit values on 31-bit machines). */
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#ifdef __s390x__
|
||||
p_gpr[0] = *(unsigned long *) rvalue;
|
||||
#else
|
||||
p_gpr[0] = ((unsigned long *) rvalue)[0],
|
||||
p_gpr[1] = ((unsigned long *) rvalue)[1];
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_UINT8:
|
||||
p_gpr[0] = *(unsigned long *) rvalue;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_SINT8:
|
||||
p_gpr[0] = *(signed long *) rvalue;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_closure. */
|
||||
/* */
|
||||
/* Function - Prepare a FFI closure. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
#ifndef __s390x__
|
||||
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
|
||||
*(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
|
||||
*(short *)&closure->tramp [4] = 0x1006;
|
||||
*(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
|
||||
*(long *)&closure->tramp [8] = (long)closure;
|
||||
*(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
|
||||
#else
|
||||
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
|
||||
*(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
|
||||
*(short *)&closure->tramp [4] = 0x100e;
|
||||
*(short *)&closure->tramp [6] = 0x0004;
|
||||
*(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
|
||||
*(long *)&closure->tramp[16] = (long)closure;
|
||||
*(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
59
libffi/src/s390/ffitarget.h
Normal file
59
libffi/src/s390/ffitarget.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for S390.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#if defined (__s390x__)
|
||||
#define S390X
|
||||
#endif
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#ifdef S390X
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#endif
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
429
libffi/src/s390/sysv.S
Normal file
429
libffi/src/s390/sysv.S
Normal file
@@ -0,0 +1,429 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2000 Software AG
|
||||
|
||||
S390 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifndef __s390x__
|
||||
|
||||
.text
|
||||
|
||||
# r2: cif->bytes
|
||||
# r3: &ecif
|
||||
# r4: ffi_prep_args
|
||||
# r5: ret_type
|
||||
# r6: ecif.rvalue
|
||||
# ov: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,%function
|
||||
ffi_call_SYSV:
|
||||
.LFB1:
|
||||
stm %r6,%r15,24(%r15) # Save registers
|
||||
.LCFI0:
|
||||
basr %r13,0 # Set up base register
|
||||
.Lbase:
|
||||
lr %r11,%r15 # Set up frame pointer
|
||||
.LCFI1:
|
||||
sr %r15,%r2
|
||||
ahi %r15,-96-48 # Allocate stack
|
||||
lr %r8,%r6 # Save ecif.rvalue
|
||||
sr %r9,%r9
|
||||
ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
|
||||
l %r7,96(%r11) # Load function address
|
||||
st %r11,0(%r15) # Set up back chain
|
||||
ahi %r11,-48 # Register save area
|
||||
.LCFI2:
|
||||
|
||||
la %r2,96(%r15) # Save area
|
||||
# r3 already holds &ecif
|
||||
basr %r14,%r4 # Call ffi_prep_args
|
||||
|
||||
lm %r2,%r6,0(%r11) # Load arguments
|
||||
ld %f0,32(%r11)
|
||||
ld %f2,40(%r11)
|
||||
la %r14,0(%r13,%r9) # Set return address
|
||||
br %r7 # ... and call function
|
||||
|
||||
.LretNone: # Return void
|
||||
l %r4,48+56(%r11)
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretFloat:
|
||||
l %r4,48+56(%r11)
|
||||
ste %f0,0(%r8) # Return float
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretDouble:
|
||||
l %r4,48+56(%r11)
|
||||
std %f0,0(%r8) # Return double
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt32:
|
||||
l %r4,48+56(%r11)
|
||||
st %r2,0(%r8) # Return int
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt64:
|
||||
l %r4,48+56(%r11)
|
||||
stm %r2,%r3,0(%r8) # Return long long
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.Ltable:
|
||||
.byte .LretNone-.Lbase # FFI390_RET_VOID
|
||||
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
|
||||
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
|
||||
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
|
||||
.byte .LretInt32-.Lbase # FFI390_RET_INT32
|
||||
.byte .LretInt64-.Lbase # FFI390_RET_INT64
|
||||
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
|
||||
|
||||
.globl ffi_closure_SYSV
|
||||
.type ffi_closure_SYSV,%function
|
||||
ffi_closure_SYSV:
|
||||
.LFB2:
|
||||
stm %r12,%r15,48(%r15) # Save registers
|
||||
.LCFI10:
|
||||
basr %r13,0 # Set up base register
|
||||
.Lcbase:
|
||||
stm %r2,%r6,8(%r15) # Save arguments
|
||||
std %f0,64(%r15)
|
||||
std %f2,72(%r15)
|
||||
lr %r1,%r15 # Set up stack frame
|
||||
ahi %r15,-96
|
||||
.LCFI11:
|
||||
l %r12,.Lchelper-.Lcbase(%r13) # Get helper function
|
||||
lr %r2,%r0 # Closure
|
||||
la %r3,8(%r1) # GPRs
|
||||
la %r4,64(%r1) # FPRs
|
||||
la %r5,96(%r1) # Overflow
|
||||
st %r1,0(%r15) # Set up back chain
|
||||
|
||||
bas %r14,0(%r12,%r13) # Call helper
|
||||
|
||||
l %r4,96+56(%r15)
|
||||
ld %f0,96+64(%r15) # Load return registers
|
||||
lm %r2,%r3,96+8(%r15)
|
||||
lm %r12,%r15,96+48(%r15)
|
||||
br %r4
|
||||
|
||||
.align 4
|
||||
.Lchelper:
|
||||
.long ffi_closure_helper_SYSV-.Lcbase
|
||||
|
||||
.LFE2:
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
|
||||
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -4 # CIE Data Alignment Factor
|
||||
.byte 0xe # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0xf
|
||||
.uleb128 0x60
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x9
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0xa
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.uleb128 0xb
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.uleb128 0xc
|
||||
.byte 0x8b # DW_CFA_offset, column 0xb
|
||||
.uleb128 0xd
|
||||
.byte 0x8a # DW_CFA_offset, column 0xa
|
||||
.uleb128 0xe
|
||||
.byte 0x89 # DW_CFA_offset, column 0x9
|
||||
.uleb128 0xf
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.uleb128 0x10
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.uleb128 0x11
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.uleb128 0x12
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0xb
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x90
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
.LSFDE2:
|
||||
.4byte .LEFDE2-.LASFDE2 # FDE Length
|
||||
.LASFDE2:
|
||||
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB2-. # FDE initial location
|
||||
.4byte .LFE2-.LFB2 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI10-.LFB2
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x9
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0xa
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.uleb128 0xb
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.uleb128 0xc
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI11-.LCFI10
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0xc0
|
||||
.align 4
|
||||
.LEFDE2:
|
||||
|
||||
#else
|
||||
|
||||
.text
|
||||
|
||||
# r2: cif->bytes
|
||||
# r3: &ecif
|
||||
# r4: ffi_prep_args
|
||||
# r5: ret_type
|
||||
# r6: ecif.rvalue
|
||||
# ov: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,%function
|
||||
ffi_call_SYSV:
|
||||
.LFB1:
|
||||
stmg %r6,%r15,48(%r15) # Save registers
|
||||
.LCFI0:
|
||||
larl %r13,.Lbase # Set up base register
|
||||
lgr %r11,%r15 # Set up frame pointer
|
||||
.LCFI1:
|
||||
sgr %r15,%r2
|
||||
aghi %r15,-160-80 # Allocate stack
|
||||
lgr %r8,%r6 # Save ecif.rvalue
|
||||
llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
|
||||
lg %r7,160(%r11) # Load function address
|
||||
stg %r11,0(%r15) # Set up back chain
|
||||
aghi %r11,-80 # Register save area
|
||||
.LCFI2:
|
||||
|
||||
la %r2,160(%r15) # Save area
|
||||
# r3 already holds &ecif
|
||||
basr %r14,%r4 # Call ffi_prep_args
|
||||
|
||||
lmg %r2,%r6,0(%r11) # Load arguments
|
||||
ld %f0,48(%r11)
|
||||
ld %f2,56(%r11)
|
||||
ld %f4,64(%r11)
|
||||
ld %f6,72(%r11)
|
||||
la %r14,0(%r13,%r9) # Set return address
|
||||
br %r7 # ... and call function
|
||||
|
||||
.Lbase:
|
||||
.LretNone: # Return void
|
||||
lg %r4,80+112(%r11)
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretFloat:
|
||||
lg %r4,80+112(%r11)
|
||||
ste %f0,0(%r8) # Return float
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretDouble:
|
||||
lg %r4,80+112(%r11)
|
||||
std %f0,0(%r8) # Return double
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt32:
|
||||
lg %r4,80+112(%r11)
|
||||
st %r2,0(%r8) # Return int
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt64:
|
||||
lg %r4,80+112(%r11)
|
||||
stg %r2,0(%r8) # Return long
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.Ltable:
|
||||
.byte .LretNone-.Lbase # FFI390_RET_VOID
|
||||
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
|
||||
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
|
||||
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
|
||||
.byte .LretInt32-.Lbase # FFI390_RET_INT32
|
||||
.byte .LretInt64-.Lbase # FFI390_RET_INT64
|
||||
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
|
||||
|
||||
.globl ffi_closure_SYSV
|
||||
.type ffi_closure_SYSV,%function
|
||||
ffi_closure_SYSV:
|
||||
.LFB2:
|
||||
stmg %r14,%r15,112(%r15) # Save registers
|
||||
.LCFI10:
|
||||
stmg %r2,%r6,16(%r15) # Save arguments
|
||||
std %f0,128(%r15)
|
||||
std %f2,136(%r15)
|
||||
std %f4,144(%r15)
|
||||
std %f6,152(%r15)
|
||||
lgr %r1,%r15 # Set up stack frame
|
||||
aghi %r15,-160
|
||||
.LCFI11:
|
||||
lgr %r2,%r0 # Closure
|
||||
la %r3,16(%r1) # GPRs
|
||||
la %r4,128(%r1) # FPRs
|
||||
la %r5,160(%r1) # Overflow
|
||||
stg %r1,0(%r15) # Set up back chain
|
||||
|
||||
brasl %r14,ffi_closure_helper_SYSV # Call helper
|
||||
|
||||
lg %r14,160+112(%r15)
|
||||
ld %f0,160+128(%r15) # Load return registers
|
||||
lg %r2,160+16(%r15)
|
||||
la %r15,160(%r15)
|
||||
br %r14
|
||||
.LFE2:
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
|
||||
|
||||
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0xe # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0xf
|
||||
.uleb128 0xa0
|
||||
.align 8
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x5
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0x6
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.uleb128 0x7
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.uleb128 0x8
|
||||
.byte 0x8b # DW_CFA_offset, column 0xb
|
||||
.uleb128 0x9
|
||||
.byte 0x8a # DW_CFA_offset, column 0xa
|
||||
.uleb128 0xa
|
||||
.byte 0x89 # DW_CFA_offset, column 0x9
|
||||
.uleb128 0xb
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.uleb128 0xc
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.uleb128 0xd
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.uleb128 0xe
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0xb
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0xf0
|
||||
.align 8
|
||||
.LEFDE1:
|
||||
.LSFDE2:
|
||||
.4byte .LEFDE2-.LASFDE2 # FDE Length
|
||||
.LASFDE2:
|
||||
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB2-. # FDE initial location
|
||||
.4byte .LFE2-.LFB2 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI10-.LFB2
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x5
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0x6
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI11-.LCFI10
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x140
|
||||
.align 8
|
||||
.LEFDE2:
|
||||
|
||||
#endif
|
||||
|
||||
713
libffi/src/sh/ffi.c
Normal file
713
libffi/src/sh/ffi.c
Normal file
@@ -0,0 +1,713 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006 Kaz Kojima
|
||||
|
||||
SuperH 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>
|
||||
|
||||
#define NGREGARG 4
|
||||
#if defined(__SH4__)
|
||||
#define NFREGARG 8
|
||||
#endif
|
||||
|
||||
#if defined(__HITACHI__)
|
||||
#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
|
||||
#else
|
||||
#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
|
||||
#endif
|
||||
|
||||
/* If the structure has essentialy an unique element, return its type. */
|
||||
static int
|
||||
simple_type (ffi_type *arg)
|
||||
{
|
||||
if (arg->type != FFI_TYPE_STRUCT)
|
||||
return arg->type;
|
||||
else if (arg->elements[1])
|
||||
return FFI_TYPE_STRUCT;
|
||||
|
||||
return simple_type (arg->elements[0]);
|
||||
}
|
||||
|
||||
static int
|
||||
return_type (ffi_type *arg)
|
||||
{
|
||||
unsigned short type;
|
||||
|
||||
if (arg->type != FFI_TYPE_STRUCT)
|
||||
return arg->type;
|
||||
|
||||
type = simple_type (arg->elements[0]);
|
||||
if (! arg->elements[1])
|
||||
{
|
||||
switch (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:
|
||||
return FFI_TYPE_INT;
|
||||
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/* gcc uses r0/r1 pair for some kind of structures. */
|
||||
if (arg->size <= 2 * sizeof (int))
|
||||
{
|
||||
int i = 0;
|
||||
ffi_type *e;
|
||||
|
||||
while ((e = arg->elements[i++]))
|
||||
{
|
||||
type = simple_type (e);
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
return FFI_TYPE_UINT64;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FFI_TYPE_STRUCT;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register int tmp;
|
||||
register unsigned int avn;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
int greg, ireg;
|
||||
#if defined(__SH4__)
|
||||
int freg = 0;
|
||||
#endif
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
|
||||
}
|
||||
else
|
||||
ireg = 0;
|
||||
|
||||
/* Set arguments for registers. */
|
||||
greg = ireg;
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
if (greg++ >= NGREGARG)
|
||||
continue;
|
||||
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
argp += z;
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
#if defined(__SH4__)
|
||||
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (freg++ >= NFREGARG)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (greg++ >= NGREGARG)
|
||||
continue;
|
||||
}
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
argp += z;
|
||||
}
|
||||
#if defined(__SH4__)
|
||||
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
if (freg + 1 >= NFREGARG)
|
||||
continue;
|
||||
freg = (freg + 1) & ~1;
|
||||
freg += 2;
|
||||
memcpy (argp, *p_argv, z);
|
||||
argp += z;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (int) - 1) / sizeof (int);
|
||||
#if defined(__SH4__)
|
||||
if (greg + n - 1 >= NGREGARG)
|
||||
continue;
|
||||
#else
|
||||
if (greg >= NGREGARG)
|
||||
continue;
|
||||
#endif
|
||||
greg += n;
|
||||
memcpy (argp, *p_argv, z);
|
||||
argp += n * sizeof (int);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set arguments on stack. */
|
||||
greg = ireg;
|
||||
#if defined(__SH4__)
|
||||
freg = 0;
|
||||
#endif
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
if (greg++ < NGREGARG)
|
||||
continue;
|
||||
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
argp += z;
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
#if defined(__SH4__)
|
||||
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (freg++ < NFREGARG)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (greg++ < NGREGARG)
|
||||
continue;
|
||||
}
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
argp += z;
|
||||
}
|
||||
#if defined(__SH4__)
|
||||
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
if (freg + 1 < NFREGARG)
|
||||
{
|
||||
freg = (freg + 1) & ~1;
|
||||
freg += 2;
|
||||
continue;
|
||||
}
|
||||
memcpy (argp, *p_argv, z);
|
||||
argp += z;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (int) - 1) / sizeof (int);
|
||||
if (greg + n - 1 < NGREGARG)
|
||||
{
|
||||
greg += n;
|
||||
continue;
|
||||
}
|
||||
#if (! defined(__SH4__))
|
||||
else if (greg < NGREGARG)
|
||||
{
|
||||
greg = NGREGARG;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
memcpy (argp, *p_argv, z);
|
||||
argp += n * sizeof (int);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int i, j;
|
||||
int size, type;
|
||||
int n, m;
|
||||
int greg;
|
||||
#if defined(__SH4__)
|
||||
int freg = 0;
|
||||
#endif
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
|
||||
STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
|
||||
|
||||
#if defined(__SH4__)
|
||||
for (i = j = 0; i < cif->nargs && j < 12; i++)
|
||||
{
|
||||
type = (cif->arg_types)[i]->type;
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (freg >= NFREGARG)
|
||||
continue;
|
||||
freg++;
|
||||
cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
|
||||
j++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if ((freg + 1) >= NFREGARG)
|
||||
continue;
|
||||
freg = (freg + 1) & ~1;
|
||||
freg += 2;
|
||||
cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
|
||||
j++;
|
||||
break;
|
||||
|
||||
default:
|
||||
size = (cif->arg_types)[i]->size;
|
||||
n = (size + sizeof (int) - 1) / sizeof (int);
|
||||
if (greg + n - 1 >= NGREGARG)
|
||||
continue;
|
||||
greg += n;
|
||||
for (m = 0; m < n; m++)
|
||||
cif->flags += FFI_TYPE_INT << (2 * j++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i = j = 0; i < cif->nargs && j < 4; i++)
|
||||
{
|
||||
size = (cif->arg_types)[i]->size;
|
||||
n = (size + sizeof (int) - 1) / sizeof (int);
|
||||
if (greg >= NGREGARG)
|
||||
continue;
|
||||
else if (greg + n - 1 >= NGREGARG)
|
||||
n = NGREGARG - greg;
|
||||
greg += n;
|
||||
for (m = 0; m < n; m++)
|
||||
cif->flags += FFI_TYPE_INT << (2 * j++);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags += (unsigned) cif->rtype->type << 24;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << 24;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)());
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
UINT64 trvalue;
|
||||
|
||||
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 (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& return_type (cif->rtype) != FFI_TYPE_STRUCT)
|
||||
ecif.rvalue = &trvalue;
|
||||
else if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rvalue
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& return_type (cif->rtype) != FFI_TYPE_STRUCT)
|
||||
memcpy (rvalue, &trvalue, cif->rtype->size);
|
||||
}
|
||||
|
||||
extern void ffi_closure_SYSV (void);
|
||||
#if defined(__SH4__)
|
||||
extern void __ic_invalidate (void *line);
|
||||
#endif
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
unsigned short insn;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
/* Set T bit if the function returns a struct pointed with R2. */
|
||||
insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
|
||||
? 0x0018 /* sett */
|
||||
: 0x0008 /* clrt */);
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
tramp[0] = 0xd301d102;
|
||||
tramp[1] = 0x0000412b | (insn << 16);
|
||||
#else
|
||||
tramp[0] = 0xd102d301;
|
||||
tramp[1] = 0x412b0000 | insn;
|
||||
#endif
|
||||
*(void **) &tramp[2] = (void *)closure; /* ctx */
|
||||
*(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
#if defined(__SH4__)
|
||||
/* Flush the icache. */
|
||||
__ic_invalidate(&closure->tramp[0]);
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_SYSV, and on
|
||||
* entry, r3 holds the address of the closure.
|
||||
* After storing the registers that could possibly contain
|
||||
* parameters to be passed into the stack frame and setting
|
||||
* up space for a return value, ffi_closure_SYSV invokes the
|
||||
* following helper function to do most of the work.
|
||||
*/
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define OFS_INT8 0
|
||||
#define OFS_INT16 0
|
||||
#else
|
||||
#define OFS_INT8 3
|
||||
#define OFS_INT16 2
|
||||
#endif
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
||||
unsigned long *pgr, unsigned long *pfr,
|
||||
unsigned long *pst)
|
||||
{
|
||||
void **avalue;
|
||||
ffi_type **p_arg;
|
||||
int i, avn;
|
||||
int ireg, greg = 0;
|
||||
#if defined(__SH4__)
|
||||
int freg = 0;
|
||||
#endif
|
||||
ffi_cif *cif;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
/* Copy the caller's structure return value address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
|
||||
{
|
||||
rvalue = (void *) *pgr++;
|
||||
ireg = 1;
|
||||
}
|
||||
else
|
||||
ireg = 0;
|
||||
|
||||
cif = closure->cif;
|
||||
greg = ireg;
|
||||
avn = cif->nargs;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
if (greg++ >= NGREGARG)
|
||||
continue;
|
||||
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = (((char *)pgr) + OFS_INT8);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = (((char *)pgr) + OFS_INT16);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = pgr;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
pgr++;
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
#if defined(__SH4__)
|
||||
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (freg++ >= NFREGARG)
|
||||
continue;
|
||||
avalue[i] = pfr;
|
||||
pfr++;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (greg++ >= NGREGARG)
|
||||
continue;
|
||||
avalue[i] = pgr;
|
||||
pgr++;
|
||||
}
|
||||
}
|
||||
#if defined(__SH4__)
|
||||
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
if (freg + 1 >= NFREGARG)
|
||||
continue;
|
||||
if (freg & 1)
|
||||
pfr++;
|
||||
freg = (freg + 1) & ~1;
|
||||
freg += 2;
|
||||
avalue[i] = pfr;
|
||||
pfr += 2;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (int) - 1) / sizeof (int);
|
||||
#if defined(__SH4__)
|
||||
if (greg + n - 1 >= NGREGARG)
|
||||
continue;
|
||||
#else
|
||||
if (greg >= NGREGARG)
|
||||
continue;
|
||||
#endif
|
||||
greg += n;
|
||||
avalue[i] = pgr;
|
||||
pgr += n;
|
||||
}
|
||||
}
|
||||
|
||||
greg = ireg;
|
||||
#if defined(__SH4__)
|
||||
freg = 0;
|
||||
#endif
|
||||
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
if (greg++ < NGREGARG)
|
||||
continue;
|
||||
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = (((char *)pst) + OFS_INT8);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = (((char *)pst) + OFS_INT16);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = pst;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
pst++;
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
#if defined(__SH4__)
|
||||
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (freg++ < NFREGARG)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (greg++ < NGREGARG)
|
||||
continue;
|
||||
}
|
||||
avalue[i] = pst;
|
||||
pst++;
|
||||
}
|
||||
#if defined(__SH4__)
|
||||
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
if (freg + 1 < NFREGARG)
|
||||
{
|
||||
freg = (freg + 1) & ~1;
|
||||
freg += 2;
|
||||
continue;
|
||||
}
|
||||
avalue[i] = pst;
|
||||
pst += 2;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (int) - 1) / sizeof (int);
|
||||
if (greg + n - 1 < NGREGARG)
|
||||
{
|
||||
greg += n;
|
||||
continue;
|
||||
}
|
||||
#if (! defined(__SH4__))
|
||||
else if (greg < NGREGARG)
|
||||
{
|
||||
greg += n;
|
||||
pst += greg - NGREGARG;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = pst;
|
||||
pst += n;
|
||||
}
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_SYSV how to perform return type promotions. */
|
||||
return return_type (cif->rtype);
|
||||
}
|
||||
48
libffi/src/sh/ffitarget.h
Normal file
48
libffi/src/sh/ffitarget.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for SuperH.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
845
libffi/src/sh/sysv.S
Normal file
845
libffi/src/sh/sysv.S
Normal file
@@ -0,0 +1,845 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2002, 2003, 2004, 2006 Kaz Kojima
|
||||
|
||||
SuperH 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
/* XXX these lose for some platforms, I'm sure. */
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif
|
||||
|
||||
#if defined(__HITACHI__)
|
||||
#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
|
||||
#else
|
||||
#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
# r4: ffi_prep_args
|
||||
# r5: &ecif
|
||||
# r6: bytes
|
||||
# r7: flags
|
||||
# sp+0: rvalue
|
||||
# sp+4: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
ENTRY(ffi_call_SYSV)
|
||||
# Save registers
|
||||
.LFB1:
|
||||
mov.l r8,@-r15
|
||||
.LCFI0:
|
||||
mov.l r9,@-r15
|
||||
.LCFI1:
|
||||
mov.l r10,@-r15
|
||||
.LCFI2:
|
||||
mov.l r12,@-r15
|
||||
.LCFI3:
|
||||
mov.l r14,@-r15
|
||||
.LCFI4:
|
||||
sts.l pr,@-r15
|
||||
.LCFI5:
|
||||
mov r15,r14
|
||||
.LCFI6:
|
||||
#if defined(__SH4__)
|
||||
mov r6,r8
|
||||
mov r7,r9
|
||||
|
||||
sub r6,r15
|
||||
add #-16,r15
|
||||
mov #~7,r0
|
||||
and r0,r15
|
||||
|
||||
mov r4,r0
|
||||
jsr @r0
|
||||
mov r15,r4
|
||||
|
||||
mov r9,r1
|
||||
shlr8 r9
|
||||
shlr8 r9
|
||||
shlr8 r9
|
||||
|
||||
mov #FFI_TYPE_STRUCT,r2
|
||||
cmp/eq r2,r9
|
||||
bf 1f
|
||||
#if STRUCT_VALUE_ADDRESS_WITH_ARG
|
||||
mov.l @r15+,r4
|
||||
bra 2f
|
||||
mov #5,r2
|
||||
#else
|
||||
mov.l @r15+,r10
|
||||
#endif
|
||||
1:
|
||||
mov #4,r2
|
||||
2:
|
||||
mov #4,r3
|
||||
|
||||
L_pass:
|
||||
cmp/pl r8
|
||||
bf L_call_it
|
||||
|
||||
mov r1,r0
|
||||
and #3,r0
|
||||
|
||||
L_pass_d:
|
||||
cmp/eq #FFI_TYPE_DOUBLE,r0
|
||||
bf L_pass_f
|
||||
|
||||
mov r3,r0
|
||||
and #1,r0
|
||||
tst r0,r0
|
||||
bt 1f
|
||||
add #1,r3
|
||||
1:
|
||||
mov #12,r0
|
||||
cmp/hs r0,r3
|
||||
bt/s 3f
|
||||
shlr2 r1
|
||||
bsr L_pop_d
|
||||
nop
|
||||
3:
|
||||
add #2,r3
|
||||
bra L_pass
|
||||
add #-8,r8
|
||||
|
||||
L_pop_d:
|
||||
mov r3,r0
|
||||
add r0,r0
|
||||
add r3,r0
|
||||
add #-12,r0
|
||||
braf r0
|
||||
nop
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
fmov.s @r15+,fr5
|
||||
rts
|
||||
fmov.s @r15+,fr4
|
||||
fmov.s @r15+,fr7
|
||||
rts
|
||||
fmov.s @r15+,fr6
|
||||
fmov.s @r15+,fr9
|
||||
rts
|
||||
fmov.s @r15+,fr8
|
||||
fmov.s @r15+,fr11
|
||||
rts
|
||||
fmov.s @r15+,fr10
|
||||
#else
|
||||
fmov.s @r15+,fr4
|
||||
rts
|
||||
fmov.s @r15+,fr5
|
||||
fmov.s @r15+,fr6
|
||||
rts
|
||||
fmov.s @r15+,fr7
|
||||
fmov.s @r15+,fr8
|
||||
rts
|
||||
fmov.s @r15+,fr9
|
||||
fmov.s @r15+,fr10
|
||||
rts
|
||||
fmov.s @r15+,fr11
|
||||
#endif
|
||||
|
||||
L_pass_f:
|
||||
cmp/eq #FFI_TYPE_FLOAT,r0
|
||||
bf L_pass_i
|
||||
|
||||
mov #12,r0
|
||||
cmp/hs r0,r3
|
||||
bt/s 2f
|
||||
shlr2 r1
|
||||
bsr L_pop_f
|
||||
nop
|
||||
2:
|
||||
add #1,r3
|
||||
bra L_pass
|
||||
add #-4,r8
|
||||
|
||||
L_pop_f:
|
||||
mov r3,r0
|
||||
shll2 r0
|
||||
add #-16,r0
|
||||
braf r0
|
||||
nop
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
rts
|
||||
fmov.s @r15+,fr5
|
||||
rts
|
||||
fmov.s @r15+,fr4
|
||||
rts
|
||||
fmov.s @r15+,fr7
|
||||
rts
|
||||
fmov.s @r15+,fr6
|
||||
rts
|
||||
fmov.s @r15+,fr9
|
||||
rts
|
||||
fmov.s @r15+,fr8
|
||||
rts
|
||||
fmov.s @r15+,fr11
|
||||
rts
|
||||
fmov.s @r15+,fr10
|
||||
#else
|
||||
rts
|
||||
fmov.s @r15+,fr4
|
||||
rts
|
||||
fmov.s @r15+,fr5
|
||||
rts
|
||||
fmov.s @r15+,fr6
|
||||
rts
|
||||
fmov.s @r15+,fr7
|
||||
rts
|
||||
fmov.s @r15+,fr8
|
||||
rts
|
||||
fmov.s @r15+,fr9
|
||||
rts
|
||||
fmov.s @r15+,fr10
|
||||
rts
|
||||
fmov.s @r15+,fr11
|
||||
#endif
|
||||
|
||||
L_pass_i:
|
||||
cmp/eq #FFI_TYPE_INT,r0
|
||||
bf L_call_it
|
||||
|
||||
mov #8,r0
|
||||
cmp/hs r0,r2
|
||||
bt/s 2f
|
||||
shlr2 r1
|
||||
bsr L_pop_i
|
||||
nop
|
||||
2:
|
||||
add #1,r2
|
||||
bra L_pass
|
||||
add #-4,r8
|
||||
|
||||
L_pop_i:
|
||||
mov r2,r0
|
||||
shll2 r0
|
||||
add #-16,r0
|
||||
braf r0
|
||||
nop
|
||||
rts
|
||||
mov.l @r15+,r4
|
||||
rts
|
||||
mov.l @r15+,r5
|
||||
rts
|
||||
mov.l @r15+,r6
|
||||
rts
|
||||
mov.l @r15+,r7
|
||||
|
||||
L_call_it:
|
||||
# call function
|
||||
#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
|
||||
mov r10, r2
|
||||
#endif
|
||||
mov.l @(28,r14),r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
L_ret_d:
|
||||
mov #FFI_TYPE_DOUBLE,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_ret_ll
|
||||
|
||||
mov.l @(24,r14),r1
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
fmov.s fr1,@r1
|
||||
add #4,r1
|
||||
bra L_epilogue
|
||||
fmov.s fr0,@r1
|
||||
#else
|
||||
fmov.s fr0,@r1
|
||||
add #4,r1
|
||||
bra L_epilogue
|
||||
fmov.s fr1,@r1
|
||||
#endif
|
||||
|
||||
L_ret_ll:
|
||||
mov #FFI_TYPE_SINT64,r2
|
||||
cmp/eq r2,r9
|
||||
bt/s 1f
|
||||
mov #FFI_TYPE_UINT64,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_ret_f
|
||||
|
||||
1:
|
||||
mov.l @(24,r14),r2
|
||||
mov.l r0,@r2
|
||||
bra L_epilogue
|
||||
mov.l r1,@(4,r2)
|
||||
|
||||
L_ret_f:
|
||||
mov #FFI_TYPE_FLOAT,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_ret_i
|
||||
|
||||
mov.l @(24,r14),r1
|
||||
bra L_epilogue
|
||||
fmov.s fr0,@r1
|
||||
|
||||
L_ret_i:
|
||||
mov #FFI_TYPE_INT,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_epilogue
|
||||
|
||||
mov.l @(24,r14),r1
|
||||
bra L_epilogue
|
||||
mov.l r0,@r1
|
||||
|
||||
L_epilogue:
|
||||
# Remove the space we pushed for the args
|
||||
mov r14,r15
|
||||
|
||||
lds.l @r15+,pr
|
||||
mov.l @r15+,r14
|
||||
mov.l @r15+,r12
|
||||
mov.l @r15+,r10
|
||||
mov.l @r15+,r9
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
#else
|
||||
mov r6,r8
|
||||
mov r7,r9
|
||||
|
||||
sub r6,r15
|
||||
add #-16,r15
|
||||
mov #~7,r0
|
||||
and r0,r15
|
||||
|
||||
mov r4,r0
|
||||
jsr @r0
|
||||
mov r15,r4
|
||||
|
||||
mov r9,r3
|
||||
shlr8 r9
|
||||
shlr8 r9
|
||||
shlr8 r9
|
||||
|
||||
mov #FFI_TYPE_STRUCT,r2
|
||||
cmp/eq r2,r9
|
||||
bf 1f
|
||||
#if STRUCT_VALUE_ADDRESS_WITH_ARG
|
||||
mov.l @r15+,r4
|
||||
bra 2f
|
||||
mov #5,r2
|
||||
#else
|
||||
mov.l @r15+,r10
|
||||
#endif
|
||||
1:
|
||||
mov #4,r2
|
||||
2:
|
||||
|
||||
L_pass:
|
||||
cmp/pl r8
|
||||
bf L_call_it
|
||||
|
||||
mov r3,r0
|
||||
and #3,r0
|
||||
|
||||
L_pass_d:
|
||||
cmp/eq #FFI_TYPE_DOUBLE,r0
|
||||
bf L_pass_i
|
||||
|
||||
mov r15,r0
|
||||
and #7,r0
|
||||
tst r0,r0
|
||||
bt 1f
|
||||
add #4,r15
|
||||
1:
|
||||
mov #8,r0
|
||||
cmp/hs r0,r2
|
||||
bt/s 2f
|
||||
shlr2 r3
|
||||
bsr L_pop_d
|
||||
nop
|
||||
2:
|
||||
add #2,r2
|
||||
bra L_pass
|
||||
add #-8,r8
|
||||
|
||||
L_pop_d:
|
||||
mov r2,r0
|
||||
add r0,r0
|
||||
add r2,r0
|
||||
add #-12,r0
|
||||
add r0,r0
|
||||
braf r0
|
||||
nop
|
||||
mov.l @r15+,r4
|
||||
rts
|
||||
mov.l @r15+,r5
|
||||
mov.l @r15+,r5
|
||||
rts
|
||||
mov.l @r15+,r6
|
||||
mov.l @r15+,r6
|
||||
rts
|
||||
mov.l @r15+,r7
|
||||
rts
|
||||
mov.l @r15+,r7
|
||||
|
||||
L_pass_i:
|
||||
cmp/eq #FFI_TYPE_INT,r0
|
||||
bf L_call_it
|
||||
|
||||
mov #8,r0
|
||||
cmp/hs r0,r2
|
||||
bt/s 2f
|
||||
shlr2 r3
|
||||
bsr L_pop_i
|
||||
nop
|
||||
2:
|
||||
add #1,r2
|
||||
bra L_pass
|
||||
add #-4,r8
|
||||
|
||||
L_pop_i:
|
||||
mov r2,r0
|
||||
shll2 r0
|
||||
add #-16,r0
|
||||
braf r0
|
||||
nop
|
||||
rts
|
||||
mov.l @r15+,r4
|
||||
rts
|
||||
mov.l @r15+,r5
|
||||
rts
|
||||
mov.l @r15+,r6
|
||||
rts
|
||||
mov.l @r15+,r7
|
||||
|
||||
L_call_it:
|
||||
# call function
|
||||
#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
|
||||
mov r10, r2
|
||||
#endif
|
||||
mov.l @(28,r14),r1
|
||||
jsr @r1
|
||||
nop
|
||||
|
||||
L_ret_d:
|
||||
mov #FFI_TYPE_DOUBLE,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_ret_ll
|
||||
|
||||
mov.l @(24,r14),r2
|
||||
mov.l r0,@r2
|
||||
bra L_epilogue
|
||||
mov.l r1,@(4,r2)
|
||||
|
||||
L_ret_ll:
|
||||
mov #FFI_TYPE_SINT64,r2
|
||||
cmp/eq r2,r9
|
||||
bt/s 1f
|
||||
mov #FFI_TYPE_UINT64,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_ret_i
|
||||
|
||||
1:
|
||||
mov.l @(24,r14),r2
|
||||
mov.l r0,@r2
|
||||
bra L_epilogue
|
||||
mov.l r1,@(4,r2)
|
||||
|
||||
L_ret_i:
|
||||
mov #FFI_TYPE_FLOAT,r2
|
||||
cmp/eq r2,r9
|
||||
bt 1f
|
||||
mov #FFI_TYPE_INT,r2
|
||||
cmp/eq r2,r9
|
||||
bf L_epilogue
|
||||
1:
|
||||
mov.l @(24,r14),r1
|
||||
bra L_epilogue
|
||||
mov.l r0,@r1
|
||||
|
||||
L_epilogue:
|
||||
# Remove the space we pushed for the args
|
||||
mov r14,r15
|
||||
|
||||
lds.l @r15+,pr
|
||||
mov.l @r15+,r14
|
||||
mov.l @r15+,r12
|
||||
mov.l @r15+,r10
|
||||
mov.l @r15+,r9
|
||||
rts
|
||||
mov.l @r15+,r8
|
||||
#endif
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
.globl ffi_closure_helper_SYSV
|
||||
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB2:
|
||||
mov.l r7,@-r15
|
||||
.LCFI7:
|
||||
mov.l r6,@-r15
|
||||
.LCFI8:
|
||||
mov.l r5,@-r15
|
||||
.LCFI9:
|
||||
mov.l r4,@-r15
|
||||
.LCFIA:
|
||||
mov.l r14,@-r15
|
||||
.LCFIB:
|
||||
sts.l pr,@-r15
|
||||
|
||||
/* Stack layout:
|
||||
xx bytes (on stack parameters)
|
||||
16 bytes (register parameters)
|
||||
4 bytes (saved frame pointer)
|
||||
4 bytes (saved return address)
|
||||
32 bytes (floating register parameters, SH-4 only)
|
||||
8 bytes (result)
|
||||
4 bytes (pad)
|
||||
4 bytes (5th arg)
|
||||
<- new stack pointer
|
||||
*/
|
||||
.LCFIC:
|
||||
#if defined(__SH4__)
|
||||
add #-48,r15
|
||||
#else
|
||||
add #-16,r15
|
||||
#endif
|
||||
.LCFID:
|
||||
mov r15,r14
|
||||
.LCFIE:
|
||||
|
||||
#if defined(__SH4__)
|
||||
mov r14,r1
|
||||
add #48,r1
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
fmov.s fr10,@-r1
|
||||
fmov.s fr11,@-r1
|
||||
fmov.s fr8,@-r1
|
||||
fmov.s fr9,@-r1
|
||||
fmov.s fr6,@-r1
|
||||
fmov.s fr7,@-r1
|
||||
fmov.s fr4,@-r1
|
||||
fmov.s fr5,@-r1
|
||||
#else
|
||||
fmov.s fr11,@-r1
|
||||
fmov.s fr10,@-r1
|
||||
fmov.s fr9,@-r1
|
||||
fmov.s fr8,@-r1
|
||||
fmov.s fr7,@-r1
|
||||
fmov.s fr6,@-r1
|
||||
fmov.s fr5,@-r1
|
||||
fmov.s fr4,@-r1
|
||||
#endif
|
||||
mov r1,r7
|
||||
mov r14,r6
|
||||
add #56,r6
|
||||
#else
|
||||
mov r14,r6
|
||||
add #24,r6
|
||||
#endif
|
||||
|
||||
bt/s 10f
|
||||
mov r2, r5
|
||||
mov r14,r1
|
||||
add #8,r1
|
||||
mov r1,r5
|
||||
10:
|
||||
|
||||
mov r14,r1
|
||||
#if defined(__SH4__)
|
||||
add #72,r1
|
||||
#else
|
||||
add #40,r1
|
||||
#endif
|
||||
mov.l r1,@r14
|
||||
|
||||
#ifdef PIC
|
||||
mov.l L_got,r1
|
||||
mova L_got,r0
|
||||
add r0,r1
|
||||
mov.l L_helper,r0
|
||||
add r1,r0
|
||||
#else
|
||||
mov.l L_helper,r0
|
||||
#endif
|
||||
jsr @r0
|
||||
mov r3,r4
|
||||
|
||||
shll r0
|
||||
mov r0,r1
|
||||
mova L_table,r0
|
||||
add r1,r0
|
||||
mov.w @r0,r0
|
||||
mov r14,r2
|
||||
braf r0
|
||||
add #8,r2
|
||||
0:
|
||||
.align 2
|
||||
#ifdef PIC
|
||||
L_got:
|
||||
.long _GLOBAL_OFFSET_TABLE_
|
||||
L_helper:
|
||||
.long ffi_closure_helper_SYSV@GOTOFF
|
||||
#else
|
||||
L_helper:
|
||||
.long ffi_closure_helper_SYSV
|
||||
#endif
|
||||
L_table:
|
||||
.short L_case_v - 0b /* FFI_TYPE_VOID */
|
||||
.short L_case_i - 0b /* FFI_TYPE_INT */
|
||||
#if defined(__SH4__)
|
||||
.short L_case_f - 0b /* FFI_TYPE_FLOAT */
|
||||
.short L_case_d - 0b /* FFI_TYPE_DOUBLE */
|
||||
.short L_case_d - 0b /* FFI_TYPE_LONGDOUBLE */
|
||||
#else
|
||||
.short L_case_i - 0b /* FFI_TYPE_FLOAT */
|
||||
.short L_case_ll - 0b /* FFI_TYPE_DOUBLE */
|
||||
.short L_case_ll - 0b /* FFI_TYPE_LONGDOUBLE */
|
||||
#endif
|
||||
.short L_case_uq - 0b /* FFI_TYPE_UINT8 */
|
||||
.short L_case_q - 0b /* FFI_TYPE_SINT8 */
|
||||
.short L_case_uh - 0b /* FFI_TYPE_UINT16 */
|
||||
.short L_case_h - 0b /* FFI_TYPE_SINT16 */
|
||||
.short L_case_i - 0b /* FFI_TYPE_UINT32 */
|
||||
.short L_case_i - 0b /* FFI_TYPE_SINT32 */
|
||||
.short L_case_ll - 0b /* FFI_TYPE_UINT64 */
|
||||
.short L_case_ll - 0b /* FFI_TYPE_SINT64 */
|
||||
.short L_case_v - 0b /* FFI_TYPE_STRUCT */
|
||||
.short L_case_i - 0b /* FFI_TYPE_POINTER */
|
||||
|
||||
#if defined(__SH4__)
|
||||
L_case_d:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
fmov.s @r2+,fr1
|
||||
bra L_case_v
|
||||
fmov.s @r2,fr0
|
||||
#else
|
||||
fmov.s @r2+,fr0
|
||||
bra L_case_v
|
||||
fmov.s @r2,fr1
|
||||
#endif
|
||||
|
||||
L_case_f:
|
||||
bra L_case_v
|
||||
fmov.s @r2,fr0
|
||||
#endif
|
||||
|
||||
L_case_ll:
|
||||
mov.l @r2+,r0
|
||||
bra L_case_v
|
||||
mov.l @r2,r1
|
||||
|
||||
L_case_i:
|
||||
bra L_case_v
|
||||
mov.l @r2,r0
|
||||
|
||||
L_case_q:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#else
|
||||
add #3,r2
|
||||
#endif
|
||||
bra L_case_v
|
||||
mov.b @r2,r0
|
||||
|
||||
L_case_uq:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#else
|
||||
add #3,r2
|
||||
#endif
|
||||
mov.b @r2,r0
|
||||
bra L_case_v
|
||||
extu.b r0,r0
|
||||
|
||||
L_case_h:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#else
|
||||
add #2,r2
|
||||
#endif
|
||||
bra L_case_v
|
||||
mov.w @r2,r0
|
||||
|
||||
L_case_uh:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#else
|
||||
add #2,r2
|
||||
#endif
|
||||
mov.w @r2,r0
|
||||
extu.w r0,r0
|
||||
/* fall through */
|
||||
|
||||
L_case_v:
|
||||
#if defined(__SH4__)
|
||||
add #48,r15
|
||||
#else
|
||||
add #16,r15
|
||||
#endif
|
||||
lds.l @r15+,pr
|
||||
mov.l @r15+,r14
|
||||
rts
|
||||
add #16,r15
|
||||
.LFE2:
|
||||
.ffi_closure_SYSV_end:
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame","aw",@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.4byte 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#ifdef PIC
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.byte 0x0 /* CIE Augmentation */
|
||||
#endif
|
||||
.byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
|
||||
.byte 0x7c /* sleb128 -4; CIE Data Alignment Factor */
|
||||
.byte 0x11 /* CIE RA Column */
|
||||
#ifdef PIC
|
||||
.uleb128 0x1 /* Augmentation size */
|
||||
.byte 0x10 /* FDE Encoding (pcrel) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.byte 0xf /* uleb128 0xf */
|
||||
.byte 0x0 /* uleb128 0x0 */
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-__FRAME_BEGIN__ /* FDE CIE offset */
|
||||
#ifdef PIC
|
||||
.4byte .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 /* FDE address range */
|
||||
#ifdef PIC
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x4 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x8 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0xc /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI3-.LCFI2
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x10 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI4-.LCFI3
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x14 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI5-.LCFI4
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x18 /* uleb128 0x4 */
|
||||
.byte 0x91 /* DW_CFA_offset, column 0x11 */
|
||||
.byte 0x6 /* uleb128 0x6 */
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.byte 0x5 /* uleb128 0x5 */
|
||||
.byte 0x8c /* DW_CFA_offset, column 0xc */
|
||||
.byte 0x4 /* uleb128 0x4 */
|
||||
.byte 0x8a /* DW_CFA_offset, column 0xa */
|
||||
.byte 0x3 /* uleb128 0x3 */
|
||||
.byte 0x89 /* DW_CFA_offset, column 0x9 */
|
||||
.byte 0x2 /* uleb128 0x2 */
|
||||
.byte 0x88 /* DW_CFA_offset, column 0x8 */
|
||||
.byte 0x1 /* uleb128 0x1 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI6-.LCFI5
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.byte 0xe /* uleb128 0xe */
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
.LSFDE3:
|
||||
.4byte .LEFDE3-.LASFDE3 /* FDE Length */
|
||||
.LASFDE3:
|
||||
.4byte .LASFDE3-__FRAME_BEGIN__ /* FDE CIE offset */
|
||||
#ifdef PIC
|
||||
.4byte .LFB2-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB2 /* FDE initial location */
|
||||
#endif
|
||||
.4byte .LFE2-.LFB2 /* FDE address range */
|
||||
#ifdef PIC
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI7-.LFB2
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x4 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI8-.LCFI7
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x8 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI9-.LCFI8
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0xc /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFIA-.LCFI9
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x10 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFIB-.LCFIA
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x14 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFIC-.LCFIB
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x18 /* uleb128 0x4 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFID-.LCFIC
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
#if defined(__SH4__)
|
||||
.byte 24+48 /* uleb128 24+48 */
|
||||
#else
|
||||
.byte 24+16 /* uleb128 24+16 */
|
||||
#endif
|
||||
.byte 0x91 /* DW_CFA_offset, column 0x11 */
|
||||
.byte 0x6 /* uleb128 0x6 */
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.byte 0x5 /* uleb128 0x5 */
|
||||
.byte 0x84 /* DW_CFA_offset, column 0x4 */
|
||||
.byte 0x4 /* uleb128 0x4 */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 */
|
||||
.byte 0x3 /* uleb128 0x3 */
|
||||
.byte 0x86 /* DW_CFA_offset, column 0x6 */
|
||||
.byte 0x2 /* uleb128 0x2 */
|
||||
.byte 0x87 /* DW_CFA_offset, column 0x7 */
|
||||
.byte 0x1 /* uleb128 0x1 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFIE-.LCFID
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.byte 0xe /* uleb128 0xe */
|
||||
.align 2
|
||||
.LEFDE3:
|
||||
455
libffi/src/sh64/ffi.c
Normal file
455
libffi/src/sh64/ffi.c
Normal file
@@ -0,0 +1,455 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2003, 2004, 2006 Kaz Kojima
|
||||
|
||||
SuperH SHmedia 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>
|
||||
|
||||
#define NGREGARG 8
|
||||
#define NFREGARG 12
|
||||
|
||||
static int
|
||||
return_type (ffi_type *arg)
|
||||
{
|
||||
|
||||
if (arg->type != FFI_TYPE_STRUCT)
|
||||
return arg->type;
|
||||
|
||||
/* gcc uses r2 if the result can be packed in on register. */
|
||||
if (arg->size <= sizeof (UINT8))
|
||||
return FFI_TYPE_UINT8;
|
||||
else if (arg->size <= sizeof (UINT16))
|
||||
return FFI_TYPE_UINT16;
|
||||
else if (arg->size <= sizeof (UINT32))
|
||||
return FFI_TYPE_UINT32;
|
||||
else if (arg->size <= sizeof (UINT64))
|
||||
return FFI_TYPE_UINT64;
|
||||
|
||||
return FFI_TYPE_STRUCT;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
register unsigned int i;
|
||||
register unsigned int avn;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
|
||||
avn = ecif->cif->nargs;
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
|
||||
{
|
||||
size_t z;
|
||||
int align;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
align = (*p_arg)->alignment;
|
||||
if (z < sizeof (UINT32))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
else if (z == sizeof (UINT32) && align == sizeof (UINT32))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
*(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
else if (z == sizeof (UINT64)
|
||||
&& align == sizeof (UINT64)
|
||||
&& ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
|
||||
{
|
||||
*(UINT64 *) argp = *(UINT64 *) (*p_argv);
|
||||
argp += sizeof (UINT64);
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
|
||||
|
||||
memcpy (argp, *p_argv, z);
|
||||
argp += n * sizeof (UINT64);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
int i, j;
|
||||
int size, type;
|
||||
int n, m;
|
||||
int greg;
|
||||
int freg;
|
||||
int fpair = -1;
|
||||
|
||||
greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
|
||||
freg = 0;
|
||||
cif->flags2 = 0;
|
||||
|
||||
for (i = j = 0; i < cif->nargs; i++)
|
||||
{
|
||||
type = (cif->arg_types)[i]->type;
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
greg++;
|
||||
cif->bytes += sizeof (UINT64) - sizeof (float);
|
||||
if (freg >= NFREGARG - 1)
|
||||
continue;
|
||||
if (fpair < 0)
|
||||
{
|
||||
fpair = freg;
|
||||
freg += 2;
|
||||
}
|
||||
else
|
||||
fpair = -1;
|
||||
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
|
||||
continue;
|
||||
if ((freg + 1) < NFREGARG)
|
||||
{
|
||||
freg += 2;
|
||||
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
|
||||
}
|
||||
else
|
||||
cif->flags2 += FFI_TYPE_INT << (2 * j++);
|
||||
break;
|
||||
|
||||
default:
|
||||
size = (cif->arg_types)[i]->size;
|
||||
if (size < sizeof (UINT64))
|
||||
cif->bytes += sizeof (UINT64) - size;
|
||||
n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
|
||||
if (greg >= NGREGARG)
|
||||
continue;
|
||||
else if (greg + n - 1 >= NGREGARG)
|
||||
greg = NGREGARG;
|
||||
else
|
||||
greg += n;
|
||||
for (m = 0; m < n; m++)
|
||||
cif->flags2 += FFI_TYPE_INT << (2 * j++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags = return_type (cif->rtype);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = cif->rtype->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, long long, unsigned *,
|
||||
void (*fn)());
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
UINT64 trvalue;
|
||||
|
||||
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 (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& return_type (cif->rtype) != FFI_TYPE_STRUCT)
|
||||
ecif.rvalue = &trvalue;
|
||||
else if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->flags2,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rvalue
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& return_type (cif->rtype) != FFI_TYPE_STRUCT)
|
||||
memcpy (rvalue, &trvalue, cif->rtype->size);
|
||||
}
|
||||
|
||||
extern void ffi_closure_SYSV (void);
|
||||
extern void __ic_invalidate (void *line);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
/* Since ffi_closure is an aligned object, the ffi trampoline is
|
||||
called as an SHcompact code. Sigh.
|
||||
SHcompact part:
|
||||
mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
|
||||
SHmedia part:
|
||||
movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
|
||||
movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63 */
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
tramp[0] = 0x7001c701;
|
||||
tramp[1] = 0x0009402b;
|
||||
#else
|
||||
tramp[0] = 0xc7017001;
|
||||
tramp[1] = 0x402b0009;
|
||||
#endif
|
||||
tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
|
||||
tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
|
||||
tramp[4] = 0x6bf10600;
|
||||
tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
|
||||
tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
|
||||
tramp[7] = 0x4401fff0;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. */
|
||||
asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* Basically the trampoline invokes ffi_closure_SYSV, and on
|
||||
* entry, r3 holds the address of the closure.
|
||||
* After storing the registers that could possibly contain
|
||||
* parameters to be passed into the stack frame and setting
|
||||
* up space for a return value, ffi_closure_SYSV invokes the
|
||||
* following helper function to do most of the work.
|
||||
*/
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
|
||||
UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
|
||||
{
|
||||
void **avalue;
|
||||
ffi_type **p_arg;
|
||||
int i, avn;
|
||||
int greg, freg;
|
||||
ffi_cif *cif;
|
||||
int fpair = -1;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
/* Copy the caller's structure return value address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (UINT64 *) *pgr;
|
||||
greg = 1;
|
||||
}
|
||||
else
|
||||
greg = 0;
|
||||
|
||||
freg = 0;
|
||||
cif = closure->cif;
|
||||
avn = cif->nargs;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
void *p;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (UINT32))
|
||||
{
|
||||
p = pgr + greg++;
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_STRUCT:
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
avalue[i] = p;
|
||||
#else
|
||||
avalue[i] = ((char *) p) + sizeof (UINT32) - z;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof (UINT32))
|
||||
{
|
||||
if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
if (freg < NFREGARG - 1)
|
||||
{
|
||||
if (fpair >= 0)
|
||||
{
|
||||
avalue[i] = (UINT32 *) pfr + fpair;
|
||||
fpair = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
fpair = freg;
|
||||
avalue[i] = (UINT32 *) pfr + (1 ^ freg);
|
||||
#else
|
||||
fpair = 1 ^ freg;
|
||||
avalue[i] = (UINT32 *) pfr + freg;
|
||||
#endif
|
||||
freg += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
avalue[i] = pgr + greg;
|
||||
#else
|
||||
avalue[i] = (UINT32 *) (pgr + greg) + 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
avalue[i] = pgr + greg;
|
||||
#else
|
||||
avalue[i] = (UINT32 *) (pgr + greg) + 1;
|
||||
#endif
|
||||
greg++;
|
||||
}
|
||||
else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
if (freg + 1 >= NFREGARG)
|
||||
avalue[i] = pgr + greg;
|
||||
else
|
||||
{
|
||||
avalue[i] = pfr + (freg >> 1);
|
||||
freg += 2;
|
||||
}
|
||||
greg++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
|
||||
|
||||
avalue[i] = pgr + greg;
|
||||
greg += n;
|
||||
}
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_SYSV how to perform return type promotions. */
|
||||
return return_type (cif->rtype);
|
||||
}
|
||||
|
||||
52
libffi/src/sh64/ffitarget.h
Normal file
52
libffi/src/sh64/ffitarget.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for SuperH - SHmedia.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_SYSV,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
|
||||
#define FFI_EXTRA_CIF_FIELDS long long flags2
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
533
libffi/src/sh64/sysv.S
Normal file
533
libffi/src/sh64/sysv.S
Normal file
@@ -0,0 +1,533 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2003, 2004, 2006 Kaz Kojima
|
||||
|
||||
SuperH SHmedia 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
/* XXX these lose for some platforms, I'm sure. */
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define OFS_FLT 0
|
||||
#else
|
||||
#define OFS_FLT 4
|
||||
#endif
|
||||
|
||||
.section .text..SHmedia32,"ax"
|
||||
|
||||
# r2: ffi_prep_args
|
||||
# r3: &ecif
|
||||
# r4: bytes
|
||||
# r5: flags
|
||||
# r6: flags2
|
||||
# r7: rvalue
|
||||
# r8: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.align 5
|
||||
ENTRY(ffi_call_SYSV)
|
||||
# Save registers
|
||||
.LFB1:
|
||||
addi.l r15, -48, r15
|
||||
.LCFI0:
|
||||
st.q r15, 40, r32
|
||||
st.q r15, 32, r31
|
||||
st.q r15, 24, r30
|
||||
st.q r15, 16, r29
|
||||
st.q r15, 8, r28
|
||||
st.l r15, 4, r18
|
||||
st.l r15, 0, r14
|
||||
.LCFI1:
|
||||
add.l r15, r63, r14
|
||||
.LCFI2:
|
||||
# add r4, r63, r28
|
||||
add r5, r63, r29
|
||||
add r6, r63, r30
|
||||
add r7, r63, r31
|
||||
add r8, r63, r32
|
||||
|
||||
addi r4, (64 + 7), r4
|
||||
andi r4, ~7, r4
|
||||
sub.l r15, r4, r15
|
||||
|
||||
ptabs/l r2, tr0
|
||||
add r15, r63, r2
|
||||
blink tr0, r18
|
||||
|
||||
addi r15, 64, r22
|
||||
movi 0, r0
|
||||
movi 0, r1
|
||||
movi -1, r23
|
||||
|
||||
pt/l 1f, tr1
|
||||
bnei/l r29, FFI_TYPE_STRUCT, tr1
|
||||
ld.l r15, 0, r19
|
||||
addi r15, 8, r15
|
||||
addi r0, 1, r0
|
||||
1:
|
||||
|
||||
.L_pass:
|
||||
andi r30, 3, r20
|
||||
shlri r30, 2, r30
|
||||
|
||||
pt/l .L_call_it, tr0
|
||||
pt/l .L_pass_i, tr1
|
||||
pt/l .L_pass_f, tr2
|
||||
|
||||
beqi/l r20, FFI_TYPE_VOID, tr0
|
||||
beqi/l r20, FFI_TYPE_INT, tr1
|
||||
beqi/l r20, FFI_TYPE_FLOAT, tr2
|
||||
|
||||
.L_pass_d:
|
||||
addi r0, 1, r0
|
||||
pt/l 3f, tr0
|
||||
movi 12, r20
|
||||
bge/l r1, r20, tr0
|
||||
|
||||
pt/l .L_pop_d, tr1
|
||||
pt/l 2f, tr0
|
||||
blink tr1, r63
|
||||
2:
|
||||
addi.l r15, 8, r15
|
||||
3:
|
||||
pt/l .L_pass, tr0
|
||||
addi r1, 2, r1
|
||||
blink tr0, r63
|
||||
|
||||
.L_pop_d:
|
||||
pt/l .L_pop_d_tbl, tr1
|
||||
gettr tr1, r20
|
||||
shlli r1, 2, r21
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
|
||||
.L_pop_d_tbl:
|
||||
fld.d r15, 0, dr0
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr2
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr4
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr6
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr8
|
||||
blink tr0, r63
|
||||
fld.d r15, 0, dr10
|
||||
blink tr0, r63
|
||||
|
||||
.L_pass_f:
|
||||
addi r0, 1, r0
|
||||
pt/l 3f, tr0
|
||||
movi 12, r20
|
||||
bge/l r1, r20, tr0
|
||||
|
||||
pt/l .L_pop_f, tr1
|
||||
pt/l 2f, tr0
|
||||
blink tr1, r63
|
||||
2:
|
||||
addi.l r15, 8, r15
|
||||
3:
|
||||
pt/l .L_pass, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.L_pop_f:
|
||||
pt/l .L_pop_f_tbl, tr1
|
||||
pt/l 5f, tr2
|
||||
gettr tr1, r20
|
||||
bge/l r23, r63, tr2
|
||||
add r1, r63, r23
|
||||
shlli r1, 3, r21
|
||||
addi r1, 2, r1
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
5:
|
||||
addi r23, 1, r21
|
||||
movi -1, r23
|
||||
shlli r21, 3, r21
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
|
||||
.L_pop_f_tbl:
|
||||
fld.s r15, OFS_FLT, fr0
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr1
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr2
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr3
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr4
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr5
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr6
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr7
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr8
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr9
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr10
|
||||
blink tr0, r63
|
||||
fld.s r15, OFS_FLT, fr11
|
||||
blink tr0, r63
|
||||
|
||||
.L_pass_i:
|
||||
pt/l 3f, tr0
|
||||
movi 8, r20
|
||||
bge/l r0, r20, tr0
|
||||
|
||||
pt/l .L_pop_i, tr1
|
||||
pt/l 2f, tr0
|
||||
blink tr1, r63
|
||||
2:
|
||||
addi.l r15, 8, r15
|
||||
3:
|
||||
pt/l .L_pass, tr0
|
||||
addi r0, 1, r0
|
||||
blink tr0, r63
|
||||
|
||||
.L_pop_i:
|
||||
pt/l .L_pop_i_tbl, tr1
|
||||
gettr tr1, r20
|
||||
shlli r0, 3, r21
|
||||
add r20, r21, r20
|
||||
ptabs/l r20, tr1
|
||||
blink tr1, r63
|
||||
|
||||
.L_pop_i_tbl:
|
||||
ld.q r15, 0, r2
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r3
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r4
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r5
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r6
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r7
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r8
|
||||
blink tr0, r63
|
||||
ld.q r15, 0, r9
|
||||
blink tr0, r63
|
||||
|
||||
.L_call_it:
|
||||
# call function
|
||||
pt/l 1f, tr1
|
||||
bnei/l r29, FFI_TYPE_STRUCT, tr1
|
||||
add r19, r63, r2
|
||||
1:
|
||||
add r22, r63, r15
|
||||
ptabs/l r32, tr0
|
||||
blink tr0, r18
|
||||
|
||||
pt/l .L_ret_i, tr0
|
||||
pt/l .L_ret_ll, tr1
|
||||
pt/l .L_ret_d, tr2
|
||||
pt/l .L_ret_f, tr3
|
||||
pt/l .L_epilogue, tr4
|
||||
|
||||
beqi/l r29, FFI_TYPE_INT, tr0
|
||||
beqi/l r29, FFI_TYPE_UINT32, tr0
|
||||
beqi/l r29, FFI_TYPE_SINT64, tr1
|
||||
beqi/l r29, FFI_TYPE_UINT64, tr1
|
||||
beqi/l r29, FFI_TYPE_DOUBLE, tr2
|
||||
beqi/l r29, FFI_TYPE_FLOAT, tr3
|
||||
|
||||
pt/l .L_ret_q, tr0
|
||||
pt/l .L_ret_h, tr1
|
||||
|
||||
beqi/l r29, FFI_TYPE_UINT8, tr0
|
||||
beqi/l r29, FFI_TYPE_UINT16, tr1
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_d:
|
||||
fst.d r31, 0, dr0
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_ll:
|
||||
st.q r31, 0, r2
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_f:
|
||||
fst.s r31, OFS_FLT, fr0
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_q:
|
||||
st.b r31, 0, r2
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_h:
|
||||
st.w r31, 0, r2
|
||||
blink tr4, r63
|
||||
|
||||
.L_ret_i:
|
||||
st.l r31, 0, r2
|
||||
# Fall
|
||||
|
||||
.L_epilogue:
|
||||
# Remove the space we pushed for the args
|
||||
add r14, r63, r15
|
||||
|
||||
ld.l r15, 0, r14
|
||||
ld.l r15, 4, r18
|
||||
ld.q r15, 8, r28
|
||||
ld.q r15, 16, r29
|
||||
ld.q r15, 24, r30
|
||||
ld.q r15, 32, r31
|
||||
ld.q r15, 40, r32
|
||||
addi.l r15, 48, r15
|
||||
ptabs r18, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
.align 5
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB2:
|
||||
addi.l r15, -136, r15
|
||||
.LCFI3:
|
||||
st.l r15, 12, r18
|
||||
st.l r15, 8, r14
|
||||
st.l r15, 4, r12
|
||||
.LCFI4:
|
||||
add r15, r63, r14
|
||||
.LCFI5:
|
||||
/* Stack layout:
|
||||
...
|
||||
64 bytes (register parameters)
|
||||
48 bytes (floating register parameters)
|
||||
8 bytes (result)
|
||||
4 bytes (r18)
|
||||
4 bytes (r14)
|
||||
4 bytes (r12)
|
||||
4 bytes (for align)
|
||||
<- new stack pointer
|
||||
*/
|
||||
fst.d r14, 24, dr0
|
||||
fst.d r14, 32, dr2
|
||||
fst.d r14, 40, dr4
|
||||
fst.d r14, 48, dr6
|
||||
fst.d r14, 56, dr8
|
||||
fst.d r14, 64, dr10
|
||||
st.q r14, 72, r2
|
||||
st.q r14, 80, r3
|
||||
st.q r14, 88, r4
|
||||
st.q r14, 96, r5
|
||||
st.q r14, 104, r6
|
||||
st.q r14, 112, r7
|
||||
st.q r14, 120, r8
|
||||
st.q r14, 128, r9
|
||||
|
||||
add r1, r63, r2
|
||||
addi r14, 16, r3
|
||||
addi r14, 72, r4
|
||||
addi r14, 24, r5
|
||||
addi r14, 136, r6
|
||||
#ifdef PIC
|
||||
movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
|
||||
shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
|
||||
.LPCS0: ptrel/u r12, tr0
|
||||
movi ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
|
||||
gettr tr0, r12
|
||||
ldx.l r1, r12, r1
|
||||
ptabs r1, tr0
|
||||
#else
|
||||
pt/l ffi_closure_helper_SYSV, tr0
|
||||
#endif
|
||||
blink tr0, r18
|
||||
|
||||
shlli r2, 1, r1
|
||||
movi (((datalabel .L_table) >> 16) & 65535), r2
|
||||
shori ((datalabel .L_table) & 65535), r2
|
||||
ldx.w r2, r1, r1
|
||||
add r1, r2, r1
|
||||
pt/l .L_case_v, tr1
|
||||
ptabs r1, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.align 2
|
||||
.L_table:
|
||||
.word .L_case_v - datalabel .L_table /* FFI_TYPE_VOID */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_INT */
|
||||
.word .L_case_f - datalabel .L_table /* FFI_TYPE_FLOAT */
|
||||
.word .L_case_d - datalabel .L_table /* FFI_TYPE_DOUBLE */
|
||||
.word .L_case_d - datalabel .L_table /* FFI_TYPE_LONGDOUBLE */
|
||||
.word .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */
|
||||
.word .L_case_q - datalabel .L_table /* FFI_TYPE_SINT8 */
|
||||
.word .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */
|
||||
.word .L_case_h - datalabel .L_table /* FFI_TYPE_SINT16 */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_UINT32 */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_SINT32 */
|
||||
.word .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */
|
||||
.word .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */
|
||||
.word .L_case_v - datalabel .L_table /* FFI_TYPE_STRUCT */
|
||||
.word .L_case_i - datalabel .L_table /* FFI_TYPE_POINTER */
|
||||
|
||||
.align 2
|
||||
.L_case_d:
|
||||
fld.d r14, 16, dr0
|
||||
blink tr1, r63
|
||||
.L_case_f:
|
||||
fld.s r14, 16, fr0
|
||||
blink tr1, r63
|
||||
.L_case_ll:
|
||||
ld.q r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_i:
|
||||
ld.l r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_q:
|
||||
ld.b r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_uq:
|
||||
ld.ub r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_h:
|
||||
ld.w r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_uh:
|
||||
ld.uw r14, 16, r2
|
||||
blink tr1, r63
|
||||
.L_case_v:
|
||||
add.l r14, r63, r15
|
||||
ld.l r15, 4, r12
|
||||
ld.l r15, 8, r14
|
||||
ld.l r15, 12, r18
|
||||
addi.l r15, 136, r15
|
||||
ptabs r18, tr0
|
||||
blink tr0, r63
|
||||
|
||||
.LFE2:
|
||||
.ffi_closure_SYSV_end:
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame","aw",@progbits
|
||||
__FRAME_BEGIN__:
|
||||
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.4byte 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#ifdef PIC
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.byte 0x0 /* CIE Augmentation */
|
||||
#endif
|
||||
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||
.byte 0x12 /* CIE RA Column */
|
||||
#ifdef PIC
|
||||
.uleb128 0x1 /* Augmentation size */
|
||||
.byte 0x10 /* FDE Encoding (pcrel) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.uleb128 0xf
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte datalabel .LEFDE1-datalabel .LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.4byte datalabel .LASFDE1-datalabel __FRAME_BEGIN__
|
||||
#ifdef PIC
|
||||
.4byte .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.4byte datalabel .LFE1-datalabel .LFB1 /* FDE address range */
|
||||
#ifdef PIC
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI0-datalabel .LFB1
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.uleb128 0x30
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI1-datalabel .LCFI0
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.uleb128 0xc
|
||||
.byte 0x92 /* DW_CFA_offset, column 0x12 */
|
||||
.uleb128 0xb
|
||||
.byte 0x9c /* DW_CFA_offset, column 0x1c */
|
||||
.uleb128 0xa
|
||||
.byte 0x9d /* DW_CFA_offset, column 0x1d */
|
||||
.uleb128 0x8
|
||||
.byte 0x9e /* DW_CFA_offset, column 0x1e */
|
||||
.uleb128 0x6
|
||||
.byte 0x9f /* DW_CFA_offset, column 0x1f */
|
||||
.uleb128 0x4
|
||||
.byte 0xa0 /* DW_CFA_offset, column 0x20 */
|
||||
.uleb128 0x2
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI2-datalabel .LCFI1
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0xe
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
.LSFDE3:
|
||||
.4byte datalabel .LEFDE3-datalabel .LASFDE3 /* FDE Length */
|
||||
.LASFDE3:
|
||||
.4byte datalabel .LASFDE3-datalabel __FRAME_BEGIN__
|
||||
#ifdef PIC
|
||||
.4byte .LFB2-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB2 /* FDE initial location */
|
||||
#endif
|
||||
.4byte datalabel .LFE2-datalabel .LFB2 /* FDE address range */
|
||||
#ifdef PIC
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI3-datalabel .LFB2
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.uleb128 0x88
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI4-datalabel .LCFI3
|
||||
.byte 0x8c /* DW_CFA_offset, column 0xc */
|
||||
.uleb128 0x21
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.uleb128 0x20
|
||||
.byte 0x92 /* DW_CFA_offset, column 0x12 */
|
||||
.uleb128 0x1f
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte datalabel .LCFI5-datalabel .LCFI4
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0xe
|
||||
.align 2
|
||||
.LEFDE3:
|
||||
@@ -1,7 +1,7 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996 Cygnus Solutions
|
||||
ffi.c - Copyright (c) 1996, 2003, 2004 Red Hat, Inc.
|
||||
|
||||
Sparc Foreign Function Interface
|
||||
SPARC Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -24,24 +24,21 @@
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_private.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_v8(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(int);
|
||||
|
||||
@@ -66,18 +63,12 @@ void ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
||||
((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++)
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
if (avn)
|
||||
{
|
||||
avn--;
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| (*p_arg)->type == FFI_TYPE_LONGDOUBLE
|
||||
@@ -122,7 +113,6 @@ void ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -159,6 +149,7 @@ int ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
||||
ecif->cif->rtype->size > 32)
|
||||
{
|
||||
*(unsigned long long *) argp = (unsigned long)ecif->rvalue;
|
||||
argp += sizeof(long long);
|
||||
tmp = 1;
|
||||
}
|
||||
|
||||
@@ -331,7 +322,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
||||
int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
||||
{
|
||||
ffi_type **ptr = &arg->elements[0];
|
||||
|
||||
@@ -343,18 +334,19 @@ int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *fl
|
||||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
off = ffi_V9_return_struct(*ptr, off, ret, intg, flt);
|
||||
off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
|
||||
off = ALIGN(off, FFI_SIZEOF_ARG);
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
memcpy(ret + off, flt + off, (*ptr)->size);
|
||||
memmove(ret + off, flt + off, (*ptr)->size);
|
||||
off += (*ptr)->size;
|
||||
break;
|
||||
default:
|
||||
memcpy(ret + off, intg + off, (*ptr)->size);
|
||||
memmove(ret + off, intg + off, (*ptr)->size);
|
||||
off += (*ptr)->size;
|
||||
break;
|
||||
}
|
||||
@@ -363,10 +355,14 @@ int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *fl
|
||||
return off;
|
||||
}
|
||||
|
||||
extern int ffi_call_V8(void *, extended_cif *, unsigned,
|
||||
|
||||
#ifdef SPARC64
|
||||
extern int ffi_call_v9(void *, extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)());
|
||||
extern int ffi_call_V9(void *, extended_cif *, unsigned,
|
||||
#else
|
||||
extern int ffi_call_v8(void *, extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)());
|
||||
#endif
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
@@ -399,16 +395,16 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
/* We don't yet support calling 32bit code from 64bit */
|
||||
FFI_ASSERT(0);
|
||||
#else
|
||||
ffi_call_V8(ffi_prep_args_v8, &ecif, cif->bytes,
|
||||
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
|
||||
cif->flags, rvalue, fn);
|
||||
#endif
|
||||
break;
|
||||
case FFI_V9:
|
||||
#ifdef SPARC64
|
||||
ffi_call_V9(ffi_prep_args_v9, &ecif, cif->bytes,
|
||||
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
|
||||
cif->flags, rval, fn);
|
||||
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
ffi_V9_return_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
|
||||
ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
|
||||
#else
|
||||
/* And vice versa */
|
||||
FFI_ASSERT(0);
|
||||
@@ -420,3 +416,193 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef SPARC64
|
||||
extern void ffi_closure_v9(void);
|
||||
#else
|
||||
extern void ffi_closure_v8(void);
|
||||
#endif
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn;
|
||||
#ifdef SPARC64
|
||||
/* Trampoline address is equal to the closure address. We take advantage
|
||||
of that to reduce the trampoline size by 8 bytes. */
|
||||
FFI_ASSERT (cif->abi == FFI_V9);
|
||||
fn = (unsigned long) ffi_closure_v9;
|
||||
tramp[0] = 0x83414000; /* rd %pc, %g1 */
|
||||
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
|
||||
tramp[2] = 0x81c14000; /* jmp %g5 */
|
||||
tramp[3] = 0x01000000; /* nop */
|
||||
*((unsigned long *) &tramp[4]) = fn;
|
||||
#else
|
||||
unsigned long ctx = (unsigned long) closure;
|
||||
FFI_ASSERT (cif->abi == FFI_V8);
|
||||
fn = (unsigned long) ffi_closure_v8;
|
||||
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
|
||||
tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
|
||||
tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */
|
||||
tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the Icache. FIXME: alignment isn't certain, assume 8 bytes */
|
||||
#ifdef SPARC64
|
||||
asm volatile ("flush %0" : : "r" (closure) : "memory");
|
||||
asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
|
||||
#else
|
||||
asm volatile ("iflush %0" : : "r" (closure) : "memory");
|
||||
asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory");
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_sparc_inner_v8(ffi_closure *closure,
|
||||
void *rvalue, unsigned long *gpr, unsigned long *scratch)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
ffi_type **arg_types;
|
||||
void **avalue;
|
||||
int i, argn;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_types = cif->arg_types;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
/* Copy the caller's structure return address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| cif->flags == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
)
|
||||
rvalue = (void *) gpr[0];
|
||||
|
||||
/* Always skip the structure return address. */
|
||||
argn = 1;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
if (arg_types[i]->type == FFI_TYPE_STRUCT
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* Straight copy of invisible reference. */
|
||||
avalue[i] = (void *)gpr[argn++];
|
||||
}
|
||||
else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
|
||||
|| arg_types[i]->type == FFI_TYPE_SINT64
|
||||
|| arg_types[i]->type == FFI_TYPE_UINT64)
|
||||
/* gpr is 8-byte aligned. */
|
||||
&& (argn % 2) != 0)
|
||||
{
|
||||
/* Align on a 8-byte boundary. */
|
||||
scratch[0] = gpr[argn];
|
||||
scratch[1] = gpr[argn+1];
|
||||
avalue[i] = scratch;
|
||||
scratch -= 2;
|
||||
argn += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Always right-justify. */
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_sparc_inner_v9(ffi_closure *closure,
|
||||
void *rvalue, unsigned long *gpr, double *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
ffi_type **arg_types;
|
||||
void **avalue;
|
||||
int i, argn, fp_slot_max;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_types = cif->arg_types;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
/* Copy the caller's structure return address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_VOID
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) gpr[0];
|
||||
/* Skip the structure return address. */
|
||||
argn = 1;
|
||||
}
|
||||
else
|
||||
argn = 0;
|
||||
|
||||
fp_slot_max = 16 - argn;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
if (arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (arg_types[i]->size > 16)
|
||||
{
|
||||
/* Straight copy of invisible reference. */
|
||||
avalue[i] = (void *)gpr[argn++];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left-justify. */
|
||||
ffi_v9_layout_struct(arg_types[i],
|
||||
0,
|
||||
(char *) &gpr[argn],
|
||||
(char *) &gpr[argn],
|
||||
(char *) &fpr[argn]);
|
||||
avalue[i] = &gpr[argn];
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Right-justify. */
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
|
||||
if (i < fp_slot_max
|
||||
&& (arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| arg_types[i]->type == FFI_TYPE_DOUBLE
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
||||
#endif
|
||||
))
|
||||
avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
|
||||
else
|
||||
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
65
libffi/src/sparc/ffitarget.h
Normal file
65
libffi/src/sparc/ffitarget.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for SPARC.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#if defined(__arch64__) || defined(__sparcv9)
|
||||
#define SPARC64
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_V8,
|
||||
FFI_V8PLUS,
|
||||
FFI_V9,
|
||||
#ifdef SPARC64
|
||||
FFI_DEFAULT_ABI = FFI_V9,
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_V8,
|
||||
#endif
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef SPARC64
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
267
libffi/src/sparc/v8.S
Normal file
267
libffi/src/sparc/v8.S
Normal file
@@ -0,0 +1,267 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
v8.S - Copyright (c) 1996, 1997, 2003, 2004 Red Hat, Inc.
|
||||
|
||||
SPARC 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#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:
|
||||
.LLFB1:
|
||||
save %sp, -STACKFRAME, %sp
|
||||
.LLCFI0:
|
||||
|
||||
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
|
||||
nop ! STRUCT returning functions skip 12 instead of 8 bytes
|
||||
|
||||
! 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_SINT64
|
||||
be longlong
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
bne done
|
||||
nop
|
||||
st %f0, [%i4+0]
|
||||
st %f1, [%i4+4]
|
||||
|
||||
done:
|
||||
ret
|
||||
restore
|
||||
|
||||
longlong:
|
||||
st %o0, [%i4+0]
|
||||
st %o1, [%i4+4]
|
||||
ret
|
||||
restore
|
||||
.LLFE1:
|
||||
|
||||
.ffi_call_v8_end:
|
||||
.size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
|
||||
|
||||
|
||||
#undef STACKFRAME
|
||||
#define STACKFRAME 104 /* 16*4 register window +
|
||||
1*4 struct return +
|
||||
6*4 args backing store +
|
||||
3*4 locals */
|
||||
|
||||
/* ffi_closure_v8(...)
|
||||
|
||||
Receives the closure argument in %g2. */
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_closure_v8
|
||||
|
||||
ffi_closure_v8:
|
||||
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
|
||||
.register %g2, #scratch
|
||||
#endif
|
||||
.LLFB2:
|
||||
! Reserve frame space for all arguments in case
|
||||
! we need to align them on a 8-byte boundary.
|
||||
ld [%g2+FFI_TRAMPOLINE_SIZE], %g1
|
||||
ld [%g1+4], %g1
|
||||
sll %g1, 3, %g1
|
||||
add %g1, STACKFRAME, %g1
|
||||
! %g1 == STACKFRAME + 8*nargs
|
||||
neg %g1
|
||||
save %sp, %g1, %sp
|
||||
.LLCFI1:
|
||||
|
||||
! Store all of the potential argument registers in va_list format.
|
||||
st %i0, [%fp+68+0]
|
||||
st %i1, [%fp+68+4]
|
||||
st %i2, [%fp+68+8]
|
||||
st %i3, [%fp+68+12]
|
||||
st %i4, [%fp+68+16]
|
||||
st %i5, [%fp+68+20]
|
||||
|
||||
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
||||
mov %g2, %o0
|
||||
add %fp, -8, %o1
|
||||
add %fp, 64, %o2
|
||||
call ffi_closure_sparc_inner_v8
|
||||
add %fp, -16, %o3
|
||||
|
||||
! Load up the return value in the proper type.
|
||||
! See ffi_prep_cif_machdep for the list of cases.
|
||||
cmp %o0, FFI_TYPE_VOID
|
||||
be done1
|
||||
|
||||
cmp %o0, FFI_TYPE_INT
|
||||
be integer
|
||||
|
||||
cmp %o0, FFI_TYPE_FLOAT
|
||||
be,a done1
|
||||
ld [%fp-8], %f0
|
||||
|
||||
cmp %o0, FFI_TYPE_DOUBLE
|
||||
be,a done1
|
||||
ldd [%fp-8], %f0
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
cmp %o0, FFI_TYPE_LONGDOUBLE
|
||||
be done2
|
||||
#endif
|
||||
|
||||
cmp %o0, FFI_TYPE_STRUCT
|
||||
be done2
|
||||
|
||||
! FFI_TYPE_SINT64
|
||||
! FFI_TYPE_UINT64
|
||||
ld [%fp-4], %i1
|
||||
|
||||
integer:
|
||||
ld [%fp-8], %i0
|
||||
|
||||
done1:
|
||||
jmp %i7+8
|
||||
restore
|
||||
done2:
|
||||
! Skip 'unimp'.
|
||||
jmp %i7+12
|
||||
restore
|
||||
.LLFE2:
|
||||
|
||||
.ffi_closure_v8_end:
|
||||
.size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
|
||||
|
||||
#ifdef SPARC64
|
||||
#define WS 8
|
||||
#define nword xword
|
||||
#define uanword uaxword
|
||||
#else
|
||||
#define WS 4
|
||||
#define nword long
|
||||
#define uanword uaword
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RO_EH_FRAME
|
||||
.section ".eh_frame",#alloc
|
||||
#else
|
||||
.section ".eh_frame",#alloc,#write
|
||||
#endif
|
||||
.LLframe1:
|
||||
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
|
||||
.LLSCIE1:
|
||||
.uaword 0x0 ! CIE Identifier Tag
|
||||
.byte 0x1 ! CIE Version
|
||||
.ascii "zR\0" ! CIE Augmentation
|
||||
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor
|
||||
.byte 0xf ! CIE RA Column
|
||||
.byte 0x1 ! uleb128 0x1; Augmentation size
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.byte 0x1b ! FDE Encoding (pcrel sdata4)
|
||||
#else
|
||||
.byte 0x50 ! FDE Encoding (aligned absolute)
|
||||
#endif
|
||||
.byte 0xc ! DW_CFA_def_cfa
|
||||
.byte 0xe ! uleb128 0xe
|
||||
.byte 0x0 ! uleb128 0x0
|
||||
.align WS
|
||||
.LLECIE1:
|
||||
.LLSFDE1:
|
||||
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
|
||||
.LLASFDE1:
|
||||
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB1)
|
||||
.uaword .LLFE1-.LLFB1 ! FDE address range
|
||||
#else
|
||||
.align WS
|
||||
.nword .LLFB1
|
||||
.uanword .LLFE1-.LLFB1 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI0-.LLFB1
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align WS
|
||||
.LLEFDE1:
|
||||
.LLSFDE2:
|
||||
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
|
||||
.LLASFDE2:
|
||||
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB2)
|
||||
.uaword .LLFE2-.LLFB2 ! FDE address range
|
||||
#else
|
||||
.align WS
|
||||
.nword .LLFB2
|
||||
.uanword .LLFE2-.LLFB2 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI1-.LLFB2
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align WS
|
||||
.LLEFDE2:
|
||||
302
libffi/src/sparc/v9.S
Normal file
302
libffi/src/sparc/v9.S
Normal file
@@ -0,0 +1,302 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
v9.S - Copyright (c) 2000, 2003, 2004 Red Hat, Inc.
|
||||
|
||||
SPARC 64-bit 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef SPARC64
|
||||
/* Only compile this in for 64bit builds, because otherwise the object file
|
||||
will have inproper architecture due to used instructions. */
|
||||
|
||||
#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
|
||||
#define STACK_BIAS 2047
|
||||
#define ARGS (128) /* Offset of register area in frame */
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_call_v9
|
||||
.globl _ffi_call_v9
|
||||
|
||||
ffi_call_v9:
|
||||
_ffi_call_v9:
|
||||
.LLFB1:
|
||||
save %sp, -STACKFRAME, %sp
|
||||
.LLCFI0:
|
||||
|
||||
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
|
||||
add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
|
||||
! frame to set up
|
||||
|
||||
mov %l0, %o0 ! call routine to set up frame
|
||||
call %i0
|
||||
mov %i1, %o1 ! (delay)
|
||||
brz,pt %o0, 1f
|
||||
ldx [%l0+ARGS], %o0 ! call foreign function
|
||||
|
||||
ldd [%l0+ARGS], %f0
|
||||
ldd [%l0+ARGS+8], %f2
|
||||
ldd [%l0+ARGS+16], %f4
|
||||
ldd [%l0+ARGS+24], %f6
|
||||
ldd [%l0+ARGS+32], %f8
|
||||
ldd [%l0+ARGS+40], %f10
|
||||
ldd [%l0+ARGS+48], %f12
|
||||
ldd [%l0+ARGS+56], %f14
|
||||
ldd [%l0+ARGS+64], %f16
|
||||
ldd [%l0+ARGS+72], %f18
|
||||
ldd [%l0+ARGS+80], %f20
|
||||
ldd [%l0+ARGS+88], %f22
|
||||
ldd [%l0+ARGS+96], %f24
|
||||
ldd [%l0+ARGS+104], %f26
|
||||
ldd [%l0+ARGS+112], %f28
|
||||
ldd [%l0+ARGS+120], %f30
|
||||
|
||||
1: ldx [%l0+ARGS+8], %o1
|
||||
ldx [%l0+ARGS+16], %o2
|
||||
ldx [%l0+ARGS+24], %o3
|
||||
ldx [%l0+ARGS+32], %o4
|
||||
ldx [%l0+ARGS+40], %o5
|
||||
call %i5
|
||||
sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
|
||||
|
||||
! If the return value pointer is NULL, assume no return value.
|
||||
brz,pn %i4, done
|
||||
nop
|
||||
|
||||
cmp %i3, FFI_TYPE_INT
|
||||
be,a,pt %icc, done
|
||||
stx %o0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_FLOAT
|
||||
be,a,pn %icc, done
|
||||
st %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
be,a,pn %icc, done
|
||||
std %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_STRUCT
|
||||
be,pn %icc, dostruct
|
||||
|
||||
cmp %i3, FFI_TYPE_LONGDOUBLE
|
||||
bne,pt %icc, done
|
||||
nop
|
||||
std %f0, [%i4+0]
|
||||
std %f2, [%i4+8]
|
||||
|
||||
done: ret
|
||||
restore
|
||||
|
||||
dostruct:
|
||||
/* This will not work correctly for unions. */
|
||||
stx %o0, [%i4+0]
|
||||
stx %o1, [%i4+8]
|
||||
stx %o2, [%i4+16]
|
||||
stx %o3, [%i4+24]
|
||||
std %f0, [%i4+32]
|
||||
std %f2, [%i4+40]
|
||||
std %f4, [%i4+48]
|
||||
std %f6, [%i4+56]
|
||||
ret
|
||||
restore
|
||||
.LLFE1:
|
||||
|
||||
.ffi_call_v9_end:
|
||||
.size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
|
||||
|
||||
|
||||
#undef STACKFRAME
|
||||
#define STACKFRAME 336 /* 16*8 register window +
|
||||
6*8 args backing store +
|
||||
20*8 locals */
|
||||
#define FP %fp+STACK_BIAS
|
||||
|
||||
/* ffi_closure_v9(...)
|
||||
|
||||
Receives the closure argument in %g1. */
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_closure_v9
|
||||
|
||||
ffi_closure_v9:
|
||||
.LLFB2:
|
||||
save %sp, -STACKFRAME, %sp
|
||||
.LLCFI1:
|
||||
|
||||
! Store all of the potential argument registers in va_list format.
|
||||
stx %i0, [FP+128+0]
|
||||
stx %i1, [FP+128+8]
|
||||
stx %i2, [FP+128+16]
|
||||
stx %i3, [FP+128+24]
|
||||
stx %i4, [FP+128+32]
|
||||
stx %i5, [FP+128+40]
|
||||
|
||||
! Store possible floating point argument registers too.
|
||||
std %f0, [FP-128]
|
||||
std %f2, [FP-120]
|
||||
std %f4, [FP-112]
|
||||
std %f6, [FP-104]
|
||||
std %f8, [FP-96]
|
||||
std %f10, [FP-88]
|
||||
std %f12, [FP-80]
|
||||
std %f14, [FP-72]
|
||||
std %f16, [FP-64]
|
||||
std %f18, [FP-56]
|
||||
std %f20, [FP-48]
|
||||
std %f22, [FP-40]
|
||||
std %f24, [FP-32]
|
||||
std %f26, [FP-24]
|
||||
std %f28, [FP-16]
|
||||
std %f30, [FP-8]
|
||||
|
||||
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
||||
mov %g1, %o0
|
||||
add %fp, STACK_BIAS-160, %o1
|
||||
add %fp, STACK_BIAS+128, %o2
|
||||
call ffi_closure_sparc_inner_v9
|
||||
add %fp, STACK_BIAS-128, %o3
|
||||
|
||||
! Load up the return value in the proper type.
|
||||
! See ffi_prep_cif_machdep for the list of cases.
|
||||
cmp %o0, FFI_TYPE_VOID
|
||||
be,pn %icc, done1
|
||||
|
||||
cmp %o0, FFI_TYPE_INT
|
||||
be,pn %icc, integer
|
||||
|
||||
cmp %o0, FFI_TYPE_FLOAT
|
||||
be,a,pn %icc, done1
|
||||
ld [FP-160], %f0
|
||||
|
||||
cmp %o0, FFI_TYPE_DOUBLE
|
||||
be,a,pn %icc, done1
|
||||
ldd [FP-160], %f0
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
cmp %o0, FFI_TYPE_LONGDOUBLE
|
||||
be,a,pn %icc, longdouble1
|
||||
ldd [FP-160], %f0
|
||||
#endif
|
||||
|
||||
! FFI_TYPE_STRUCT
|
||||
ldx [FP-152], %i1
|
||||
ldx [FP-144], %i2
|
||||
ldx [FP-136], %i3
|
||||
ldd [FP-160], %f0
|
||||
ldd [FP-152], %f2
|
||||
ldd [FP-144], %f4
|
||||
ldd [FP-136], %f6
|
||||
|
||||
integer:
|
||||
ldx [FP-160], %i0
|
||||
|
||||
done1:
|
||||
ret
|
||||
restore
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
longdouble1:
|
||||
ldd [FP-152], %f2
|
||||
ret
|
||||
restore
|
||||
#endif
|
||||
.LLFE2:
|
||||
|
||||
.ffi_closure_v9_end:
|
||||
.size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
|
||||
|
||||
#ifdef HAVE_RO_EH_FRAME
|
||||
.section ".eh_frame",#alloc
|
||||
#else
|
||||
.section ".eh_frame",#alloc,#write
|
||||
#endif
|
||||
.LLframe1:
|
||||
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
|
||||
.LLSCIE1:
|
||||
.uaword 0x0 ! CIE Identifier Tag
|
||||
.byte 0x1 ! CIE Version
|
||||
.ascii "zR\0" ! CIE Augmentation
|
||||
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 ! sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 0xf ! CIE RA Column
|
||||
.byte 0x1 ! uleb128 0x1; Augmentation size
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.byte 0x1b ! FDE Encoding (pcrel sdata4)
|
||||
#else
|
||||
.byte 0x50 ! FDE Encoding (aligned absolute)
|
||||
#endif
|
||||
.byte 0xc ! DW_CFA_def_cfa
|
||||
.byte 0xe ! uleb128 0xe
|
||||
.byte 0xff,0xf ! uleb128 0x7ff
|
||||
.align 8
|
||||
.LLECIE1:
|
||||
.LLSFDE1:
|
||||
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
|
||||
.LLASFDE1:
|
||||
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB1)
|
||||
.uaword .LLFE1-.LLFB1 ! FDE address range
|
||||
#else
|
||||
.align 8
|
||||
.xword .LLFB1
|
||||
.uaxword .LLFE1-.LLFB1 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI0-.LLFB1
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align 8
|
||||
.LLEFDE1:
|
||||
.LLSFDE2:
|
||||
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
|
||||
.LLASFDE2:
|
||||
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB2)
|
||||
.uaword .LLFE2-.LLFB2 ! FDE address range
|
||||
#else
|
||||
.align 8
|
||||
.xword .LLFB2
|
||||
.uaxword .LLFE2-.LLFB2 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI1-.LLFB2
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align 8
|
||||
.LLEFDE2:
|
||||
#endif
|
||||
60
libffi/src/types.c
Normal file
60
libffi/src/types.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
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>
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
#define FFI_TYPEDEF(name, type, id) \
|
||||
struct struct_align_##name { \
|
||||
char c; \
|
||||
type x; \
|
||||
}; \
|
||||
ffi_type ffi_type_##name = { \
|
||||
sizeof(type), \
|
||||
offsetof(struct struct_align_##name, x), \
|
||||
id, NULL \
|
||||
}
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
ffi_type ffi_type_void = {
|
||||
1, 1, FFI_TYPE_VOID, NULL
|
||||
};
|
||||
|
||||
FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
|
||||
FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
|
||||
FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
|
||||
FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
|
||||
FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
|
||||
FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
|
||||
FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
|
||||
FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
|
||||
|
||||
FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
|
||||
|
||||
FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
|
||||
FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
|
||||
FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user