Commit b1760f7f by Richard Henderson Committed by Richard Henderson

Merge libffi to upstream commit c82cc159426d8d4402375fa1ae3f045b9cf82e16

From-SVN: r219477
parent 62e22fcb
2015-01-12 Richard Henderson <rth@redhat.com>
Merge to upstream commit c82cc159426d8d4402375fa1ae3f045b9cf82e16.
2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
PR bootstrap/63784
......
libffi - Copyright (c) 1996-2012 Anthony Green, Red Hat, Inc and others.
libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others.
See source files for details.
Permission is hereby granted, free of charge, to any person obtaining
......
#!/bin/sh
PLATFORM_IOS=/Developer/Platforms/iPhoneOS.platform/
PLATFORM_IOS_SIM=/Developer/Platforms/iPhoneSimulator.platform/
SDK_IOS_VERSION="4.2"
MIN_IOS_VERSION="3.0"
OUTPUT_DIR="universal-ios"
build_target () {
local platform=$1
local sdk=$2
local arch=$3
local triple=$4
local builddir=$5
mkdir -p "${builddir}"
pushd "${builddir}"
export CC="${platform}"/Developer/usr/bin/gcc-4.2
export CFLAGS="-arch ${arch} -isysroot ${sdk} -miphoneos-version-min=${MIN_IOS_VERSION}"
../configure --host=${triple} && make
popd
}
# Build all targets
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv6 arm-apple-darwin10 armv6-ios
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv7 arm-apple-darwin10 armv7-ios
build_target "${PLATFORM_IOS_SIM}" "${PLATFORM_IOS_SIM}/Developer/SDKs/iPhoneSimulator${SDK_IOS_VERSION}.sdk/" i386 i386-apple-darwin10 i386-ios-sim
# Create universal output directories
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}/include"
mkdir -p "${OUTPUT_DIR}/include/armv6"
mkdir -p "${OUTPUT_DIR}/include/armv7"
mkdir -p "${OUTPUT_DIR}/include/i386"
# Create the universal binary
lipo -create armv6-ios/.libs/libffi.a armv7-ios/.libs/libffi.a i386-ios-sim/.libs/libffi.a -output "${OUTPUT_DIR}/libffi.a"
# Copy in the headers
copy_headers () {
local src=$1
local dest=$2
# Fix non-relative header reference
sed 's/<ffitarget.h>/"ffitarget.h"/' < "${src}/include/ffi.h" > "${dest}/ffi.h"
cp "${src}/include/ffitarget.h" "${dest}"
}
copy_headers armv6-ios "${OUTPUT_DIR}/include/armv6"
copy_headers armv7-ios "${OUTPUT_DIR}/include/armv7"
copy_headers i386-ios-sim "${OUTPUT_DIR}/include/i386"
# Create top-level header
(
cat << EOF
#ifdef __arm__
#include <arm/arch.h>
#ifdef _ARM_ARCH_6
#include "include/armv6/ffi.h"
#elif _ARM_ARCH_7
#include "include/armv7/ffi.h"
#endif
#elif defined(__i386__)
#include "include/i386/ffi.h"
#endif
EOF
) > "${OUTPUT_DIR}/ffi.h"
This source diff could not be displayed because it is too large. You can view the blob instead.
# configure.host
#
# This shell script handles all host based configuration for libffi.
#
#
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
# Most of the time we can define all the variables all at once...
case "${host}" in
frv*-elf)
LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
;;
aarch64*-*-*)
TARGET=AARCH64; TARGETDIR=aarch64
SOURCES="ffi.c sysv.S"
;;
alpha*-*-*)
TARGET=ALPHA; TARGETDIR=alpha;
# Support 128-bit long double, changeable via command-line switch.
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
SOURCES="ffi.c osf.S"
;;
arc*-*-*)
TARGET=ARC; TARGETDIR=arc
SOURCES="ffi.c arcompact.S"
;;
arm*-*-*)
TARGET=ARM; TARGETDIR=arm
SOURCES="ffi.c sysv.S"
;;
avr32*-*-*)
TARGET=AVR32; TARGETDIR=avr32
SOURCES="ffi.c sysv.S"
;;
bfin*)
TARGET=BFIN; TARGETDIR=bfin
SOURCES="ffi.c sysv.S"
;;
cris-*-*)
TARGET=LIBFFI_CRIS; TARGETDIR=cris
SOURCES="ffi.c sysv.S"
;;
frv-*-*)
TARGET=FRV; TARGETDIR=frv
SOURCES="ffi.c eabi.S"
;;
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
TARGET=PA_LINUX; TARGETDIR=pa
SOURCES="ffi.c linux.S"
;;
hppa*64-*-hpux*)
TARGET=PA64_HPUX; TARGETDIR=pa
;;
hppa*-*-hpux*)
TARGET=PA_HPUX; TARGETDIR=pa
SOURCES="ffi.c hpux32.S"
;;
i?86-*-freebsd* | i?86-*-openbsd*)
TARGET=X86_FREEBSD; TARGETDIR=x86
;;
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix* \
| x86_64-*-cygwin* | x86_64-*-mingw*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
TARGET=X86_WIN32
else
TARGET=X86_WIN64
fi
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
# We must also check with_cross_host to decide if this is a native
# or cross-build and select where to install dlls appropriately.
if test -n "$with_cross_host" &&
test x"$with_cross_host" != x"no"; then
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
else
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
fi
;;
i?86-*-darwin* | x86_64-*-darwin*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
TARGET=X86_DARWIN
else
TARGET=X86_64_DARWIN
fi
;;
i?86-*-* | x86_64-*-* | amd64-*)
TARGETDIR=x86
if test $ac_cv_sizeof_size_t = 4; then
case "$host" in
*-gnux32)
TARGET=X86_64
;;
*)
TARGET=X86
;;
esac
else
TARGET=X86_64;
fi
;;
ia64*-*-*)
TARGET=IA64; TARGETDIR=ia64
SOURCES="ffi.c unix.S"
;;
m32r*-*-*)
TARGET=M32R; TARGETDIR=m32r
SOURCES="ffi.c sysv.S"
;;
m68k-*-*)
TARGET=M68K; TARGETDIR=m68k
SOURCES="ffi.c sysv.S"
;;
m88k-*-*)
TARGET=M88K; TARGETDIR=m88k
SOURCES="ffi.c obsd.S"
;;
microblaze*-*-*)
TARGET=MICROBLAZE; TARGETDIR=microblaze
SOURCES="ffi.c sysv.S"
;;
moxie-*-*)
TARGET=MOXIE; TARGETDIR=moxie
SOURCES="ffi.c eabi.S"
;;
metag-*-*)
TARGET=METAG; TARGETDIR=metag
SOURCES="ffi.c sysv.S"
;;
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
TARGET=MIPS; TARGETDIR=mips
;;
mips*-*linux* | mips*-*-openbsd*)
# Support 128-bit long double for NewABI.
HAVE_LONG_DOUBLE='defined(__mips64)'
TARGET=MIPS; TARGETDIR=mips
;;
nios2*-linux*)
TARGET=NIOS2; TARGETDIR=nios2
SOURCES="ffi.c sysv.S"
;;
or1k*-linux*)
TARGET=OR1K; TARGETDIR=or1k
SOURCES="ffi.c sysv.S"
;;
powerpc*-*-linux* | powerpc-*-sysv*)
TARGET=POWERPC; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc-*-amigaos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-beos*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc-*-darwin* | powerpc64-*-darwin*)
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
;;
powerpc-*-aix* | rs6000-*-aix*)
TARGET=POWERPC_AIX; TARGETDIR=powerpc
;;
powerpc-*-freebsd* | powerpc-*-openbsd*)
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
HAVE_LONG_DOUBLE_VARIANT=1
;;
powerpc64-*-freebsd*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
powerpc*-*-rtems*)
TARGET=POWERPC; TARGETDIR=powerpc
;;
s390-*-* | s390x-*-*)
TARGET=S390; TARGETDIR=s390
SOURCES="ffi.c sysv.S"
;;
sh-*-* | sh[[34]]*-*-*)
TARGET=SH; TARGETDIR=sh
SOURCES="ffi.c sysv.S"
;;
sh64-*-* | sh5*-*-*)
TARGET=SH64; TARGETDIR=sh64
SOURCES="ffi.c sysv.S"
;;
sparc*-*-*)
TARGET=SPARC; TARGETDIR=sparc
SOURCES="ffi.c ffi64.c v8.S v9.S"
;;
tile*-*)
TARGET=TILE; TARGETDIR=tile
SOURCES="ffi.c tile.S"
;;
vax-*-*)
TARGET=VAX; TARGETDIR=vax
SOURCES="ffi.c elfbsd.S"
;;
xtensa*-*)
TARGET=XTENSA; TARGETDIR=xtensa
SOURCES="ffi.c sysv.S"
;;
esac
# ... but some of the cases above share configury.
case "${TARGET}" in
MIPS)
SOURCES="ffi.c o32.S n32.S"
;;
POWERPC)
SOURCES="ffi.c ffi_sysv.c ffi_linux64.c sysv.S ppc_closure.S"
SOURCES="${SOURCES} linux64.S linux64_closure.S"
;;
POWERPC_AIX)
SOURCES="ffi_darwin.c aix.S aix_closure.S"
;;
POWERPC_DARWIN)
SOURCES="ffi_darwin.c darwin.S darwin_closure.S"
;;
POWERPC_FREEBSD)
SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S"
;;
X86 | X86_FREEBSD | X86_WIN32)
SOURCES="ffi.c sysv.S"
;;
X86_64)
SOURCES="ffi64.c unix64.S"
;;
X86_WIN64)
SOURCES="ffiw64.c win64.S"
;;
X86_DARWIN)
SOURCES="darwin_c.c darwin.S"
;;
X86_64_DARWIN)
SOURCES="darwin64_c.c darwin64.S"
;;
esac
# If we failed to configure SOURCES, we can't do anything.
if test -z "${SOURCES}"; then
UNSUPPORTED=1
fi
......@@ -63,14 +63,14 @@ section entitled ``GNU General Public License''.
@node Introduction
@chapter What is libffi?
Compilers for high-level languages generate code that follow certain
Compilers for high level languages generate code that follow certain
conventions. These conventions are necessary, in part, for separate
compilation to work. One such convention is the @dfn{calling
convention}. The calling convention is a set of assumptions made by
the compiler about where function arguments will be found on entry to
a function. A calling convention also specifies where the return
value for a function is found. The calling convention is part of
what is called the @dfn{ABI} or @dfn{Application Binary Interface}.
value for a function is found. The calling convention is also
sometimes called the @dfn{ABI} or @dfn{Application Binary Interface}.
@cindex calling convention
@cindex ABI
@cindex Application Binary Interface
......@@ -247,6 +247,8 @@ int main()
* Primitive Types:: Built-in types.
* Structures:: Structure types.
* Type Example:: Structure type example.
* Complex:: Complex types.
* Complex Type Example:: Complex type example.
@end menu
@node Primitive Types
......@@ -345,6 +347,20 @@ On other platforms, it is not.
@tindex ffi_type_pointer
A generic @code{void *} pointer. You should use this for all
pointers, regardless of their real type.
@item ffi_type_complex_float
@tindex ffi_type_complex_float
The C @code{_Complex float} type.
@item ffi_type_complex_double
@tindex ffi_type_complex_double
The C @code{_Complex double} type.
@item ffi_type_complex_longdouble
@tindex ffi_type_complex_longdouble
The C @code{_Complex long double} type.
On platforms that have a C @code{long double} type, this is defined.
On other platforms, it is not.
@end table
Each of these is of type @code{ffi_type}, so you must take the address
......@@ -429,6 +445,135 @@ Here is the corresponding code to describe this struct to
@}
@end example
@node Complex
@subsection Complex Types
@samp{libffi} supports the complex types defined by the C99
standard (@code{_Complex float}, @code{_Complex double} and
@code{_Complex long double} with the built-in type descriptors
@code{ffi_type_complex_float}, @code{ffi_type_complex_double} and
@code{ffi_type_complex_longdouble}.
Custom complex types like @code{_Complex int} can also be used.
An @code{ffi_type} object has to be defined to describe the
complex type to @samp{libffi}.
@tindex ffi_type
@deftp {Data type} ffi_type
@table @code
@item size_t size
This must be manually set to the size of the complex type.
@item unsigned short alignment
This must be manually set to the alignment of the complex type.
@item unsigned short type
For a complex type, this must be set to @code{FFI_TYPE_COMPLEX}.
@item ffi_type **elements
This is a @samp{NULL}-terminated array of pointers to
@code{ffi_type} objects. The first element is set to the
@code{ffi_type} of the complex's base type. The second element
must be set to @code{NULL}.
@end table
@end deftp
The section @ref{Complex Type Example} shows a way to determine
the @code{size} and @code{alignment} members in a platform
independent way.
For platforms that have no complex support in @code{libffi} yet,
the functions @code{ffi_prep_cif} and @code{ffi_prep_args} abort
the program if they encounter a complex type.
@node Complex Type Example
@subsection Complex Type Example
This example demonstrates how to use complex types:
@example
#include <stdio.h>
#include <ffi.h>
#include <complex.h>
void complex_fn(_Complex float cf,
_Complex double cd,
_Complex long double cld)
@{
printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n",
(float)creal (cf), (float)cimag (cf),
(float)creal (cd), (float)cimag (cd),
(float)creal (cld), (float)cimag (cld));
@}
int main()
@{
ffi_cif cif;
ffi_type *args[3];
void *values[3];
_Complex float cf;
_Complex double cd;
_Complex long double cld;
/* Initialize the argument info vectors */
args[0] = &ffi_type_complex_float;
args[1] = &ffi_type_complex_double;
args[2] = &ffi_type_complex_longdouble;
values[0] = &cf;
values[1] = &cd;
values[2] = &cld;
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
&ffi_type_void, args) == FFI_OK)
@{
cf = 1.0 + 20.0 * I;
cd = 300.0 + 4000.0 * I;
cld = 50000.0 + 600000.0 * I;
/* Call the function */
ffi_call(&cif, (void (*)(void))complex_fn, 0, values);
@}
return 0;
@}
@end example
This is an example for defining a custom complex type descriptor
for compilers that support them:
@example
/*
* This macro can be used to define new complex type descriptors
* in a platform independent way.
*
* name: Name of the new descriptor is ffi_type_complex_<name>.
* type: The C base type of the complex type.
*/
#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \
static ffi_type *ffi_elements_complex_##name [2] = @{ \
(ffi_type *)(&ffitype), NULL \
@}; \
struct struct_align_complex_##name @{ \
char c; \
_Complex type x; \
@}; \
ffi_type ffi_type_complex_##name = @{ \
sizeof(_Complex type), \
offsetof(struct struct_align_complex_##name, x), \
FFI_TYPE_COMPLEX, \
(ffi_type **)ffi_elements_complex_##name \
@}
/* Define new complex type descriptors using the macro: */
/* ffi_type_complex_sint */
FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
/* ffi_type_complex_uchar */
FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
@end example
The new type descriptors can then be used like one of the built-in
type descriptors in the previous example.
@node Multiple ABIs
@section Multiple ABIs
......@@ -534,7 +679,7 @@ writable and executable addresses.
@section Closure Example
A trivial example that creates a new @code{puts} by binding
@code{fputs} with @code{stdin}.
@code{fputs} with @code{stdout}.
@example
#include <stdio.h>
......
@set UPDATED 6 March 2012
@set UPDATED-MONTH March 2012
@set EDITION 3.0.11
@set VERSION 3.0.11
@set UPDATED 6 March 2012
@set UPDATED-MONTH March 2012
@set EDITION 3.0.11
@set VERSION 3.0.11
@set UPDATED 8 November 2014
@set UPDATED-MONTH November 2014
@set EDITION 3.2.1
@set VERSION 3.2.1
......@@ -26,10 +26,10 @@
/* Cannot use malloc on this target, so, we revert to alternative means */
#undef FFI_MMAP_EXEC_WRIT
/* Define this is you do not want support for the raw API. */
/* Define this if 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. */
/* Define this if you do not want support for aggregate types. */
#undef FFI_NO_STRUCTS
/* Define to 1 if you have `alloca', as a function or macro. */
......@@ -48,6 +48,9 @@
/* Define if your assembler supports .register. */
#undef HAVE_AS_REGISTER_PSEUDO_OP
/* Define if the compiler uses zarch features. */
#undef HAVE_AS_S390_ZARCH
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
#undef HAVE_AS_SPARC_UA_PCREL
......@@ -82,6 +85,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkostemp' function. */
#undef HAVE_MKOSTEMP
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
......@@ -155,6 +161,9 @@
/* The size of `long double', as computed by sizeof. */
#undef SIZEOF_LONG_DOUBLE
/* The size of `size_t', as computed by sizeof. */
#undef SIZEOF_SIZE_T
/* 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 runtime.
......
#!/usr/bin/env python
import subprocess
import os
import errno
import collections
import glob
import argparse
class Platform(object):
pass
class simulator_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphonesimulator'
arch = 'i386'
triple = 'i386-apple-darwin11'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __i386__\n\n"
suffix = "\n\n#endif"
src_dir = 'x86'
src_files = ['darwin.S', 'win32.S', 'ffi.c']
class simulator64_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphonesimulator'
arch = 'x86_64'
triple = 'x86_64-apple-darwin13'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __x86_64__\n\n"
suffix = "\n\n#endif"
src_dir = 'x86'
src_files = ['darwin64.S', 'ffi64.c']
class device_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphoneos'
arch = 'armv7'
triple = 'arm-apple-darwin11'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __arm__\n\n"
suffix = "\n\n#endif"
src_dir = 'arm'
src_files = ['sysv.S', 'trampoline.S', 'ffi.c']
class device64_platform(Platform):
directory = 'darwin_ios'
sdk = 'iphoneos'
arch = 'arm64'
triple = 'aarch64-apple-darwin13'
version_min = '-miphoneos-version-min=7.0'
prefix = "#ifdef __arm64__\n\n"
suffix = "\n\n#endif"
src_dir = 'aarch64'
src_files = ['sysv.S', 'ffi.c']
class desktop32_platform(Platform):
directory = 'darwin_osx'
sdk = 'macosx'
arch = 'i386'
triple = 'i386-apple-darwin10'
version_min = '-mmacosx-version-min=10.6'
src_dir = 'x86'
src_files = ['darwin.S', 'win32.S', 'ffi.c']
prefix = "#ifdef __i386__\n\n"
suffix = "\n\n#endif"
class desktop64_platform(Platform):
directory = 'darwin_osx'
sdk = 'macosx'
arch = 'x86_64'
triple = 'x86_64-apple-darwin10'
version_min = '-mmacosx-version-min=10.6'
prefix = "#ifdef __x86_64__\n\n"
suffix = "\n\n#endif"
src_dir = 'x86'
src_files = ['darwin64.S', 'ffi64.c']
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST:
pass
else:
raise
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
mkdir_p(dst_dir)
out_filename = filename
if file_suffix:
split_name = os.path.splitext(filename)
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
with open(os.path.join(src_dir, filename)) as in_file:
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
if prefix:
out_file.write(prefix)
out_file.write(in_file.read())
if suffix:
out_file.write(suffix)
def list_files(src_dir, pattern=None, filelist=None):
if pattern: filelist = glob.iglob(os.path.join(src_dir, pattern))
for file in filelist:
yield os.path.basename(file)
def copy_files(src_dir, dst_dir, pattern=None, filelist=None, file_suffix=None, prefix=None, suffix=None):
for filename in list_files(src_dir, pattern=pattern, filelist=filelist):
move_file(src_dir, dst_dir, filename, file_suffix=file_suffix, prefix=prefix, suffix=suffix)
def copy_src_platform_files(platform):
src_dir = os.path.join('src', platform.src_dir)
dst_dir = os.path.join(platform.directory, 'src', platform.src_dir)
copy_files(src_dir, dst_dir, filelist=platform.src_files, file_suffix=platform.arch, prefix=platform.prefix, suffix=platform.suffix)
def build_target(platform, platform_headers):
def xcrun_cmd(cmd):
return 'xcrun -sdk %s %s -arch %s' % (platform.sdk, cmd, platform.arch)
tag='%s-%s' % (platform.sdk, platform.arch)
build_dir = 'build_%s' % tag
mkdir_p(build_dir)
env = dict(CC=xcrun_cmd('clang'),
LD=xcrun_cmd('ld'),
CFLAGS='%s' % (platform.version_min))
working_dir = os.getcwd()
try:
os.chdir(build_dir)
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
finally:
os.chdir(working_dir)
for src_dir in [build_dir, os.path.join(build_dir, 'include')]:
copy_files(src_dir,
os.path.join(platform.directory, 'include'),
pattern='*.h',
file_suffix=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
for filename in list_files(src_dir, pattern='*.h'):
platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix))
def make_tramp():
with open('src/arm/trampoline.S', 'w') as tramp_out:
p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)
p.wait()
def generate_source_and_headers(generate_osx=True, generate_ios=True):
copy_files('src', 'darwin_common/src', pattern='*.c')
copy_files('include', 'darwin_common/include', pattern='*.h')
if generate_ios:
make_tramp()
copy_src_platform_files(simulator_platform)
copy_src_platform_files(simulator64_platform)
copy_src_platform_files(device_platform)
copy_src_platform_files(device64_platform)
if generate_osx:
copy_src_platform_files(desktop32_platform)
copy_src_platform_files(desktop64_platform)
platform_headers = collections.defaultdict(set)
if generate_ios:
build_target(simulator_platform, platform_headers)
build_target(simulator64_platform, platform_headers)
build_target(device_platform, platform_headers)
build_target(device64_platform, platform_headers)
if generate_osx:
build_target(desktop32_platform, platform_headers)
build_target(desktop64_platform, platform_headers)
mkdir_p('darwin_common/include')
for header_name, tag_tuples in platform_headers.iteritems():
basename, suffix = os.path.splitext(header_name)
with open(os.path.join('darwin_common/include', header_name), 'w') as header:
for tag_tuple in tag_tuples:
header.write('%s#include <%s_%s%s>\n%s\n' % (tag_tuple[0], basename, tag_tuple[1], suffix, tag_tuple[2]))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--only-ios', action='store_true', default=False)
parser.add_argument('--only-osx', action='store_true', default=False)
args = parser.parse_args()
generate_source_and_headers(generate_osx=not args.only_ios, generate_ios=not args.only_osx)
#!/usr/bin/env python
import subprocess
import re
import os
import errno
import collections
import sys
class Platform(object):
pass
sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
def sdkinfo(sdkname):
ret = {}
for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
kv = line.strip().split(': ', 1)
if len(kv) == 2:
k,v = kv
ret[k] = v
return ret
sim_sdk_info = sdkinfo('iphonesimulator')
device_sdk_info = sdkinfo('iphoneos')
def latest_sdks():
latest_sim = None
latest_device = None
for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
match = sdk_re.match(line)
if match:
if 'Simulator' in line:
latest_sim = match.group(1)
elif 'iOS' in line:
latest_device = match.group(1)
return latest_sim, latest_device
sim_sdk, device_sdk = latest_sdks()
class simulator_platform(Platform):
sdk='iphonesimulator'
arch = 'i386'
name = 'simulator'
triple = 'i386-apple-darwin10'
sdkroot = sim_sdk_info['Path']
prefix = "#if !defined(__arm__) && defined(__i386__)\n\n"
suffix = "\n\n#endif"
class device_platform(Platform):
sdk='iphoneos'
name = 'ios'
arch = 'armv7'
triple = 'arm-apple-darwin10'
sdkroot = device_sdk_info['Path']
prefix = "#ifdef __arm__\n\n"
suffix = "\n\n#endif"
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
out_filename = filename
if file_suffix:
split_name = os.path.splitext(filename)
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
with open(os.path.join(src_dir, filename)) as in_file:
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
if prefix:
out_file.write(prefix)
out_file.write(in_file.read())
if suffix:
out_file.write(suffix)
headers_seen = collections.defaultdict(set)
def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
for root, dirs, files in os.walk(src_dir, followlinks=True):
relroot = os.path.relpath(root,src_dir)
def move_dir(arch, prefix='', suffix='', files=[]):
for file in files:
file_suffix = None
if file.endswith('.h'):
if dest_include_dir:
file_suffix = arch
if arch:
headers_seen[file].add(arch)
move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
elif dest_dir:
outroot = os.path.join(dest_dir, relroot)
move_file(root, outroot, file, prefix=prefix, suffix=suffix)
if relroot == '.':
move_dir(arch=arch,
files=files,
prefix=prefix,
suffix=suffix)
elif relroot == 'arm':
move_dir(arch='arm',
prefix="#ifdef __arm__\n\n",
suffix="\n\n#endif",
files=files)
elif relroot == 'x86':
move_dir(arch='i386',
prefix="#if !defined(__arm__) && defined(__i386__)\n\n",
suffix="\n\n#endif",
files=files)
def build_target(platform):
def xcrun_cmd(cmd):
return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
build_dir = 'build_' + platform.name
if not os.path.exists(build_dir):
os.makedirs(build_dir)
env = dict(CC=xcrun_cmd('clang'),
LD=xcrun_cmd('ld'),
CFLAGS='-arch %s -isysroot %s -miphoneos-version-min=4.0' % (platform.arch, platform.sdkroot))
working_dir=os.getcwd()
try:
os.chdir(build_dir)
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
move_source_tree('.', None, '../ios/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
move_source_tree('./include', None, '../ios/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
finally:
os.chdir(working_dir)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
def main():
move_source_tree('src', 'ios/src', 'ios/include')
move_source_tree('include', None, 'ios/include')
build_target(simulator_platform)
build_target(device_platform)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
with open(os.path.join('ios/include', header_name), 'w') as header:
for arch in archs:
header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
if __name__ == '__main__':
main()
#!/usr/bin/env python
import subprocess
import re
import os
import errno
import collections
import sys
class Platform(object):
pass
sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
def sdkinfo(sdkname):
ret = {}
for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
kv = line.strip().split(': ', 1)
if len(kv) == 2:
k,v = kv
ret[k] = v
return ret
desktop_sdk_info = sdkinfo('macosx')
def latest_sdks():
latest_desktop = None
for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
match = sdk_re.match(line)
if match:
if 'OS X' in line:
latest_desktop = match.group(1)
return latest_desktop
desktop_sdk = latest_sdks()
class desktop_platform_32(Platform):
sdk='macosx'
arch = 'i386'
name = 'mac32'
triple = 'i386-apple-darwin10'
sdkroot = desktop_sdk_info['Path']
prefix = "#if defined(__i386__) && !defined(__x86_64__)\n\n"
suffix = "\n\n#endif"
class desktop_platform_64(Platform):
sdk='macosx'
arch = 'x86_64'
name = 'mac'
triple = 'x86_64-apple-darwin10'
sdkroot = desktop_sdk_info['Path']
prefix = "#if !defined(__i386__) && defined(__x86_64__)\n\n"
suffix = "\n\n#endif"
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
out_filename = filename
if file_suffix:
split_name = os.path.splitext(filename)
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
with open(os.path.join(src_dir, filename)) as in_file:
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
if prefix:
out_file.write(prefix)
out_file.write(in_file.read())
if suffix:
out_file.write(suffix)
headers_seen = collections.defaultdict(set)
def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
for root, dirs, files in os.walk(src_dir, followlinks=True):
relroot = os.path.relpath(root,src_dir)
def move_dir(arch, prefix='', suffix='', files=[]):
for file in files:
file_suffix = None
if file.endswith('.h'):
if dest_include_dir:
file_suffix = arch
if arch:
headers_seen[file].add(arch)
move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
elif dest_dir:
outroot = os.path.join(dest_dir, relroot)
move_file(root, outroot, file, prefix=prefix, suffix=suffix)
if relroot == '.':
move_dir(arch=arch,
files=files,
prefix=prefix,
suffix=suffix)
elif relroot == 'x86':
move_dir(arch='i386',
prefix="#if defined(__i386__) && !defined(__x86_64__)\n\n",
suffix="\n\n#endif",
files=files)
move_dir(arch='x86_64',
prefix="#if !defined(__i386__) && defined(__x86_64__)\n\n",
suffix="\n\n#endif",
files=files)
def build_target(platform):
def xcrun_cmd(cmd):
return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
build_dir = 'build_' + platform.name
if not os.path.exists(build_dir):
os.makedirs(build_dir)
env = dict(CC=xcrun_cmd('clang'),
LD=xcrun_cmd('ld'),
CFLAGS='-arch %s -isysroot %s -mmacosx-version-min=10.6' % (platform.arch, platform.sdkroot))
working_dir=os.getcwd()
try:
os.chdir(build_dir)
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
move_source_tree('.', None, '../osx/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
move_source_tree('./include', None, '../osx/include',
arch=platform.arch,
prefix=platform.prefix,
suffix=platform.suffix)
finally:
os.chdir(working_dir)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
def main():
move_source_tree('src', 'osx/src', 'osx/include')
move_source_tree('include', None, 'osx/include')
build_target(desktop_platform_32)
build_target(desktop_platform_64)
for header_name, archs in headers_seen.iteritems():
basename, suffix = os.path.splitext(header_name)
with open(os.path.join('osx/include', header_name), 'w') as header:
for arch in archs:
header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
if __name__ == '__main__':
main()
......@@ -3,7 +3,8 @@
AUTOMAKE_OPTIONS=foreign
DISTCLEANFILES=ffitarget.h
EXTRA_DIST=ffi.h.in ffi_common.h
noinst_HEADERS=ffi_common.h ffi_cfi.h
EXTRA_DIST=ffi.h.in
# Where generated headers like ffitarget.h get installed.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
......
......@@ -37,7 +37,7 @@ host_triplet = @host@
target_triplet = @target@
subdir = include
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/ffi.h.in $(toollibffi_HEADERS)
$(srcdir)/ffi.h.in $(noinst_HEADERS) $(toollibffi_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/asmcfi.m4 \
......@@ -78,7 +78,7 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(toollibffidir)"
HEADERS = $(toollibffi_HEADERS)
HEADERS = $(noinst_HEADERS) $(toollibffi_HEADERS)
ETAGS = etags
CTAGS = ctags
ACLOCAL = @ACLOCAL@
......@@ -99,6 +99,10 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
......@@ -151,12 +155,14 @@ SHELL = @SHELL@
STRIP = @STRIP@
TARGET = @TARGET@
TARGETDIR = @TARGETDIR@
TARGET_OBJ = @TARGET_OBJ@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
......@@ -212,7 +218,8 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign
DISTCLEANFILES = ffitarget.h
EXTRA_DIST = ffi.h.in ffi_common.h
noinst_HEADERS = ffi_common.h ffi_cfi.h
EXTRA_DIST = ffi.h.in
# Where generated headers like ffitarget.h get installed.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
......
/* -----------------------------------------------------------------*-C-*-
libffi @VERSION@ - Copyright (c) 2011 Anthony Green
libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person
......@@ -68,7 +68,7 @@ extern "C" {
#ifndef LIBFFI_ASM
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
......@@ -166,25 +166,49 @@ typedef struct _ffi_type
#error "long size not supported"
#endif
/* Need minimal decorations for DLLs to works on Windows. */
/* GCC has autoimport and autoexport. Rely on Libtool to */
/* help MSVC export from a DLL, but always declare data */
/* to be imported for MSVC clients. This costs an extra */
/* indirection for MSVC clients using the static version */
/* of the library, but don't worry about that. Besides, */
/* as a workaround, they can define FFI_BUILDING if they */
/* *know* they are going to link with the static library. */
#if defined _MSC_VER && !defined FFI_BUILDING
#define FFI_EXTERN extern __declspec(dllimport)
#else
#define FFI_EXTERN extern
#endif
/* These are defined in types.c */
extern ffi_type ffi_type_void;
extern ffi_type ffi_type_uint8;
extern ffi_type ffi_type_sint8;
extern ffi_type ffi_type_uint16;
extern ffi_type ffi_type_sint16;
extern ffi_type ffi_type_uint32;
extern ffi_type ffi_type_sint32;
extern ffi_type ffi_type_uint64;
extern ffi_type ffi_type_sint64;
extern ffi_type ffi_type_float;
extern ffi_type ffi_type_double;
extern ffi_type ffi_type_pointer;
FFI_EXTERN ffi_type ffi_type_void;
FFI_EXTERN ffi_type ffi_type_uint8;
FFI_EXTERN ffi_type ffi_type_sint8;
FFI_EXTERN ffi_type ffi_type_uint16;
FFI_EXTERN ffi_type ffi_type_sint16;
FFI_EXTERN ffi_type ffi_type_uint32;
FFI_EXTERN ffi_type ffi_type_sint32;
FFI_EXTERN ffi_type ffi_type_uint64;
FFI_EXTERN ffi_type ffi_type_sint64;
FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if @HAVE_LONG_DOUBLE@
extern ffi_type ffi_type_longdouble;
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
FFI_EXTERN ffi_type ffi_type_complex_float;
FFI_EXTERN ffi_type ffi_type_complex_double;
#if @HAVE_LONG_DOUBLE@
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
#else
#define ffi_type_complex_longdouble ffi_type_complex_double
#endif
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
......@@ -207,10 +231,10 @@ typedef struct {
#endif
} ffi_cif;
#if HAVE_LONG_DOUBLE_VARIANT
#if @HAVE_LONG_DOUBLE_VARIANT@
/* Used to adjust size/alignment of ffi types. */
void ffi_prep_types (ffi_abi abi);
# endif
#endif
/* Used internally, but overridden by some architectures */
ffi_status ffi_prep_cif_core(ffi_cif *cif,
......@@ -288,7 +312,12 @@ size_t ffi_java_raw_size (ffi_cif *cif);
__declspec(align(8))
#endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
......@@ -321,8 +350,12 @@ ffi_prep_closure_loc (ffi_closure*,
# pragma pack 8
#endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
......@@ -342,7 +375,12 @@ typedef struct {
} ffi_raw_closure;
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
void *trampoline_table_entry;
#else
char tramp[FFI_TRAMPOLINE_SIZE];
#endif
ffi_cif *cif;
......@@ -390,6 +428,22 @@ ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
#endif /* FFI_CLOSURES */
#if FFI_GO_CLOSURES
typedef struct {
void *tramp;
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
} ffi_go_closure;
ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*));
void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure);
#endif /* FFI_GO_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
ffi_status ffi_prep_cif(ffi_cif *cif,
......@@ -437,9 +491,10 @@ void ffi_call(ffi_cif *cif,
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
#define FFI_TYPE_COMPLEX 15
/* This should always refer to the last type code (for sanity checks) */
#define FFI_TYPE_LAST FFI_TYPE_POINTER
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}
......
/* -----------------------------------------------------------------------
ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc.
Conditionally assemble cfi directives. Only necessary for building libffi.
----------------------------------------------------------------------- */
#ifndef FFI_CFI_H
#define FFI_CFI_H
#ifdef HAVE_AS_CFI_PSEUDO_OP
# define cfi_startproc .cfi_startproc
# define cfi_endproc .cfi_endproc
# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
# define cfi_offset(reg, off) .cfi_offset reg, off
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
# define cfi_register(r1, r2) .cfi_register r1, r2
# define cfi_return_column(reg) .cfi_return_column reg
# define cfi_restore(reg) .cfi_restore reg
# define cfi_same_value(reg) .cfi_same_value reg
# define cfi_undefined(reg) .cfi_undefined reg
# define cfi_remember_state .cfi_remember_state
# define cfi_restore_state .cfi_restore_state
# define cfi_window_save .cfi_window_save
# define cfi_personality(enc, exp) .cfi_personality enc, exp
# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
# define cfi_escape(...) .cfi_escape __VA_ARGS__
#else
# define cfi_startproc
# define cfi_endproc
# define cfi_def_cfa(reg, off)
# define cfi_def_cfa_register(reg)
# define cfi_def_cfa_offset(off)
# define cfi_adjust_cfa_offset(off)
# define cfi_offset(reg, off)
# define cfi_rel_offset(reg, off)
# define cfi_register(r1, r2)
# define cfi_return_column(reg)
# define cfi_restore(reg)
# define cfi_same_value(reg)
# define cfi_undefined(reg)
# define cfi_remember_state
# define cfi_restore_state
# define cfi_window_save
# define cfi_personality(enc, exp)
# define cfi_lsda(enc, exp)
# define cfi_escape(...)
#endif /* HAVE_AS_CFI_PSEUDO_OP */
#endif /* FFI_CFI_H */
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (C) 2011, 2012 Anthony Green
ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc
Copyright (c) 1996 Red Hat, Inc.
......@@ -19,10 +19,14 @@ extern "C" {
/* Do not move this. Some versions of AIX are very picky about where
this is positioned. */
#ifdef __GNUC__
/* mingw64 defines this already in malloc.h. */
#ifndef alloca
# define alloca __builtin_alloca
#endif
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
/* mingw64 defines this already in malloc.h. */
# ifndef alloca
# define alloca __builtin_alloca
# endif
# endif
# define MAYBE_UNUSED __attribute__((__unused__))
#else
# define MAYBE_UNUSED
......@@ -30,17 +34,17 @@ extern "C" {
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
# ifdef _MSC_VER
# define alloca _alloca
# else
char *alloca ();
# endif
# endif
# endif
# endif
# endif
#endif
/* Check for the existence of memcpy. */
......@@ -87,7 +91,7 @@ typedef struct
} extended_cif;
/* Terse sized type definitions. */
#if defined(_MSC_VER) || defined(__sgi)
#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
typedef unsigned char UINT8;
typedef signed char SINT8;
typedef unsigned short UINT16;
......
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
toolexeclibdir=@toolexeclibdir@
includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
Name: @PACKAGE_NAME@
Description: Library supporting Foreign Function Interfaces
Version: @PACKAGE_VERSION@
Libs: -L${toolexeclibdir} -lffi
Cflags: -I${includedir}
......@@ -97,6 +97,10 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
......@@ -149,12 +153,14 @@ SHELL = @SHELL@
STRIP = @STRIP@
TARGET = @TARGET@
TARGETDIR = @TARGETDIR@
TARGET_OBJ = @TARGET_OBJ@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
......
......@@ -61,10 +61,8 @@ does not refer to a valid ABI,
.Nm FFI_BAD_ABI
will be returned. Available ABIs are
defined in
.Nm <ffitarget.h>
.
.Nm <ffitarget.h> .
.Sh SEE ALSO
.Xr ffi 3 ,
.Xr ffi_call 3 ,
.Xr ffi_prep_cif_var 3
......@@ -42,8 +42,10 @@
# format and translated into something sensible for cl or ml.
#
args_orig=$@
args="-nologo -W3"
md=-MD
static_crt=
debug_crt=
cl="cl"
ml="ml"
safeseh="-safeseh"
......@@ -62,31 +64,65 @@ do
shift 1
;;
-m64)
cl="cl" # "$MSVC/x86_amd64/cl"
ml="ml64" # "$MSVC/x86_amd64/ml64"
safeseh=
shift 1
;;
-clang-cl)
cl="clang-cl"
safeseh=
shift 1
;;
-O0)
args="$args -Od"
shift 1
;;
-O*)
# If we're optimizing, make sure we explicitly turn on some optimizations
# that are implicitly disabled by debug symbols (-Zi).
args="$args $1 -OPT:REF -OPT:ICF -INCREMENTAL:NO"
# Runtime error checks (enabled by setting -RTC1 in the -DFFI_DEBUG
# case below) are not compatible with optimization flags and will
# cause the build to fail. Therefore, drop the optimization flag if
# -DFFI_DEBUG is also set.
case $args_orig in
*-DFFI_DEBUG*)
args="$args"
;;
*)
# The ax_cc_maxopt.m4 macro from the upstream autoconf-archive
# project doesn't support MSVC and therefore ends up trying to
# use -O3. Use the equivalent "max optimization" flag for MSVC
# instead of erroring out.
case $1 in
-O3)
args="$args -O2"
;;
*)
args="$args $1"
;;
esac
opt="true"
;;
esac
shift 1
;;
-g)
# Enable debug symbol generation.
args="$args -Zi -DEBUG"
args="$args -Zi"
shift 1
;;
-DFFI_DEBUG)
# Link against debug CRT and enable runtime error checks.
# Enable runtime error checks.
args="$args -RTC1"
defines="$defines $1"
md=-MDd
shift 1
;;
-DUSE_STATIC_RTL)
# Link against static CRT.
static_crt=1
shift 1
;;
-DUSE_DEBUG_RTL)
# Link against debug CRT.
debug_crt=1
shift 1
;;
-c)
......@@ -126,6 +162,10 @@ do
# to do here.
shift 1
;;
-pedantic)
# libffi tests -pedantic with -Wall, so drop it also.
shift 1
;;
-Werror)
args="$args -WX"
shift 1
......@@ -170,6 +210,23 @@ do
esac
done
# If -Zi is specified, certain optimizations are implicitly disabled
# by MSVC. Add back those optimizations if this is an optimized build.
# NOTE: These arguments must come after all others.
if [ -n "$opt" ]; then
args="$args -link -OPT:REF -OPT:ICF -INCREMENTAL:NO"
fi
if [ -n "$static_crt" ]; then
md=-MT
else
md=-MD
fi
if [ -n "$debug_crt" ]; then
md="${md}d"
fi
if [ -n "$assembly" ]; then
if [ -z "$outdir" ]; then
outdir="."
......@@ -189,7 +246,10 @@ if [ -n "$assembly" ]; then
else
args="$md $args"
echo "$cl $args"
eval "\"$cl\" $args"
# Return an error code of 1 if an invalid command line parameter is passed
# instead of just ignoring it.
eval "(\"$cl\" $args 2>&1 1>&3 | \
awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1"
result=$?
fi
......
......@@ -42,18 +42,20 @@ typedef enum ffi_abi
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 36
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0
/* ---- Internal ---- */
#if defined (__APPLE__)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
#else
/* iOS reserves x18 for the system. Disable Go closures until
a new static chain is chosen. */
#define FFI_GO_CLOSURES 1
#endif
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
#define AARCH64_FFI_WITH_V_BIT 0
#define AARCH64_N_XREG 32
#define AARCH64_N_VREG 32
#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
/*
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 AUTHORS OR COPYRIGHT HOLDERS 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 AARCH64_RET_VOID 0
#define AARCH64_RET_INT64 1
#define AARCH64_RET_INT128 2
#define AARCH64_RET_UNUSED3 3
#define AARCH64_RET_UNUSED4 4
#define AARCH64_RET_UNUSED5 5
#define AARCH64_RET_UNUSED6 6
#define AARCH64_RET_UNUSED7 7
/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4,
so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */
#define AARCH64_RET_S4 8
#define AARCH64_RET_S3 9
#define AARCH64_RET_S2 10
#define AARCH64_RET_S1 11
#define AARCH64_RET_D4 12
#define AARCH64_RET_D3 13
#define AARCH64_RET_D2 14
#define AARCH64_RET_D1 15
#define AARCH64_RET_Q4 16
#define AARCH64_RET_Q3 17
#define AARCH64_RET_Q2 18
#define AARCH64_RET_Q1 19
/* Note that each of the sub-64-bit integers gets two entries. */
#define AARCH64_RET_UINT8 20
#define AARCH64_RET_UINT16 22
#define AARCH64_RET_UINT32 24
#define AARCH64_RET_SINT8 26
#define AARCH64_RET_SINT16 28
#define AARCH64_RET_SINT32 30
#define AARCH64_RET_MASK 31
#define AARCH64_RET_IN_MEM (1 << 5)
#define AARCH64_RET_NEED_COPY (1 << 6)
#define AARCH64_FLAG_ARG_V_BIT 7
#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT)
#define N_X_ARG_REG 8
#define N_V_ARG_REG 8
#define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8)
......@@ -44,9 +44,13 @@ typedef enum ffi_abi {
} ffi_abi;
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0
......
#define ALPHA_ST_VOID 0
#define ALPHA_ST_INT 1
#define ALPHA_ST_FLOAT 2
#define ALPHA_ST_DOUBLE 3
#define ALPHA_ST_CPLXF 4
#define ALPHA_ST_CPLXD 5
#define ALPHA_LD_VOID 0
#define ALPHA_LD_INT64 1
#define ALPHA_LD_INT32 2
#define ALPHA_LD_UINT16 3
#define ALPHA_LD_SINT16 4
#define ALPHA_LD_UINT8 5
#define ALPHA_LD_SINT8 6
#define ALPHA_LD_FLOAT 7
#define ALPHA_LD_DOUBLE 8
#define ALPHA_LD_CPLXF 9
#define ALPHA_LD_CPLXD 10
#define ALPHA_ST_SHIFT 0
#define ALPHA_LD_SHIFT 8
#define ALPHA_RET_IN_MEM 0x10000
#define ALPHA_FLAGS(S, L) (((L) << ALPHA_LD_SHIFT) | (S))
/* -----------------------------------------------------------------------
arcompact.S - Copyright (c) 2013 Synposys, Inc. (www.synopsys.com)
ARCompact 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
#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 */
/* R4: ecif.rvalue */
/* R5: fn */
ENTRY(ffi_call_ARCompact)
/* Save registers. */
st.a fp, [sp, -4] /* fp + 20, fp */
push_s blink /* fp + 16, blink */
st.a r4, [sp, -4] /* fp + 12, ecif.rvalue */
push_s r3 /* fp + 8, fig->flags */
st.a r5, [sp, -4] /* fp + 4, fn */
push_s r2 /* fp + 0, cif->bytes */
mov fp, sp
/* Make room for all of the new args. */
sub sp, sp, r2
/* Place all of the ffi_prep_args in position. */
/* ffi_prep_args(char *stack, extended_cif *ecif) */
/* R1 already set. */
/* And call. */
jl_s.d [r0]
mov_s r0, sp
ld.ab r12, [fp, 4] /* cif->bytes */
ld.ab r11, [fp, 4] /* fn */
/* Move first 8 parameters in registers... */
ld_s r0, [sp]
ld_s r1, [sp, 4]
ld_s r2, [sp, 8]
ld_s r3, [sp, 12]
ld r4, [sp, 16]
ld r5, [sp, 20]
ld r6, [sp, 24]
ld r7, [sp, 28]
/* ...and adjust the stack. */
min r12, r12, 32
/* Call the function. */
jl.d [r11]
add sp, sp, r12
mov sp, fp
pop_s r3 /* fig->flags, return type */
pop_s r2 /* ecif.rvalue, pointer for return value */
/* If the return value pointer is NULL, assume no return value. */
breq.d r2, 0, epilogue
pop_s blink
/* Return INT. */
brne r3, FFI_TYPE_INT, return_double
b.d epilogue
st_s r0, [r2]
return_double:
brne r3, FFI_TYPE_DOUBLE, epilogue
st_s r0, [r2]
st_s r1, [r2,4]
epilogue:
j_s.d [blink]
ld.ab fp, [sp, 4]
ENTRY(ffi_closure_ARCompact)
st.a r0, [sp, -32]
st_s r1, [sp, 4]
st_s r2, [sp, 8]
st_s r3, [sp, 12]
st r4, [sp, 16]
st r5, [sp, 20]
st r6, [sp, 24]
st r7, [sp, 28]
/* pointer to arguments */
mov_s r2, sp
/* return value goes here */
sub sp, sp, 8
mov_s r1, sp
push_s blink
bl.d ffi_closure_inner_ARCompact
mov_s r0, r8 /* codeloc, set by trampoline */
pop_s blink
/* set return value to r1:r0 */
pop_s r0
pop_s r1
j_s.d [blink]
add_s sp, sp, 32
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
ARC 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>
#include <stdint.h>
#include <sys/cachectl.h>
/* for little endian ARC, the code is in fact stored as mixed endian for
performance reasons */
#if __BIG_ENDIAN__
#define CODE_ENDIAN(x) (x)
#else
#define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
#endif
/* 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;
void **p_argv;
char *argp;
ffi_type **p_arg;
tmp = 0;
argp = stack;
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
{
*(void **) argp = ecif->rvalue;
argp += 4;
}
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0); i--, p_arg++)
{
size_t z;
int alignment;
/* align alignment to 4 */
alignment = (((*p_arg)->alignment - 1) | 3) + 1;
/* Align if necessary. */
if ((alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, alignment);
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:
memcpy (argp, *p_argv, (*p_arg)->size);
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)
{
memcpy (argp, *p_argv, z);
}
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:
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_ARCompact (void (*)(char *, extended_cif *),
extended_cif *, unsigned, unsigned,
unsigned *, void (*fn) (void));
void
ffi_call (ffi_cif * cif, void (*fn) (void), 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_ARCOMPACT:
ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
default:
FFI_ASSERT (0);
break;
}
}
int
ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
ffi_arg * args)
{
void **arg_area, **p_argv;
ffi_cif *cif = closure->cif;
char *argp = (char *) args;
ffi_type **p_argt;
int i;
arg_area = (void **) alloca (cif->nargs * sizeof (void *));
/* handle hidden argument */
if (cif->flags == FFI_TYPE_STRUCT)
{
rvalue = *(void **) argp;
argp += 4;
}
p_argv = arg_area;
for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
i++, p_argt++, p_argv++)
{
size_t z;
int alignment;
/* align alignment to 4 */
alignment = (((*p_argt)->alignment - 1) | 3) + 1;
/* Align if necessary. */
if ((alignment - 1) & (unsigned) argp)
argp = (char *) ALIGN (argp, alignment);
z = (*p_argt)->size;
*p_argv = (void *) argp;
argp += z;
}
(closure->fun) (cif, rvalue, arg_area, closure->user_data);
return cif->flags;
}
extern void ffi_closure_ARCompact (void);
ffi_status
ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data, void *codeloc)
{
uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
switch (cif->abi)
{
case FFI_ARCOMPACT:
FFI_ASSERT (tramp == codeloc);
tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */
tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */
tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
break;
default:
return FFI_BAD_ABI;
}
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
return FFI_OK;
}
/* -----------------------------------------------------------------------
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
Target configuration macros for ARC.
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
#ifndef LIBFFI_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
/* ---- 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_ARCOMPACT,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_ARCOMPACT
} ffi_abi;
#endif
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_NATIVE_RAW_API 0
#endif
......@@ -53,19 +53,17 @@ typedef enum ffi_abi {
#define FFI_EXTRA_CIF_FIELDS \
int vfp_used; \
short vfp_reg_free, vfp_nargs; \
unsigned short vfp_reg_free, vfp_nargs; \
signed char vfp_args[16] \
/* Internally used. */
#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 20
#define FFI_GO_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 12
#define FFI_NATIVE_RAW_API 0
#endif
#!/bin/sh
# -----------------------------------------------------------------------
# gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
#
# ARM Trampoline Page Generator
#
# 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 AUTHORS OR COPYRIGHT
# HOLDERS 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.
# -----------------------------------------------------------------------
PROGNAME=$0
# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
# the entire arm trampoline implementation must be updated to match, too.
# Size of an individual trampoline, in bytes
TRAMPOLINE_SIZE=12
# Page size, in bytes
PAGE_SIZE=4096
# Compute the size of the reachable config page; The first 16 bytes of the config page
# are unreachable due to our maximum pc-relative ldr offset.
PAGE_AVAIL=`expr $PAGE_SIZE - 16`
# Compute the number of of available trampolines.
TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
header () {
echo "# GENERATED CODE - DO NOT EDIT"
echo "# This file was generated by $PROGNAME"
echo ""
# Write out the license header
cat << EOF
# Copyright (c) 2010, Plausible Labs Cooperative, 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 THE AUTHORS OR COPYRIGHT
# HOLDERS 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.
# -----------------------------------------------------------------------
EOF
# Write out the trampoline table, aligned to the page boundary
echo ".text"
echo ".align 12"
echo ".globl _ffi_closure_trampoline_table_page"
echo "_ffi_closure_trampoline_table_page:"
}
# WARNING - Don't modify the trampoline code size without also updating the relevent libffi code
trampoline () {
cat << END
// trampoline
// Save to stack
stmfd sp!, {r0-r3}
// Load the context argument from the config page.
// This places the first usable config value at _ffi_closure_trampoline_table-4080
// This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
ldr r0, [pc, #-4092]
// Load the jump address from the config page.
ldr pc, [pc, #-4092]
END
}
main () {
# Write out the header
header
# Write out the trampolines
local i=0
while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
trampoline
local i=`expr $i + 1`
done
}
main
#define ARM_TYPE_VFP_S 0
#define ARM_TYPE_VFP_D 1
#define ARM_TYPE_VFP_N 2
#define ARM_TYPE_INT64 3
#define ARM_TYPE_INT 4
#define ARM_TYPE_VOID 5
#define ARM_TYPE_STRUCT 6
This source diff could not be displayed because it is too large. You can view the blob instead.
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
Paulo Pizarro <paulo.pizarro@gmail.com>
Blackfin Foreign Function Interface
......
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
Paulo Pizarro <paulo.pizarro@gmail.com>
Blackfin Foreign Function Interface
......@@ -32,7 +33,7 @@
.align 4
/*
There is a "feature" in the bfin toolchain that it puts a _ before funcion names
There is a "feature" in the bfin toolchain that it puts a _ before function names
that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV
*/
.global _ffi_call_SYSV;
......@@ -40,25 +41,26 @@
.func ffi_call_SYSV
/*
cif->bytes = R0 (fp+8)
&ecif = R1 (fp+12)
ffi_prep_args = R2 (fp+16)
ret_type = stack (fp+20)
ecif.rvalue = stack (fp+24)
fn = stack (fp+28)
got (fp+32)
There is room for improvement here (we can use temporary registers
cif->bytes = R0 (fp+8)
&ecif = R1 (fp+12)
ffi_prep_args = R2 (fp+16)
ret_type = stack (fp+20)
ecif.rvalue = stack (fp+24)
fn = stack (fp+28)
got (fp+32)
There is room for improvement here (we can use temporary registers
instead of saving the values in the memory)
REGS:
P5 => Stack pointer (function arguments)
R5 => cif->bytes
R4 => ret->type
FP-20 = P3
FP-16 = SP (parameters area)
FP-12 = SP (temp)
FP-08 = function return part 1 [R0]
FP-04 = function return part 2 [R1]
REGS:
P5 => Stack pointer (function arguments)
R5 => cif->bytes
R4 => ret->type
FP-20 = P3
FP-16 = SP (parameters area)
FP-12 = SP (temp)
FP-08 = function return part 1 [R0]
FP-04 = function return part 2 [R1]
*/
_ffi_call_SYSV:
......
......@@ -34,7 +34,7 @@
#include <ffi_common.h>
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
# if __gnu_linux__
# if __gnu_linux__ && !defined(__ANDROID__)
/* This macro indicates it may be forbidden to map anonymous memory
with both write and execute permission. Code compiled when this
option is defined will attempt to map such pages once, but if it
......@@ -181,10 +181,26 @@ static int emutramp_enabled = -1;
static int
emutramp_enabled_check (void)
{
if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL)
return 1;
else
char *buf = NULL;
size_t len = 0;
FILE *f;
int ret;
f = fopen ("/proc/self/status", "r");
if (f == NULL)
return 0;
ret = 0;
while (getline (&buf, &len, f) != -1)
if (!strncmp (buf, "PaX:", 4))
{
char emutramp;
if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
ret = (emutramp == 'E');
break;
}
free (buf);
fclose (f);
return ret;
}
#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
......@@ -249,9 +265,15 @@ static size_t execsize = 0;
/* Open a temporary file name, and immediately unlink it. */
static int
open_temp_exec_file_name (char *name)
open_temp_exec_file_name (char *name, int flags)
{
int fd = mkstemp (name);
int fd;
#ifdef HAVE_MKOSTEMP
fd = mkostemp (name, flags);
#else
fd = mkstemp (name);
#endif
if (fd != -1)
unlink (name);
......@@ -264,8 +286,30 @@ static int
open_temp_exec_file_dir (const char *dir)
{
static const char suffix[] = "/ffiXXXXXX";
int lendir = strlen (dir);
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
int lendir, flags;
char *tempname;
#ifdef O_TMPFILE
int fd;
#endif
#ifdef O_CLOEXEC
flags = O_CLOEXEC;
#else
flags = 0;
#endif
#ifdef O_TMPFILE
fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
/* If the running system does not support the O_TMPFILE flag then retry without it. */
if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
return fd;
} else {
errno = 0;
}
#endif
lendir = strlen (dir);
tempname = __builtin_alloca (lendir + sizeof (suffix));
if (!tempname)
return -1;
......@@ -273,7 +317,7 @@ open_temp_exec_file_dir (const char *dir)
memcpy (tempname, dir, lendir);
memcpy (tempname + lendir, suffix, sizeof (suffix));
return open_temp_exec_file_name (tempname);
return open_temp_exec_file_name (tempname, flags);
}
/* Open a temporary file in the directory in the named environment
......@@ -382,7 +426,7 @@ open_temp_exec_file_opts_next (void)
}
/* Return a file descriptor of a temporary zero-sized file in a
writable and exexutable filesystem. */
writable and executable filesystem. */
static int
open_temp_exec_file (void)
{
......
......@@ -54,6 +54,11 @@ void ffi_type_test(ffi_type *a, char *file, int 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);
FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
|| a->elements != NULL, file, line);
FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
|| (a->elements != NULL
&& a->elements[0] != NULL && a->elements[1] == NULL),
file, line);
}
......@@ -1255,7 +1255,7 @@ extern void* sbrk(ptrdiff_t);
#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
/* Some constants coerced to size_t */
/* Annoying but necessary to avoid errors on some plaftorms */
/* Annoying but necessary to avoid errors on some platforms */
#define SIZE_T_ZERO ((size_t)0)
#define SIZE_T_ONE ((size_t)1)
#define SIZE_T_TWO ((size_t)2)
......@@ -1409,7 +1409,7 @@ static int win32munmap(void* ptr, size_t size) {
#define CALL_MORECORE(S) MFAIL
#endif /* HAVE_MORECORE */
/* mstate bit set if continguous morecore disabled or failed */
/* mstate bit set if contiguous morecore disabled or failed */
#define USE_NONCONTIGUOUS_BIT (4U)
/* segment bit set in create_mspace_with_base */
......@@ -1661,7 +1661,7 @@ struct malloc_chunk {
typedef struct malloc_chunk mchunk;
typedef struct malloc_chunk* mchunkptr;
typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
typedef unsigned int bindex_t; /* Described below */
typedef size_t bindex_t; /* Described below */
typedef unsigned int binmap_t; /* Described below */
typedef unsigned int flag_t; /* The type of various bit flag sets */
......@@ -2291,7 +2291,7 @@ static size_t traverse_and_check(mstate m);
#define treebin_at(M,i) (&((M)->treebins[i]))
/* assign tree index for size S to variable I */
#if defined(__GNUC__) && defined(i386)
#if defined(__GNUC__) && defined(__i386__)
#define compute_tree_index(S, I)\
{\
size_t X = S >> TREEBIN_SHIFT;\
......@@ -2356,7 +2356,7 @@ static size_t traverse_and_check(mstate m);
/* index corresponding to given bit */
#if defined(__GNUC__) && defined(i386)
#if defined(__GNUC__) && defined(__i386__)
#define compute_bit2idx(X, I)\
{\
unsigned int J;\
......@@ -3090,8 +3090,8 @@ static void internal_malloc_stats(mstate m) {
and choose its bk node as its replacement.
2. If x was the last node of its size, but not a leaf node, it must
be replaced with a leaf node (not merely one with an open left or
right), to make sure that lefts and rights of descendents
correspond properly to bit masks. We use the rightmost descendent
right), to make sure that lefts and rights of descendants
correspond properly to bit masks. We use the rightmost descendant
of x. We could use any other leaf, but this is easy to locate and
tends to counteract removal of leftmosts elsewhere, and so keeps
paths shorter than minimally guaranteed. This doesn't loop much
......@@ -3388,7 +3388,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
*ss = m->seg; /* Push current record */
m->seg.base = tbase;
m->seg.size = tsize;
set_segment_flags(&m->seg, mmapped);
(void)set_segment_flags(&m->seg, mmapped);
m->seg.next = ss;
/* Insert trailing fenceposts */
......@@ -3548,7 +3548,7 @@ static void* sys_alloc(mstate m, size_t nb) {
if (!is_initialized(m)) { /* first-time initialization */
m->seg.base = m->least_addr = tbase;
m->seg.size = tsize;
set_segment_flags(&m->seg, mmap_flag);
(void)set_segment_flags(&m->seg, mmap_flag);
m->magic = mparams.magic;
init_bins(m);
if (is_global(m))
......@@ -5091,10 +5091,10 @@ History:
Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
* Use last_remainder in more cases.
* Pack bins using idea from colin@nyx10.cs.du.edu
* Use ordered bins instead of best-fit threshhold
* Use ordered bins instead of best-fit threshold
* Eliminate block-local decls to simplify tracing and debugging.
* Support another case of realloc via move into top
* Fix error occuring when initial sbrk_base not word-aligned.
* Fix error occurring when initial sbrk_base not word-aligned.
* Rely on page size for units instead of SBRK_UNIT to
avoid surprises about sbrk alignment conventions.
* Add mallinfo, mallopt. Thanks to Raymond Nijssen
......
......@@ -401,7 +401,7 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
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. */
both retrieve the user data, and to restore the correct gp pointer. */
extern void ffi_closure_unix ();
......
......@@ -60,6 +60,9 @@ ffi_java_raw_size (ffi_cif *cif)
case FFI_TYPE_STRUCT:
/* No structure parameters in Java. */
abort();
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
result += FFI_SIZEOF_JAVA_RAW;
}
......@@ -104,6 +107,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
*args = (void*) &(raw++)->ptr;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
*args = raw;
raw +=
......@@ -126,6 +133,9 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
*args = (void*) raw;
raw += 2;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
*args = (void*) raw++;
}
......@@ -254,6 +264,10 @@ ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
*(SINT64 *)rvalue <<= 32;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
break;
}
......@@ -279,6 +293,10 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
*(SINT64 *)rvalue >>= 32;
break;
case FFI_TYPE_COMPLEX:
/* Not supported yet. */
abort();
default:
break;
}
......
......@@ -123,6 +123,8 @@ ffi_prep_args (void *stack, extended_cif *ecif)
#define CIF_FLAGS_POINTER 32
#define CIF_FLAGS_STRUCT1 64
#define CIF_FLAGS_STRUCT2 128
#define CIF_FLAGS_SINT8 256
#define CIF_FLAGS_SINT16 512
/* Perform machine dependent cif processing */
ffi_status
......@@ -200,6 +202,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
cif->flags = CIF_FLAGS_DINT;
break;
case FFI_TYPE_SINT16:
cif->flags = CIF_FLAGS_SINT16;
break;
case FFI_TYPE_SINT8:
cif->flags = CIF_FLAGS_SINT8;
break;
default:
cif->flags = CIF_FLAGS_INT;
break;
......
......@@ -2,9 +2,10 @@
sysv.S - Copyright (c) 2012 Alan Hourihane
Copyright (c) 1998, 2012 Andreas Schwab
Copyright (c) 2008 Red Hat, Inc.
m68k Foreign Function Interface
Copyright (c) 2008 Red Hat, Inc.
Copyright (c) 2012 Thorsten Glaser
m68k Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
......@@ -168,8 +169,28 @@ retstruct1:
retstruct2:
btst #7,%d2
jbeq noretval
jbeq retsint8
move.w %d0,(%a1)
jbra epilogue
retsint8:
btst #8,%d2
jbeq retsint16
| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
ext.w %d0
ext.l %d0
#else
extb.l %d0
#endif
move.l %d0,(%a1)
jbra epilogue
retsint16:
btst #9,%d2
jbeq noretval
ext.l %d0
move.l %d0,(%a1)
noretval:
epilogue:
......@@ -201,8 +222,10 @@ CALLFUNC(ffi_closure_SYSV):
lsr.l #1,%d0
jne 1f
jcc .Lcls_epilogue
| CIF_FLAGS_INT
move.l -12(%fp),%d0
.Lcls_epilogue:
| no CIF_FLAGS_*
unlk %fp
rts
1:
......@@ -210,6 +233,7 @@ CALLFUNC(ffi_closure_SYSV):
lsr.l #2,%d0
jne 1f
jcs .Lcls_ret_float
| CIF_FLAGS_DINT
move.l (%a0)+,%d0
move.l (%a0),%d1
jra .Lcls_epilogue
......@@ -224,6 +248,7 @@ CALLFUNC(ffi_closure_SYSV):
lsr.l #2,%d0
jne 1f
jcs .Lcls_ret_ldouble
| CIF_FLAGS_DOUBLE
#if defined(__MC68881__) || defined(__HAVE_68881__)
fmove.d (%a0),%fp0
#else
......@@ -242,17 +267,37 @@ CALLFUNC(ffi_closure_SYSV):
jra .Lcls_epilogue
1:
lsr.l #2,%d0
jne .Lcls_ret_struct2
jne 1f
jcs .Lcls_ret_struct1
| CIF_FLAGS_POINTER
move.l (%a0),%a0
move.l %a0,%d0
jra .Lcls_epilogue
.Lcls_ret_struct1:
move.b (%a0),%d0
jra .Lcls_epilogue
.Lcls_ret_struct2:
1:
lsr.l #2,%d0
jne 1f
jcs .Lcls_ret_sint8
| CIF_FLAGS_STRUCT2
move.w (%a0),%d0
jra .Lcls_epilogue
.Lcls_ret_sint8:
move.l (%a0),%d0
| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
ext.w %d0
ext.l %d0
#else
extb.l %d0
#endif
jra .Lcls_epilogue
1:
| CIF_FLAGS_SINT16
move.l (%a0),%d0
ext.l %d0
jra .Lcls_epilogue
CFI_ENDPROC()
.size CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
......
/*
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
*
* 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 AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/*
* m88k Foreign Function Interface
*/
#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_OBSD,
FFI_DEFAULT_ABI = FFI_OBSD,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_TRAMPOLINE_SIZE 0x14
#define FFI_NATIVE_RAW_API 0
#endif
/*
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
*
* 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 AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/*
* m88k Foreign Function Interface
*/
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
.text
/*
* ffi_cacheflush_OBSD(unsigned int addr, %r2
* unsigned int size); %r3
*/
.align 4
.globl ffi_cacheflush_OBSD
.type ffi_cacheflush_OBSD,@function
ffi_cacheflush_OBSD:
tb0 0, %r0, 451
or %r0, %r0, %r0
jmp %r1
.size ffi_cacheflush_OBSD, . - ffi_cacheflush_OBSD
/*
* ffi_call_OBSD(unsigned bytes, %r2
* extended_cif *ecif, %r3
* unsigned flags, %r4
* void *rvalue, %r5
* void (*fn)()); %r6
*/
.align 4
.globl ffi_call_OBSD
.type ffi_call_OBSD,@function
ffi_call_OBSD:
subu %r31, %r31, 32
st %r30, %r31, 4
st %r1, %r31, 0
addu %r30, %r31, 32
| Save the few arguments we'll need after ffi_prep_args()
st.d %r4, %r31, 8
st %r6, %r31, 16
| Allocate room for the image of r2-r9, and the stack space for
| the args (rounded to a 16-byte boundary)
addu %r2, %r2, (8 * 4) + 15
clr %r2, %r2, 4<0>
subu %r31, %r31, %r2
| Fill register and stack image
or %r2, %r31, %r0
#ifdef PIC
bsr ffi_prep_args#plt
#else
bsr ffi_prep_args
#endif
| Save pointer to return struct address, if any
or %r12, %r2, %r0
| Get function pointer
subu %r4, %r30, 32
ld %r1, %r4, 16
| Fetch the register arguments
ld.d %r2, %r31, (0 * 4)
ld.d %r4, %r31, (2 * 4)
ld.d %r6, %r31, (4 * 4)
ld.d %r8, %r31, (6 * 4)
addu %r31, %r31, (8 * 4)
| Invoke the function
jsr %r1
| Restore stack now that we don't need the args anymore
subu %r31, %r30, 32
| Figure out what to return as the function's return value
ld %r5, %r31, 12 | rvalue
ld %r4, %r31, 8 | flags
bcnd eq0, %r5, 9f
bb0 0, %r4, 1f | CIF_FLAGS_INT
st %r2, %r5, 0
br 9f
1:
bb0 1, %r4, 1f | CIF_FLAGS_DINT
st.d %r2, %r5, 0
br 9f
1:
9:
ld %r1, %r31, 0
ld %r30, %r31, 4
jmp.n %r1
addu %r31, %r31, 32
.size ffi_call_OBSD, . - ffi_call_OBSD
/*
* ffi_closure_OBSD(ffi_closure *closure); %r13
*/
.align 4
.globl ffi_closure_OBSD
.type ffi_closure_OBSD, @function
ffi_closure_OBSD:
subu %r31, %r31, 16
st %r30, %r31, 4
st %r1, %r31, 0
addu %r30, %r31, 16
| Make room on the stack for saved register arguments and return
| value
subu %r31, %r31, (8 * 4) + (2 * 4)
st.d %r2, %r31, (0 * 4)
st.d %r4, %r31, (2 * 4)
st.d %r6, %r31, (4 * 4)
st.d %r8, %r31, (6 * 4)
| Invoke the closure function
or %r5, %r30, 0 | calling stack
addu %r4, %r31, 0 | saved registers
addu %r3, %r31, (8 * 4) | return value
or %r2, %r13, %r0 | closure
#ifdef PIC
bsr ffi_closure_OBSD_inner#plt
#else
bsr ffi_closure_OBSD_inner
#endif
| Figure out what to return as the function's return value
bb0 0, %r2, 1f | CIF_FLAGS_INT
ld %r2, %r31, (8 * 4)
br 9f
1:
bb0 1, %r2, 1f | CIF_FLAGS_DINT
ld.d %r2, %r31, (8 * 4)
br 9f
1:
9:
subu %r31, %r30, 16
ld %r1, %r31, 0
ld %r30, %r31, 4
jmp.n %r1
addu %r31, %r31, 16
.size ffi_closure_OBSD,.-ffi_closure_OBSD
/*
* ffi_closure_struct_OBSD(ffi_closure *closure); %r13
*/
.align 4
.globl ffi_closure_struct_OBSD
.type ffi_closure_struct_OBSD, @function
ffi_closure_struct_OBSD:
subu %r31, %r31, 16
st %r30, %r31, 4
st %r1, %r31, 0
addu %r30, %r31, 16
| Make room on the stack for saved register arguments
subu %r31, %r31, (8 * 4)
st.d %r2, %r31, (0 * 4)
st.d %r4, %r31, (2 * 4)
st.d %r6, %r31, (4 * 4)
st.d %r8, %r31, (6 * 4)
| Invoke the closure function
or %r5, %r30, 0 | calling stack
addu %r4, %r31, 0 | saved registers
or %r3, %r12, 0 | return value
or %r2, %r13, %r0 | closure
#ifdef PIC
bsr ffi_closure_OBSD_inner#plt
#else
bsr ffi_closure_OBSD_inner
#endif
subu %r31, %r30, 16
ld %r1, %r31, 0
ld %r30, %r31, 4
jmp.n %r1
addu %r31, %r31, 16
.size ffi_closure_struct_OBSD,.-ffi_closure_struct_OBSD
/* ----------------------------------------------------------------------
ffi.c - Copyright (c) 2013 Imagination Technologies
Meta 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>
#include <stdlib.h>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
/*
* ffi_prep_args is called by the assembly routine once stack space has been
* allocated for the function's arguments
*/
unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
/* Store return value */
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
argp -= 4;
*(void **) argp = ecif->rvalue;
}
p_argv = ecif->avalue;
/* point to next location */
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++)
{
size_t z;
/* Move argp to address of argument */
z = (*p_arg)->size;
argp -= z;
/* Align if necessary */
argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
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);
case FFI_TYPE_STRUCT:
memcpy(argp, *p_argv, (*p_arg)->size);
break;
default:
FFI_ASSERT(0);
}
} else if ( z == sizeof(int)) {
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
} else {
memcpy(argp, *p_argv, z);
}
}
/* return the size of the arguments to be passed in registers,
padded to an 8 byte boundary to preserve stack alignment */
return ALIGN(MIN(stack - argp, 6*4), 8);
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
ffi_type **ptr;
unsigned i, bytes = 0;
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) {
if ((*ptr)->size == 0)
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes += ALIGN((*ptr)->size, 4);
}
/* Ensure arg space is aligned to an 8-byte boundary */
bytes = ALIGN(bytes, 8);
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT) {
bytes += sizeof(void*);
/* Ensure stack is aligned to an 8-byte boundary */
bytes = ALIGN(bytes, 8);
}
cif->bytes = bytes;
/* 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;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = (unsigned) FFI_TYPE_SINT64;
break;
case FFI_TYPE_STRUCT:
/* Meta can store return values which are <= 64 bits */
if (cif->rtype->size <= 4)
/* Returned to D0Re0 as 32-bit value */
cif->flags = (unsigned)FFI_TYPE_INT;
else if ((cif->rtype->size > 4) && (cif->rtype->size <= 8))
/* Returned valued is stored to D1Re0|R0Re0 */
cif->flags = (unsigned)FFI_TYPE_DOUBLE;
else
/* value stored in memory */
cif->flags = (unsigned)FFI_TYPE_STRUCT;
break;
default:
cif->flags = (unsigned)FFI_TYPE_INT;
break;
}
return FFI_OK;
}
extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned, double *);
/*
* Exported in API. Entry point
* cif -> ffi_cif object
* fn -> function pointer
* rvalue -> pointer to return value
* avalue -> vector of void * pointers pointing to memory locations holding the
* arguments
*/
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
int small_struct = (((cif->flags == FFI_TYPE_INT) || (cif->flags == FFI_TYPE_DOUBLE)) && (cif->rtype->type == FFI_TYPE_STRUCT));
ecif.cif = cif;
ecif.avalue = avalue;
double temp;
/*
* 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->flags == FFI_TYPE_STRUCT))
ecif.rvalue = alloca(cif->rtype->size);
else if (small_struct)
ecif.rvalue = &temp;
else
ecif.rvalue = rvalue;
switch (cif->abi) {
case FFI_SYSV:
ffi_call_SYSV(fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
break;
default:
FFI_ASSERT(0);
break;
}
if (small_struct)
memcpy (rvalue, &temp, cif->rtype->size);
}
/* private members */
static void ffi_prep_incoming_args_SYSV (char *, void **, void **,
ffi_cif*, float *);
void ffi_closure_SYSV (ffi_closure *);
/* Do NOT change that without changing the FFI_TRAMPOLINE_SIZE */
extern unsigned int ffi_metag_trampoline[10]; /* 10 instructions */
/* end of private members */
/*
* __tramp: trampoline memory location
* __fun: assembly routine
* __ctx: memory location for wrapper
*
* At this point, tramp[0] == __ctx !
*/
void ffi_init_trampoline(unsigned char *__tramp, unsigned int __fun, unsigned int __ctx) {
memcpy (__tramp, ffi_metag_trampoline, sizeof(ffi_metag_trampoline));
*(unsigned int*) &__tramp[40] = __ctx;
*(unsigned int*) &__tramp[44] = __fun;
/* This will flush the instruction cache */
__builtin_meta2_cachewd(&__tramp[0], 1);
__builtin_meta2_cachewd(&__tramp[47], 1);
}
/* the cif must already be prepared */
ffi_status
ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
void (*closure_func)(ffi_closure*) = NULL;
if (cif->abi == FFI_SYSV)
closure_func = &ffi_closure_SYSV;
else
return FFI_BAD_ABI;
ffi_init_trampoline(
(unsigned char*)&closure->tramp[0],
(unsigned int)closure_func,
(unsigned int)codeloc);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
/* This function is jumped to by the trampoline */
unsigned int ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
ffi_closure *closure;
void **respp;
void *args;
void *vfp_args;
{
ffi_cif *cif;
void **arg_area;
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_SYSV(args, respp, arg_area, cif, vfp_args);
(closure->fun) ( cif, *respp, arg_area, closure->user_data);
return cif->flags;
}
static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif,
float *vfp_stack)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
/* stack points to original arguments */
argp = stack;
/* Store return value */
if ( cif->flags == FFI_TYPE_STRUCT ) {
argp -= 4;
*rvalue = *(void **) argp;
}
p_argv = avalue;
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) {
size_t z;
size_t alignment;
alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
if ((alignment - 1) & (unsigned)argp)
argp = (char *) ALIGN(argp, alignment);
z = (*p_arg)->size;
*p_argv = (void*) argp;
p_argv++;
argp -= z;
}
return;
}
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2013 Imagination Technologies Ltd.
Target configuration macros for Meta
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 AUTHORS OR COPYRIGHT
HOLDERS 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_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#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_TRAMPOLINE_SIZE 48
#define FFI_NATIVE_RAW_API 0
#endif
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2013 Imagination Technologies Ltd.
Meta 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 AUTHORS OR COPYRIGHT
HOLDERS 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
.macro call_reg x=
.text
.balign 4
mov D1RtP, \x
swap D1RtP, PC
.endm
! Save register arguments
.macro SAVE_ARGS
.text
.balign 4
setl [A0StP++], D0Ar6, D1Ar5
setl [A0StP++], D0Ar4, D1Ar3
setl [A0StP++], D0Ar2, D1Ar1
.endm
! Save retrun, frame pointer and other regs
.macro SAVE_REGS regs=
.text
.balign 4
setl [A0StP++], D0FrT, D1RtP
! Needs to be a pair of regs
.ifnc "\regs",""
setl [A0StP++], \regs
.endif
.endm
! Declare a global function
.macro METAG_FUNC_START name
.text
.balign 4
ENTRY(\name)
.endm
! Return registers from the stack. Reverse SAVE_REGS operation
.macro RET_REGS regs=, cond=
.ifnc "\regs", ""
getl \regs, [--A0StP]
.endif
getl D0FrT, D1RtP, [--A0StP]
.endm
! Return arguments
.macro RET_ARGS
getl D0Ar2, D1Ar1, [--A0StP]
getl D0Ar4, D1Ar3, [--A0StP]
getl D0Ar6, D1Ar5, [--A0StP]
.endm
! D1Ar1: fn
! D0Ar2: &ecif
! D1Ar3: cif->bytes
! D0Ar4: fig->flags
! D1Ar5: ecif.rvalue
! This assumes we are using GNU as
METAG_FUNC_START ffi_call_SYSV
! Save argument registers
SAVE_ARGS
! new frame
mov D0FrT, A0FrP
add A0FrP, A0StP, #0
! Preserve the old frame pointer
SAVE_REGS "D1.5, D0.5"
! Make room for new args. cifs->bytes is the total space for input
! and return arguments
add A0StP, A0StP, D1Ar3
! Preserve cifs->bytes & fn
mov D0.5, D1Ar3
mov D1.5, D1Ar1
! Place all of the ffi_prep_args in position
mov D1Ar1, A0StP
! Call ffi_prep_args(stack, &ecif)
#ifdef __PIC__
callr D1RtP, CNAME(ffi_prep_args@PLT)
#else
callr D1RtP, CNAME(ffi_prep_args)
#endif
! Restore fn pointer
! The foreign stack should look like this
! XXXXX XXXXXX <--- stack pointer
! FnArgN rvalue
! FnArgN+2 FnArgN+1
! FnArgN+4 FnArgN+3
! ....
!
! A0StP now points to the first (or return) argument + 4
! Preserve cif->bytes
getl D0Ar2, D1Ar1, [--A0StP]
getl D0Ar4, D1Ar3, [--A0StP]
getl D0Ar6, D1Ar5, [--A0StP]
! Place A0StP to the first argument again
add A0StP, A0StP, #24 ! That's because we loaded 6 regs x 4 byte each
! A0FrP points to the initial stack without the reserved space for the
! cifs->bytes, whilst A0StP points to the stack after the space allocation
! fn was the first argument of ffi_call_SYSV.
! The stack at this point looks like this:
!
! A0StP(on entry to _SYSV) -> Arg6 Arg5 | low
! Arg4 Arg3 |
! Arg2 Arg1 |
! A0FrP ----> D0FrtP D1RtP |
! D1.5 D0.5 |
! A0StP(bf prep_args) -> FnArgn FnArgn-1 |
! FnArgn-2FnArgn-3 |
! ................ | <= cifs->bytes
! FnArg4 FnArg3 |
! A0StP (prv_A0StP+cifs->bytes) FnArg2 FnArg1 | high
!
! fn was in Arg1 so it's located in in A0FrP+#-0xC
!
! D0Re0 contains the size of arguments stored in registers
sub A0StP, A0StP, D0Re0
! Arg1 is the function pointer for the foreign call. This has been
! preserved in D1.5
! Time to call (fn). Arguments should be like this:
! Arg1-Arg6 are loaded to regs
! The rest of the arguments are stored in stack pointed by A0StP
call_reg D1.5
! Reset stack.
mov A0StP, A0FrP
! Load Arg1 with the pointer to storage for the return type
! This was stored in Arg5
getd D1Ar1, [A0FrP+#-20]
! Load D0Ar2 with the return type code. This was stored in Arg4 (flags)
getd D0Ar2, [A0FrP+#-16]
! We are ready to start processing the return value
! D0Re0 (and D1Re0) hold the return value
! If the return value is NULL, assume no return value
cmp D1Ar1, #0
beq LSYM(Lepilogue)
! return INT
cmp D0Ar2, #FFI_TYPE_INT
! Sadly, there is no setd{cc} instruction so we need to workaround that
bne .INT64
setd [D1Ar1], D0Re0
b LSYM(Lepilogue)
! return INT64
.INT64:
cmp D0Ar2, #FFI_TYPE_SINT64
setleq [D1Ar1], D0Re0, D1Re0
! return DOUBLE
cmp D0Ar2, #FFI_TYPE_DOUBLE
setl [D1AR1++], D0Re0, D1Re0
LSYM(Lepilogue):
! At this point, the stack pointer points right after the argument
! saved area. We need to restore 4 regs, therefore we need to move
! 16 bytes ahead.
add A0StP, A0StP, #16
RET_REGS "D1.5, D0.5"
RET_ARGS
getd D0Re0, [A0StP]
mov A0FrP, D0FrT
swap D1RtP, PC
.ffi_call_SYSV_end:
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
/*
(called by ffi_metag_trampoline)
void ffi_closure_SYSV (ffi_closure*)
(called by ffi_closure_SYSV)
unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (closure,respp, args)
ffi_closure *closure;
void **respp;
void *args;
*/
METAG_FUNC_START ffi_closure_SYSV
! We assume that D1Ar1 holds the address of the
! ffi_closure struct. We will use that to fetch the
! arguments. The stack pointer points to an empty space
! and it is ready to store more data.
! D1Ar1 is ready
! Allocate stack space for return value
add A0StP, A0StP, #8
! Store it to D0Ar2
sub D0Ar2, A0StP, #8
sub D1Ar3, A0FrP, #4
! D1Ar3 contains the address of the original D1Ar1 argument
! We need to subtract #4 later on
! Preverve D0Ar2
mov D0.5, D0Ar2
#ifdef __PIC__
callr D1RtP, CNAME(ffi_closure_SYSV_inner@PLT)
#else
callr D1RtP, CNAME(ffi_closure_SYSV_inner)
#endif
! Check the return value and store it to D0.5
cmp D0Re0, #FFI_TYPE_INT
beq .Lretint
cmp D0Re0, #FFI_TYPE_DOUBLE
beq .Lretdouble
.Lclosure_epilogue:
sub A0StP, A0StP, #8
RET_REGS "D1.5, D0.5"
RET_ARGS
swap D1RtP, PC
.Lretint:
setd [D0.5], D0Re0
b .Lclosure_epilogue
.Lretdouble:
setl [D0.5++], D0Re0, D1Re0
b .Lclosure_epilogue
.ffi_closure_SYSV_end:
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
ENTRY(ffi_metag_trampoline)
SAVE_ARGS
! New frame
mov A0FrP, A0StP
SAVE_REGS "D1.5, D0.5"
mov D0.5, PC
! Load D1Ar1 the value of ffi_metag_trampoline
getd D1Ar1, [D0.5 + #8]
! Jump to ffi_closure_SYSV
getd PC, [D0.5 + #12]
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc
MicroBlaze 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 AUTHORS OR COPYRIGHT
HOLDERS 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>
extern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*,
unsigned int, unsigned int, unsigned int*, void (*fn)(void),
unsigned int, unsigned int);
extern void ffi_closure_SYSV(void);
#define WORD_SIZE sizeof(unsigned int)
#define ARGS_REGISTER_SIZE (WORD_SIZE * 6)
#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE)
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
void ffi_prep_args(void* stack, extended_cif* ecif)
{
unsigned int i;
ffi_type** p_arg;
void** p_argv;
void* stack_args_p = stack;
p_argv = ecif->avalue;
if (ecif == NULL || ecif->cif == NULL) {
return; /* no description to prepare */
}
if ((ecif->cif->rtype != NULL) &&
(ecif->cif->rtype->type == FFI_TYPE_STRUCT))
{
/* if return type is a struct which is referenced on the stack/reg5,
* by a pointer. Stored the return value pointer in r5.
*/
char* addr = stack_args_p;
memcpy(addr, &(ecif->rvalue), WORD_SIZE);
stack_args_p += WORD_SIZE;
}
if (ecif->avalue == NULL) {
return; /* no arguments to prepare */
}
for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
i++, p_arg++)
{
size_t size = (*p_arg)->size;
int type = (*p_arg)->type;
void* value = p_argv[i];
char* addr = stack_args_p;
int aligned_size = WORD_ALIGN(size);
/* force word alignment on the stack */
stack_args_p += aligned_size;
switch (type)
{
case FFI_TYPE_UINT8:
*(unsigned int *)addr = (unsigned int)*(UINT8*)(value);
break;
case FFI_TYPE_SINT8:
*(signed int *)addr = (signed int)*(SINT8*)(value);
break;
case FFI_TYPE_UINT16:
*(unsigned int *)addr = (unsigned int)*(UINT16*)(value);
break;
case FFI_TYPE_SINT16:
*(signed int *)addr = (signed int)*(SINT16*)(value);
break;
case FFI_TYPE_STRUCT:
#if __BIG_ENDIAN__
/*
* MicroBlaze toolchain appears to emit:
* bsrli r5, r5, 8 (caller)
* ...
* <branch to callee>
* ...
* bslli r5, r5, 8 (callee)
*
* For structs like "struct a { uint8_t a[3]; };", when passed
* by value.
*
* Structs like "struct b { uint16_t a; };" are also expected
* to be packed strangely in registers.
*
* This appears to be because the microblaze toolchain expects
* "struct b == uint16_t", which is only any issue for big
* endian.
*
* The following is a work around for big-endian only, for the
* above mentioned case, it will re-align the contents of a
* <= 3-byte struct value.
*/
if (size < WORD_SIZE)
{
memcpy (addr + (WORD_SIZE - size), value, size);
break;
}
#endif
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
case FFI_TYPE_DOUBLE:
default:
memcpy(addr, value, aligned_size);
}
}
}
ffi_status ffi_prep_cif_machdep(ffi_cif* cif)
{
/* check ABI */
switch (cif->abi)
{
case FFI_SYSV:
break;
default:
return FFI_BAD_ABI;
}
return FFI_OK;
}
void ffi_call(ffi_cif* cif, void (*fn)(void), 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, cif->rtype->type, cif->rtype->size);
break;
default:
FFI_ASSERT(0);
break;
}
}
void ffi_closure_call_SYSV(void* register_args, void* stack_args,
ffi_closure* closure, void* rvalue,
unsigned int* rtype, unsigned int* rsize)
{
/* prepare arguments for closure call */
ffi_cif* cif = closure->cif;
ffi_type** arg_types = cif->arg_types;
/* re-allocate data for the args. This needs to be done in order to keep
* multi-word objects (e.g. structs) in contiguous memory. Callers are not
* required to store the value of args in the lower 6 words in the stack
* (although they are allocated in the stack).
*/
char* stackclone = alloca(cif->bytes);
void** avalue = alloca(cif->nargs * sizeof(void*));
void* struct_rvalue = NULL;
char* ptr = stackclone;
int i;
/* copy registers into stack clone */
int registers_used = cif->bytes;
if (registers_used > ARGS_REGISTER_SIZE) {
registers_used = ARGS_REGISTER_SIZE;
}
memcpy(stackclone, register_args, registers_used);
/* copy stack allocated args into stack clone */
if (cif->bytes > ARGS_REGISTER_SIZE) {
int stack_used = cif->bytes - ARGS_REGISTER_SIZE;
memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used);
}
/* preserve struct type return pointer passing */
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
struct_rvalue = *((void**)ptr);
ptr += WORD_SIZE;
}
/* populate arg pointer list */
for (i = 0; i < cif->nargs; i++)
{
switch (arg_types[i]->type)
{
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
#ifdef __BIG_ENDIAN__
avalue[i] = ptr + 3;
#else
avalue[i] = ptr;
#endif
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
#ifdef __BIG_ENDIAN__
avalue[i] = ptr + 2;
#else
avalue[i] = ptr;
#endif
break;
case FFI_TYPE_STRUCT:
#if __BIG_ENDIAN__
/*
* Work around strange ABI behaviour.
* (see info in ffi_prep_args)
*/
if (arg_types[i]->size < WORD_SIZE)
{
memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size);
}
#endif
avalue[i] = (void*)ptr;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
avalue[i] = ptr;
break;
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_FLOAT:
default:
/* default 4-byte argument */
avalue[i] = ptr;
break;
}
ptr += WORD_ALIGN(arg_types[i]->size);
}
/* set the return type info passed back to the wrapper */
*rsize = cif->rtype->size;
*rtype = cif->rtype->type;
if (struct_rvalue != NULL) {
closure->fun(cif, struct_rvalue, avalue, closure->user_data);
/* copy struct return pointer value into function return value */
*((void**)rvalue) = struct_rvalue;
} else {
closure->fun(cif, rvalue, avalue, closure->user_data);
}
}
ffi_status ffi_prep_closure_loc(
ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void* user_data, void* codeloc)
{
unsigned long* tramp = (unsigned long*)&(closure->tramp[0]);
unsigned long cls = (unsigned long)codeloc;
unsigned long fn = 0;
unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV;
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
switch (cif->abi)
{
case FFI_SYSV:
fn = (unsigned long)ffi_closure_SYSV;
/* load r11 (temp) with fn */
/* imm fn(upper) */
tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff);
/* addik r11, r0, fn(lower) */
tramp[1] = 0x31600000 | (fn & 0xffff);
/* load r12 (temp) with cls */
/* imm cls(upper) */
tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff);
/* addik r12, r0, cls(lower) */
tramp[3] = 0x31800000 | (cls & 0xffff);
/* load r3 (temp) with ffi_closure_call_SYSV */
/* imm fn_closure_call_sysv(upper) */
tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff);
/* addik r3, r0, fn_closure_call_sysv(lower) */
tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff);
/* branch/jump to address stored in r11 (fn) */
tramp[6] = 0x98085800; /* bra r11 */
break;
default:
return FFI_BAD_ABI;
}
return FFI_OK;
}
/* -----------------------------------------------------------------------
ffitarget.h - Copyright (c) 2012, 2013 Xilinx, Inc
Target configuration macros for MicroBlaze.
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 AUTHORS OR COPYRIGHT
HOLDERS 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_H
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
/* Definitions for closures */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#define FFI_TRAMPOLINE_SIZE (4*8)
#endif
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc
MicroBlaze 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 AUTHORS OR COPYRIGHT
HOLDERS 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>
/*
* arg[0] (r5) = ffi_prep_args,
* arg[1] (r6) = &ecif,
* arg[2] (r7) = cif->bytes,
* arg[3] (r8) = cif->flags,
* arg[4] (r9) = ecif.rvalue,
* arg[5] (r10) = fn
* arg[6] (sp[0]) = cif->rtype->type
* arg[7] (sp[4]) = cif->rtype->size
*/
.text
.globl ffi_call_SYSV
.type ffi_call_SYSV, @function
ffi_call_SYSV:
/* push callee saves */
addik r1, r1, -20
swi r19, r1, 0 /* Frame Pointer */
swi r20, r1, 4 /* PIC register */
swi r21, r1, 8 /* PIC register */
swi r22, r1, 12 /* save for locals */
swi r23, r1, 16 /* save for locals */
/* save the r5-r10 registers in the stack */
addik r1, r1, -24 /* increment sp to store 6x 32-bit words */
swi r5, r1, 0
swi r6, r1, 4
swi r7, r1, 8
swi r8, r1, 12
swi r9, r1, 16
swi r10, r1, 20
/* save function pointer */
addik r3, r5, 0 /* copy ffi_prep_args into r3 */
addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */
addik r23, r10, 0 /* save function address into r23 (callee-saved) */
/* prepare stack with allocation for n (bytes = r7) args */
rsub r1, r7, r1 /* subtract bytes from sp */
/* prep args for ffi_prep_args call */
addik r5, r1, 0 /* store stack pointer into arg[0] */
/* r6 still holds ecif for arg[1] */
/* Call ffi_prep_args(stack, &ecif). */
addik r1, r1, -4
swi r15, r1, 0 /* store the link register in the frame */
brald r15, r3
nop /* branch has delay slot */
lwi r15, r1, 0
addik r1, r1, 4 /* restore the link register from the frame */
/* returns calling stack pointer location */
/* prepare args for fn call, prep_args populates them onto the stack */
lwi r5, r1, 0 /* arg[0] */
lwi r6, r1, 4 /* arg[1] */
lwi r7, r1, 8 /* arg[2] */
lwi r8, r1, 12 /* arg[3] */
lwi r9, r1, 16 /* arg[4] */
lwi r10, r1, 20 /* arg[5] */
/* call (fn) (...). */
addik r1, r1, -4
swi r15, r1, 0 /* store the link register in the frame */
brald r15, r23
nop /* branch has delay slot */
lwi r15, r1, 0
addik r1, r1, 4 /* restore the link register from the frame */
/* Remove the space we pushed for the args. */
addik r1, r22, 0 /* restore old SP */
/* restore this functions parameters */
lwi r5, r1, 0 /* arg[0] */
lwi r6, r1, 4 /* arg[1] */
lwi r7, r1, 8 /* arg[2] */
lwi r8, r1, 12 /* arg[3] */
lwi r9, r1, 16 /* arg[4] */
lwi r10, r1, 20 /* arg[5] */
addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */
/* If the return value pointer is NULL, assume no return value. */
beqi r9, ffi_call_SYSV_end
lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */
lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7]) */
/* Check if return type is actually a struct, do nothing */
rsubi r11, r22, FFI_TYPE_STRUCT
beqi r11, ffi_call_SYSV_end
/* Return 8bit */
rsubi r11, r23, 1
beqi r11, ffi_call_SYSV_store8
/* Return 16bit */
rsubi r11, r23, 2
beqi r11, ffi_call_SYSV_store16
/* Return 32bit */
rsubi r11, r23, 4
beqi r11, ffi_call_SYSV_store32
/* Return 64bit */
rsubi r11, r23, 8
beqi r11, ffi_call_SYSV_store64
/* Didn't match anything */
bri ffi_call_SYSV_end
ffi_call_SYSV_store64:
swi r3, r9, 0 /* store word r3 into return value */
swi r4, r9, 4 /* store word r4 into return value */
bri ffi_call_SYSV_end
ffi_call_SYSV_store32:
swi r3, r9, 0 /* store word r3 into return value */
bri ffi_call_SYSV_end
ffi_call_SYSV_store16:
#ifdef __BIG_ENDIAN__
shi r3, r9, 2 /* store half-word r3 into return value */
#else
shi r3, r9, 0 /* store half-word r3 into return value */
#endif
bri ffi_call_SYSV_end
ffi_call_SYSV_store8:
#ifdef __BIG_ENDIAN__
sbi r3, r9, 3 /* store byte r3 into return value */
#else
sbi r3, r9, 0 /* store byte r3 into return value */
#endif
bri ffi_call_SYSV_end
ffi_call_SYSV_end:
/* callee restores */
lwi r19, r1, 0 /* frame pointer */
lwi r20, r1, 4 /* PIC register */
lwi r21, r1, 8 /* PIC register */
lwi r22, r1, 12
lwi r23, r1, 16
addik r1, r1, 20
/* return from sub-routine (with delay slot) */
rtsd r15, 8
nop
.size ffi_call_SYSV, . - ffi_call_SYSV
/* ------------------------------------------------------------------------- */
/*
* args passed into this function, are passed down to the callee.
* this function is the target of the closure trampoline, as such r12 is
* a pointer to the closure object.
*/
.text
.globl ffi_closure_SYSV
.type ffi_closure_SYSV, @function
ffi_closure_SYSV:
/* push callee saves */
addik r11, r1, 28 /* save stack args start location (excluding regs/link) */
addik r1, r1, -12
swi r19, r1, 0 /* Frame Pointer */
swi r20, r1, 4 /* PIC register */
swi r21, r1, 8 /* PIC register */
/* store register args on stack */
addik r1, r1, -24
swi r5, r1, 0
swi r6, r1, 4
swi r7, r1, 8
swi r8, r1, 12
swi r9, r1, 16
swi r10, r1, 20
/* setup args */
addik r5, r1, 0 /* register_args */
addik r6, r11, 0 /* stack_args */
addik r7, r12, 0 /* closure object */
addik r1, r1, -8 /* allocate return value */
addik r8, r1, 0 /* void* rvalue */
addik r1, r1, -8 /* allocate for return type/size values */
addik r9, r1, 0 /* void* rtype */
addik r10, r1, 4 /* void* rsize */
/* call the wrap_call function */
addik r1, r1, -28 /* allocate args + link reg */
swi r15, r1, 0 /* store the link register in the frame */
brald r15, r3
nop /* branch has delay slot */
lwi r15, r1, 0
addik r1, r1, 28 /* restore the link register from the frame */
ffi_closure_SYSV_prepare_return:
lwi r9, r1, 0 /* rtype */
lwi r10, r1, 4 /* rsize */
addik r1, r1, 8 /* de-allocate return info values */
/* Check if return type is actually a struct, store 4 bytes */
rsubi r11, r9, FFI_TYPE_STRUCT
beqi r11, ffi_closure_SYSV_store32
/* Return 8bit */
rsubi r11, r10, 1
beqi r11, ffi_closure_SYSV_store8
/* Return 16bit */
rsubi r11, r10, 2
beqi r11, ffi_closure_SYSV_store16
/* Return 32bit */
rsubi r11, r10, 4
beqi r11, ffi_closure_SYSV_store32
/* Return 64bit */
rsubi r11, r10, 8
beqi r11, ffi_closure_SYSV_store64
/* Didn't match anything */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store64:
lwi r3, r1, 0 /* store word r3 into return value */
lwi r4, r1, 4 /* store word r4 into return value */
/* 64 bits == 2 words, no sign extend occurs */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store32:
lwi r3, r1, 0 /* store word r3 into return value */
/* 32 bits == 1 word, no sign extend occurs */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store16:
#ifdef __BIG_ENDIAN__
lhui r3, r1, 2 /* store half-word r3 into return value */
#else
lhui r3, r1, 0 /* store half-word r3 into return value */
#endif
rsubi r11, r9, FFI_TYPE_SINT16
bnei r11, ffi_closure_SYSV_end
sext16 r3, r3 /* fix sign extend of sint8 */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_store8:
#ifdef __BIG_ENDIAN__
lbui r3, r1, 3 /* store byte r3 into return value */
#else
lbui r3, r1, 0 /* store byte r3 into return value */
#endif
rsubi r11, r9, FFI_TYPE_SINT8
bnei r11, ffi_closure_SYSV_end
sext8 r3, r3 /* fix sign extend of sint8 */
bri ffi_closure_SYSV_end
ffi_closure_SYSV_end:
addik r1, r1, 8 /* de-allocate return value */
/* de-allocate stored args */
addik r1, r1, 24
/* callee restores */
lwi r19, r1, 0 /* frame pointer */
lwi r20, r1, 4 /* PIC register */
lwi r21, r1, 8 /* PIC register */
addik r1, r1, 12
/* return from sub-routine (with delay slot) */
rtsd r15, 8
nop
.size ffi_closure_SYSV, . - ffi_closure_SYSV
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment