gh-100540: Remove unused Modules/_ctypes/libffi_osx/ (GH-100543)

It was an ancient, modified copy of libffi that has not been in use
since GH-22855.
This commit is contained in:
Zachary Ware 2022-12-28 13:38:52 -06:00 committed by GitHub
parent 25590eb5de
commit 025b5c3780
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 5 additions and 6651 deletions

View File

@ -1,20 +0,0 @@
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,500 +0,0 @@
This directory contains the libffi package, which is not part of GCC but
shipped with GCC as convenience.
Status
======
libffi-2.00 has not been released yet! This is a development snapshot!
libffi-1.20 was released on October 5, 1998. Check the libffi web
page for updates: <URL:http://sources.redhat.com/libffi/>.
What is libffi?
===============
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 "calling
convention". The "calling convention" is essentially 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.
Some programs may not know at the time of compilation what arguments
are to be passed to a function. For instance, an interpreter may be
told at run-time about the number and types of arguments used to call
a given function. Libffi can be used in such programs to provide a
bridge from the interpreter program to compiled code.
The libffi library provides a portable, high level programming
interface to various calling conventions. This allows a programmer to
call any function specified by a call interface description at run
time.
Ffi stands for Foreign Function Interface. A foreign function
interface is the popular name for the interface that allows code
written in one language to call code written in another language. The
libffi library really only provides the lowest, machine dependent
layer of a fully featured foreign function interface. A layer must
exist above libffi that handles type conversions for values passed
between the two languages.
Supported Platforms and Prerequisites
=====================================
Libffi has been ported to:
SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
Irix 5.3 & 6.2 (System V/o32 & n32)
Intel x86 - Linux (System V ABI)
Alpha - Linux and OSF/1
m68k - Linux (System V ABI)
PowerPC - Linux (System V ABI, Darwin, AIX)
ARM - Linux (System V ABI)
Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
that other versions will work. Libffi has also been built and tested
with the SGI compiler tools.
On PowerPC, the tests failed (see the note below).
You must use GNU make to build libffi. SGI's make will not work.
Sun's probably won't either.
If you port libffi to another platform, please let me know! I assume
that some will be easy (x86 NetBSD), and others will be more difficult
(HP).
Installing libffi
=================
[Note: before actually performing any of these installation steps,
you may wish to read the "Platform Specific Notes" below.]
First you must configure the distribution for your particular
system. Go to the directory you wish to build libffi in and run the
"configure" program found in the root directory of the libffi source
distribution.
You may want to tell configure where to install the libffi library and
header files. To do that, use the --prefix configure switch. Libffi
will install under /usr/local by default.
If you want to enable extra run-time debugging checks use the the
--enable-debug configure switch. This is useful when your program dies
mysteriously while using libffi.
Another useful configure switch is --enable-purify-safety. Using this
will add some extra code which will suppress certain warnings when you
are using Purify with libffi. Only use this switch when using
Purify, as it will slow down the library.
Configure has many other options. Use "configure --help" to see them all.
Once configure has finished, type "make". Note that you must be using
GNU make. SGI's make will not work. Sun's probably won't either.
You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
To ensure that libffi is working as advertised, type "make test".
To install the library and header files, type "make install".
Using libffi
============
The Basics
----------
Libffi assumes that you have a pointer to the function you wish to
call and that you know the number and types of arguments to pass it,
as well as the return type of the function.
The first thing you must do is create an ffi_cif object that matches
the signature of the function you wish to call. The cif in ffi_cif
stands for Call InterFace. To prepare a call interface object, use the
following function:
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
unsigned int nargs,
ffi_type *rtype, ffi_type **atypes);
CIF is a pointer to the call interface object you wish
to initialize.
ABI is an enum that specifies the calling convention
to use for the call. FFI_DEFAULT_ABI defaults
to the system's native calling convention. Other
ABI's may be used with care. They are system
specific.
NARGS is the number of arguments this function accepts.
libffi does not yet support vararg functions.
RTYPE is a pointer to an ffi_type structure that represents
the return type of the function. Ffi_type objects
describe the types of values. libffi provides
ffi_type objects for many of the native C types:
signed int, unsigned int, signed char, unsigned char,
etc. There is also a pointer ffi_type object and
a void ffi_type. Use &ffi_type_void for functions that
don't return values.
ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
If NARGS is 0, this is ignored.
ffi_prep_cif will return a status code that you are responsible
for checking. It will be one of the following:
FFI_OK - All is good.
FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
came across is bad.
Before making the call, the VALUES vector should be initialized
with pointers to the appropriate argument values.
To call the function using the initialized ffi_cif, use the
ffi_call function:
void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
CIF is a pointer to the ffi_cif initialized specifically
for this function.
FN is a pointer to the function you want to call.
RVALUE is a pointer to a chunk of memory that is to hold the
result of the function call. Currently, it must be
at least one word in size (except for the n32 version
under Irix 6.x, which must be a pointer to an 8 byte
aligned value (a long long). It must also be at least
word aligned (depending on the return type, and the
system's alignment requirements). If RTYPE is
&ffi_type_void, this is ignored. If RVALUE is NULL,
the return value is discarded.
AVALUES is a vector of void* that point to the memory locations
holding the argument values for a call.
If NARGS is 0, this is ignored.
If you are expecting a return value from FN it will have been stored
at RVALUE.
An Example
----------
Here is a trivial example that calls puts() a few times.
#include <stdio.h>
#include <ffi.h>
int main()
{
ffi_cif cif;
ffi_type *args[1];
void *values[1];
char *s;
int rc;
/* Initialize the argument info vectors */
args[0] = &ffi_type_uint;
values[0] = &s;
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_uint, args) == FFI_OK)
{
s = "Hello World!";
ffi_call(&cif, puts, &rc, values);
/* rc now holds the result of the call to puts */
/* values holds a pointer to the function's arg, so to
call puts() again all we need to do is change the
value of s */
s = "This is cool!";
ffi_call(&cif, puts, &rc, values);
}
return 0;
}
Aggregate Types
---------------
Although libffi has no special support for unions or bit-fields, it is
perfectly happy passing structures back and forth. You must first
describe the structure to libffi by creating a new ffi_type object
for it. Here is the definition of ffi_type:
typedef struct _ffi_type
{
unsigned size;
short alignment;
short type;
struct _ffi_type **elements;
} ffi_type;
All structures must have type set to FFI_TYPE_STRUCT. You may set
size and alignment to 0. These will be calculated and reset to the
appropriate values by ffi_prep_cif().
elements is a NULL terminated array of pointers to ffi_type objects
that describe the type of the structure elements. These may, in turn,
be structure elements.
The following example initializes a ffi_type object representing the
tm struct from Linux's time.h:
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
/* Those are for future use. */
long int __tm_gmtoff__;
__const char *__tm_zone__;
};
{
ffi_type tm_type;
ffi_type *tm_type_elements[12];
int i;
tm_type.size = tm_type.alignment = 0;
tm_type.elements = &tm_type_elements;
for (i = 0; i < 9; i++)
tm_type_elements[i] = &ffi_type_sint;
tm_type_elements[9] = &ffi_type_slong;
tm_type_elements[10] = &ffi_type_pointer;
tm_type_elements[11] = NULL;
/* tm_type can now be used to represent tm argument types and
return types for ffi_prep_cif() */
}
Platform Specific Notes
=======================
Intel x86
---------
There are no known problems with the x86 port.
Sun SPARC - SunOS 4.1.3 & Solaris 2.x
-------------------------------------
You must use GNU Make to build libffi on Sun platforms.
MIPS - Irix 5.3 & 6.x
---------------------
Irix 6.2 and better supports three different calling conventions: o32,
n32 and n64. Currently, libffi only supports both o32 and n32 under
Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
configured for whichever calling convention it was built for.
By default, the configure script will try to build libffi with the GNU
development tools. To build libffi with the SGI development tools, set
the environment variable CC to either "cc -32" or "cc -n32" before
running configure under Irix 6.x (depending on whether you want an o32
or n32 library), or just "cc" for Irix 5.3.
With the n32 calling convention, when returning structures smaller
than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
Here's one way of forcing this:
double struct_storage[2];
my_small_struct *s = (my_small_struct *) struct_storage;
/* Use s for RVALUE */
If you don't do this you are liable to get spurious bus errors.
"long long" values are not supported yet.
You must use GNU Make to build libffi on SGI platforms.
ARM - System V ABI
------------------
The ARM port was performed on a NetWinder running ARM Linux ELF
(2.0.31) and gcc 2.8.1.
PowerPC System V ABI
--------------------
There are two `System V ABI's which libffi implements for PowerPC.
They differ only in how small structures are returned from functions.
In the FFI_SYSV version, structures that are 8 bytes or smaller are
returned in registers. This is what GCC does when it is configured
for solaris, and is what the System V ABI I have (dated September
1995) says.
In the FFI_GCC_SYSV version, all structures are returned the same way:
by passing a pointer as the first argument to the function. This is
what GCC does when it is configured for linux or a generic sysv
target.
EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
inconsistency with the SysV ABI: When a procedure is called with many
floating-point arguments, some of them get put on the stack. They are
all supposed to be stored in double-precision format, even if they are
only single-precision, but EGCS stores single-precision arguments as
single-precision anyway. This causes one test to fail (the `many
arguments' test).
What's With The Cryptic Comments?
=================================
You might notice a number of cryptic comments in the code, delimited
by /*@ and @*/. These are annotations read by the program LCLint, a
tool for statically checking C programs. You can read all about it at
<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
History
=======
1.20 Oct-5-98
Raffaele Sena produces ARM port.
1.19 Oct-5-98
Fixed x86 long double and long long return support.
m68k bug fixes from Andreas Schwab.
Patch for DU assembler compatibility for the Alpha from Richard
Henderson.
1.18 Apr-17-98
Bug fixes and MIPS configuration changes.
1.17 Feb-24-98
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
1.16 Feb-11-98
Richard Henderson produces Alpha port.
1.15 Dec-4-97
Fixed an n32 ABI bug. New libtool, auto* support.
1.14 May-13-97
libtool is now used to generate shared and static libraries.
Fixed a minor portability problem reported by Russ McManus
<mcmanr@eq.gs.com>.
1.13 Dec-2-96
Added --enable-purify-safety to keep Purify from complaining
about certain low level code.
Sparc fix for calling functions with < 6 args.
Linux x86 a.out fix.
1.12 Nov-22-96
Added missing ffi_type_void, needed for supporting void return
types. Fixed test case for non MIPS machines. Cygnus Support
is now Cygnus Solutions.
1.11 Oct-30-96
Added notes about GNU make.
1.10 Oct-29-96
Added configuration fix for non GNU compilers.
1.09 Oct-29-96
Added --enable-debug configure switch. Clean-ups based on LCLint
feedback. ffi_mips.h is always installed. Many configuration
fixes. Fixed ffitest.c for sparc builds.
1.08 Oct-15-96
Fixed n32 problem. Many clean-ups.
1.07 Oct-14-96
Gordon Irlam rewrites v8.S again. Bug fixes.
1.06 Oct-14-96
Gordon Irlam improved the sparc port.
1.05 Oct-14-96
Interface changes based on feedback.
1.04 Oct-11-96
Sparc port complete (modulo struct passing bug).
1.03 Oct-10-96
Passing struct args, and returning struct values works for
all architectures/calling conventions. Expanded tests.
1.02 Oct-9-96
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
Added "make test".
1.01 Oct-8-96
Fixed float passing bug in mips version. Restructured some
of the code. Builds cleanly with SGI tools.
1.00 Oct-7-96
First release. No public announcement.
Authors & Credits
=================
libffi was written by Anthony Green <green@cygnus.com>.
Portions of libffi were derived from Gianni Mariani's free gencall
library for Silicon Graphics machines.
The closure mechanism was designed and implemented by Kresten Krab
Thorup.
The Sparc port was derived from code contributed by the fine folks at
Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
The Alpha port was written by Richard Henderson at Cygnus Solutions.
Andreas Schwab ported libffi to m68k Linux and provided a number of
bug fixes.
Geoffrey Keating ported libffi to the PowerPC.
Raffaele Sena ported libffi to the ARM.
Jesper Skov and Andrew Haley both did more than their fair share of
stepping through the code and tracking down bugs.
Thanks also to Tom Tromey for bug fixes and configuration help.
Thanks to Jim Blandy, who provided some useful feedback on the libffi
interface.
If you have a problem, or have found a bug, please send a note to
green@cygnus.com.

View File

@ -1,5 +0,0 @@
This directory contains a slightly modified version of libffi, extracted from
the GCC source-tree.
The only modifications are those that are necessary to compile libffi using
the Apple provided compiler and outside of the GCC source tree.

View File

@ -1,227 +0,0 @@
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdbool.h>
#include <stdlib.h>
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
/* Perform machine independent initialization of aggregate type
specifications. */
static ffi_status
initialize_aggregate(
/*@out@*/ ffi_type* arg)
{
/*@-usedef@*/
ffi_type** ptr;
if (arg == NULL || arg->elements == NULL ||
arg->size != 0 || arg->alignment != 0)
return FFI_BAD_TYPEDEF;
ptr = &(arg->elements[0]);
while ((*ptr) != NULL)
{
if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
#ifdef POWERPC_DARWIN
int curalign = (*ptr)->alignment;
if (ptr != &(arg->elements[0]))
{
if (curalign > 4 && curalign != 16)
curalign = 4;
}
arg->size = ALIGN(arg->size, curalign);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > curalign) ?
arg->alignment : curalign;
#else
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
#endif
ptr++;
}
/* Structure size includes tail padding. This is important for
structures that fit in one register on ABIs like the PowerPC64
Linux ABI that right justify small structs in a register.
It's also needed for nested structure layout, for example
struct A { long a; char b; }; struct B { struct A x; char y; };
should find y at an offset of 2*sizeof(long) and result in a
total size of 3*sizeof(long). */
arg->size = ALIGN(arg->size, arg->alignment);
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
return FFI_OK;
/*@=usedef@*/
}
#ifndef __CRIS__
/* The CRIS ABI specifies structure elements to have byte
alignment only, so it completely overrides this functions,
which assumes "natural" alignment and padding. */
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
#if defined(X86_DARWIN) && !defined __x86_64__
static inline bool
struct_on_stack(
int size)
{
if (size > 8)
return true;
/* This is not what the ABI says, but is what is really implemented */
switch (size)
{
case 1:
case 2:
case 4:
case 8:
return false;
default:
return true;
}
}
#endif // defined(X86_DARWIN) && !defined __x86_64__
// Arguments' ffi_type->alignment must be nonzero.
ffi_status
ffi_prep_cif(
/*@out@*/ /*@partial@*/ ffi_cif* cif,
ffi_abi abi,
unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
/*@dependent@*/ ffi_type** atypes)
{
unsigned int bytes = 0;
unsigned int i;
ffi_type** ptr;
if (cif == NULL)
return FFI_BAD_TYPEDEF;
if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI)
return FFI_BAD_ABI;
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->rtype = rtype;
cif->flags = 0;
/* Initialize the return type if necessary */
/*@-usedef@*/
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
/*@=usedef@*/
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
#ifdef X86_DARWIN
&& (struct_on_stack(cif->rtype->size))
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
/* Initialize any uninitialized aggregate type definitions */
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
if ((*ptr)->alignment == 0)
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if defined(X86_DARWIN)
{
int align = (*ptr)->alignment;
if (align > 4)
align = 4;
if ((align - 1) & bytes)
bytes = ALIGN(bytes, align);
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#elif !defined __x86_64__ && !defined S390 && !defined PA
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_V9))
bytes += sizeof(void*);
else
#endif
{
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
cif->bytes = bytes;
/* Perform machine dependent cif processing */
return ffi_prep_cif_machdep(cif);
}
#endif /* not __CRIS__ */

View File

@ -1,355 +0,0 @@
/* -----------------------------------------------------------------*-C-*-
libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/* -------------------------------------------------------------------
The basic API is described in the README file.
The raw API is designed to bypass some of the argument packing
and unpacking on architectures for which it can be avoided.
The closure API allows interpreted functions to be packaged up
inside a C function pointer, so that they can be called as C functions,
with no understanding on the client side that they are interpreted.
It can also be used in other cases in which it is necessary to package
up a user specified parameter and a function pointer as a single
function pointer.
The closure API must be implemented in order to get its functionality,
e.g. for use by gij. Routines are provided to emulate the raw API
if the underlying platform doesn't allow faster implementation.
More details on the raw and closure API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- */
#ifndef LIBFFI_H
#define LIBFFI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
#ifdef MACOSX
# if defined(__i386__) || defined(__x86_64__)
# define X86_DARWIN
# elif defined(__ppc__) || defined(__ppc64__)
# define POWERPC_DARWIN
# else
# error "Unsupported MacOS X CPU type"
# endif
#else
#error "Unsupported OS type"
#endif
/* ---- System configuration information --------------------------------- */
#include "ffitarget.h"
#include "fficonfig.h"
#ifndef LIBFFI_ASM
#include <stddef.h>
#include <limits.h>
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# endif
#endif
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
#else
#error "char size not supported"
#endif
#if SHRT_MAX == 32767
# define ffi_type_ushort ffi_type_uint16
# define ffi_type_sshort ffi_type_sint16
#elif SHRT_MAX == 2147483647
# define ffi_type_ushort ffi_type_uint32
# define ffi_type_sshort ffi_type_sint32
#else
#error "short size not supported"
#endif
#if INT_MAX == 32767
# define ffi_type_uint ffi_type_uint16
# define ffi_type_sint ffi_type_sint16
#elif INT_MAX == 2147483647
# define ffi_type_uint ffi_type_uint32
# define ffi_type_sint ffi_type_sint32
#elif INT_MAX == 9223372036854775807
# define ffi_type_uint ffi_type_uint64
# define ffi_type_sint ffi_type_sint64
#else
#error "int size not supported"
#endif
#define ffi_type_ulong ffi_type_uint64
#define ffi_type_slong ffi_type_sint64
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != 9223372036854775807
# error "no 64-bit data type supported"
# endif
#elif LONG_MAX != 9223372036854775807
#error "long size not supported"
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t
can hold a pointer. */
typedef struct _ffi_type {
size_t size;
unsigned short alignment;
unsigned short type;
/*@null@*/ struct _ffi_type** elements;
} ffi_type;
/* 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_longdouble;
extern ffi_type ffi_type_pointer;
typedef enum ffi_status {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
} ffi_status;
typedef unsigned FFI_TYPE;
typedef struct ffi_cif {
ffi_abi abi;
unsigned nargs;
/*@dependent@*/ ffi_type** arg_types;
/*@dependent@*/ ffi_type* rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
/* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
# elif LONG_MAX == 9223372036854775807
# define FFI_SIZEOF_ARG 8
# endif
#endif
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
char data[FFI_SIZEOF_ARG];
void* ptr;
} ffi_raw;
void
ffi_raw_call(
/*@dependent@*/ ffi_cif* cif,
void (*fn)(void),
/*@out@*/ void* rvalue,
/*@dependent@*/ ffi_raw* avalue);
void
ffi_ptrarray_to_raw(
ffi_cif* cif,
void** args,
ffi_raw* raw);
void
ffi_raw_to_ptrarray(
ffi_cif* cif,
ffi_raw* raw,
void** args);
size_t
ffi_raw_size(
ffi_cif* cif);
/* This is analogous to the raw API, except it uses Java parameter
packing, even on 64-bit machines. I.e. on 64-bit machines
longs and doubles are followed by an empty 64-bit word. */
void
ffi_java_raw_call(
/*@dependent@*/ ffi_cif* cif,
void (*fn)(void),
/*@out@*/ void* rvalue,
/*@dependent@*/ ffi_raw* avalue);
void
ffi_java_ptrarray_to_raw(
ffi_cif* cif,
void** args,
ffi_raw* raw);
void
ffi_java_raw_to_ptrarray(
ffi_cif* cif,
ffi_raw* raw,
void** args);
size_t
ffi_java_raw_size(
ffi_cif* cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
typedef struct ffi_closure {
char tramp[FFI_TRAMPOLINE_SIZE];
ffi_cif* cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void* user_data;
} ffi_closure;
ffi_status
ffi_prep_closure(
ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void* user_data);
void ffi_closure_free(void *);
void *ffi_closure_alloc (size_t size, void **code);
typedef struct ffi_raw_closure {
char tramp[FFI_TRAMPOLINE_SIZE];
ffi_cif* cif;
#if !FFI_NATIVE_RAW_API
/* if this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void* this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
void* user_data;
} ffi_raw_closure;
ffi_status
ffi_prep_raw_closure(
ffi_raw_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void* user_data);
ffi_status
ffi_prep_java_raw_closure(
ffi_raw_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void* user_data);
#endif // FFI_CLOSURES
/* ---- Public interface definition -------------------------------------- */
ffi_status
ffi_prep_cif(
/*@out@*/ /*@partial@*/ ffi_cif* cif,
ffi_abi abi,
unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
/*@dependent@*/ ffi_type** atypes);
void
ffi_call(
/*@dependent@*/ ffi_cif* cif,
void (*fn)(void),
/*@out@*/ void* rvalue,
/*@dependent@*/ void** avalue);
/* Useful for eliminating compiler warnings */
#define FFI_FN(f) ((void (*)(void))f)
#endif // #ifndef LIBFFI_ASM
/* ---- Definitions shared with assembly code ---------------------------- */
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#ifdef HAVE_LONG_DOUBLE
# define FFI_TYPE_LONGDOUBLE 4
#else
# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
/* This should always refer to the last type code (for sanity checks) */
#define FFI_TYPE_LAST FFI_TYPE_POINTER
#ifdef __cplusplus
}
#endif
#endif // #ifndef LIBFFI_H

View File

@ -1,102 +0,0 @@
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
#ifndef FFI_COMMON_H
#define FFI_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include "fficonfig.h"
/* Do not move this. Some versions of AIX are very picky about where
this is positioned. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char* alloca();
# endif
# endif
# endif
#endif
/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy((s), (d), (n))
# endif
#endif
/*#if defined(FFI_DEBUG)
#include <stdio.h>
#endif*/
#ifdef FFI_DEBUG
#include <stdio.h>
/*@exits@*/ void
ffi_assert(
/*@temp@*/ char* expr,
/*@temp@*/ char* file,
int line);
void
ffi_stop_here(void);
void
ffi_type_test(
/*@temp@*/ /*@out@*/ ffi_type* a,
/*@temp@*/ char* file,
int line);
# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__)
#else
# define FFI_ASSERT(x)
# define FFI_ASSERT_AT(x, f, l)
# define FFI_ASSERT_VALID_TYPE(x)
#endif // #ifdef FFI_DEBUG
#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
/* Perform machine dependent cif processing */
ffi_status
ffi_prep_cif_machdep(
ffi_cif* cif);
/* Extended cif, used in callback from assembly routine */
typedef struct extended_cif {
/*@dependent@*/ ffi_cif* cif;
/*@dependent@*/ void* rvalue;
/*@dependent@*/ void** avalue;
} extended_cif;
/* Terse sized type definitions. */
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
#ifdef __cplusplus
}
#endif
#endif // #ifndef FFI_COMMON_H

View File

@ -1,150 +0,0 @@
/* Manually created fficonfig.h for Darwin on PowerPC or Intel
This file is manually generated to do away with the need for autoconf and
therefore make it easier to cross-compile and build fat binaries.
NOTE: This file was added by PyObjC.
*/
#ifndef MACOSX
#error "This file is only supported on Mac OS X"
#endif
#if defined(__i386__)
# define BYTEORDER 1234
# undef HOST_WORDS_BIG_ENDIAN
# undef WORDS_BIGENDIAN
# define SIZEOF_DOUBLE 8
# define HAVE_LONG_DOUBLE 1
# define SIZEOF_LONG_DOUBLE 16
#elif defined(__x86_64__)
# define BYTEORDER 1234
# undef HOST_WORDS_BIG_ENDIAN
# undef WORDS_BIGENDIAN
# define SIZEOF_DOUBLE 8
# define HAVE_LONG_DOUBLE 1
# define SIZEOF_LONG_DOUBLE 16
#elif defined(__ppc__)
# define BYTEORDER 4321
# define HOST_WORDS_BIG_ENDIAN 1
# define WORDS_BIGENDIAN 1
# define SIZEOF_DOUBLE 8
# if __GNUC__ >= 4
# define HAVE_LONG_DOUBLE 1
# define SIZEOF_LONG_DOUBLE 16
# else
# undef HAVE_LONG_DOUBLE
# define SIZEOF_LONG_DOUBLE 8
# endif
#elif defined(__ppc64__)
# define BYTEORDER 4321
# define HOST_WORDS_BIG_ENDIAN 1
# define WORDS_BIGENDIAN 1
# define SIZEOF_DOUBLE 8
# define HAVE_LONG_DOUBLE 1
# define SIZEOF_LONG_DOUBLE 16
#else
#error "Unknown CPU type"
#endif
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems. */
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to the flags needed for the .section .eh_frame directive. */
#define EH_FRAME_FLAGS "aw"
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Define this is you do not want support for the raw API. */
#define FFI_NO_RAW_API 1
/* 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. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if your assembler and linker support unaligned PC relative relocs. */
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
#define HAVE_MMAP_ANON 1
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
/* Define if read-only mmap of a plain file works. */
#define HAVE_MMAP_FILE 1
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "libffi"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libffi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libffi 2.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libffi"
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.1"
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define this if you are using Purify and want to suppress spurious messages. */
/* #undef USING_PURIFY */
/* Version number of package */
#define VERSION "2.1-pyobjc"
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
# ifdef LIBFFI_ASM
# define FFI_HIDDEN(name) .hidden name
# else
# define FFI_HIDDEN __attribute__((visibility ("hidden")))
# endif
#else
# ifdef LIBFFI_ASM
# define FFI_HIDDEN(name)
# else
# define FFI_HIDDEN
# endif
#endif

View File

@ -1,13 +0,0 @@
/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a
normal build, the build environment copies the file to the right location or
sets up the right include flags. We want to do neither because that would
make building fat binaries harder.
*/
#if defined(__i386__) || defined(__x86_64__)
#include "x86-ffitarget.h"
#elif defined(__ppc__) || defined(__ppc64__)
#include "ppc-ffitarget.h"
#else
#error "Unsupported CPU type"
#endif

View File

@ -1,104 +0,0 @@
/* -----------------------------------------------------------------*-C-*-
ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for PowerPC.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
/* ---- System specific configurations ----------------------------------- */
#if (defined(POWERPC) && defined(__powerpc64__)) || \
(defined(POWERPC_DARWIN) && defined(__ppc64__))
#define POWERPC64
#endif
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
#ifdef POWERPC
FFI_SYSV,
FFI_GCC_SYSV,
FFI_LINUX64,
# ifdef POWERPC64
FFI_DEFAULT_ABI = FFI_LINUX64,
# else
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
# endif
#endif
#ifdef POWERPC_AIX
FFI_AIX,
FFI_DARWIN,
FFI_DEFAULT_ABI = FFI_AIX,
#endif
#ifdef POWERPC_DARWIN
FFI_AIX,
FFI_DARWIN,
FFI_DEFAULT_ABI = FFI_DARWIN,
#endif
#ifdef POWERPC_FREEBSD
FFI_SYSV,
FFI_GCC_SYSV,
FFI_LINUX64,
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif // #ifndef LIBFFI_ASM
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
/* Needed for FFI_SYSV small structure returns. */
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST)
#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/
# define FFI_TRAMPOLINE_SIZE 48
#elif defined(POWERPC_AIX)
# define FFI_TRAMPOLINE_SIZE 24
#else
# define FFI_TRAMPOLINE_SIZE 40
#endif
#ifndef LIBFFI_ASM
# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
typedef struct ffi_aix_trampoline_struct {
void* code_pointer; /* Pointer to ffi_closure_ASM */
void* toc; /* TOC */
void* static_chain; /* Pointer to closure */
} ffi_aix_trampoline_struct;
# endif
#endif // #ifndef LIBFFI_ASM
#endif // #ifndef LIBFFI_TARGET_H

View File

@ -1,88 +0,0 @@
/* -----------------------------------------------------------------*-C-*-
x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for x86 and x86-64.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
/* ---- System specific configurations ----------------------------------- */
#if defined(X86_64) && defined(__i386__)
# undef X86_64
# define X86
#endif
#if defined(__x86_64__)
# ifndef X86_64
# define X86_64
# endif
#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,
/* ---- Intel x86 Win32 ---------- */
#ifdef X86_WIN32
FFI_SYSV,
FFI_STDCALL,
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
/* ---- Intel x86 and AMD x86-64 - */
#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
FFI_SYSV,
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
# ifdef __i386__
FFI_DEFAULT_ABI = FFI_SYSV,
# else
FFI_DEFAULT_ABI = FFI_UNIX64,
# endif
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif // #ifndef LIBFFI_ASM
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN))
# define FFI_TRAMPOLINE_SIZE 24
# define FFI_NATIVE_RAW_API 0
#else
# define FFI_TRAMPOLINE_SIZE 10
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
#endif // #ifndef LIBFFI_TARGET_H

View File

@ -1,365 +0,0 @@
#if defined(__ppc__) || defined(__ppc64__)
/* -----------------------------------------------------------------------
ppc-darwin.S - Copyright (c) 2000 John Hornkvist
Copyright (c) 2004 Free Software Foundation, Inc.
PowerPC Assembly glue.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ppc-darwin.h>
#include <architecture/ppc/mode_independent_asm.h>
.text
.align 2
.globl _ffi_prep_args
.text
.align 2
.globl _ffi_call_DARWIN
.text
.align 2
_ffi_call_DARWIN:
LFB0:
mr r12,r8 /* We only need r12 until the call,
so it doesn't have to be saved. */
LFB1:
/* Save the old stack pointer as AP. */
mr r8,r1
LCFI0:
#if defined(__ppc64__)
/* Allocate the stack space we need.
r4 (size of input data)
48 bytes (linkage area)
40 bytes (saved registers)
8 bytes (extra FPR)
r4 + 96 bytes total
*/
addi r4,r4,-96 // Add our overhead.
li r0,-32 // Align to 32 bytes.
and r4,r4,r0
#endif
stgux r1,r1,r4 // Grow the stack.
mflr r9
/* Save registers we use. */
#if defined(__ppc64__)
std r27,-40(r8)
#endif
stg r28,MODE_CHOICE(-16,-32)(r8)
stg r29,MODE_CHOICE(-12,-24)(r8)
stg r30,MODE_CHOICE(-8,-16)(r8)
stg r31,MODE_CHOICE(-4,-8)(r8)
stg r9,SF_RETURN(r8) /* return address */
#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
stg r2,MODE_CHOICE(20,40)(r1)
#endif
LCFI1:
#if defined(__ppc64__)
mr r27,r3 // our extended_cif
#endif
/* Save arguments over call. */
mr r31,r5 /* flags, */
mr r30,r6 /* rvalue, */
mr r29,r7 /* function address, */
mr r28,r8 /* our AP. */
LCFI2:
/* Call ffi_prep_args. */
mr r4,r1
li r9,0
mtctr r12 /* r12 holds address of _ffi_prep_args. */
bctrl
#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
lg r2,MODE_CHOICE(20,40)(r1)
#endif
/* Now do the call.
Set up cr1 with bits 4-7 of the flags. */
mtcrf 0x40,r31
/* Load all those argument registers.
We have set up a nice stack frame, just load it into registers. */
lg r3,SF_ARG1(r1)
lg r4,SF_ARG2(r1)
lg r5,SF_ARG3(r1)
lg r6,SF_ARG4(r1)
nop
lg r7,SF_ARG5(r1)
lg r8,SF_ARG6(r1)
lg r9,SF_ARG7(r1)
lg r10,SF_ARG8(r1)
/* Load all the FP registers. */
bf 6,L2 /* No floats to load. */
#if defined(__ppc64__)
lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
nop
lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
nop
lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
nop
lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
#elif defined(__ppc__)
lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
nop
lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
nop
lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
nop
lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
#else
#error undefined architecture
#endif
L2:
mr r12,r29 // Put the target address in r12 as specified.
mtctr r12 // Get the address to call into CTR.
nop
nop
bctrl // Make the call.
// Deal with the return value.
#if defined(__ppc64__)
mtcrf 0x3,r31 // flags in cr6 and cr7
bt 27,L(st_return_value)
#elif defined(__ppc__)
mtcrf 0x1,r31 // flags in cr7
#else
#error undefined architecture
#endif
bt 30,L(done_return_value)
bt 29,L(fp_return_value)
stg r3,0(r30)
#if defined(__ppc__)
bf 28,L(done_return_value) // Store the second long if necessary.
stg r4,4(r30)
#endif
// Fall through
L(done_return_value):
lg r1,0(r1) // Restore stack pointer.
// Restore the registers we used.
lg r9,SF_RETURN(r1) // return address
lg r31,MODE_CHOICE(-4,-8)(r1)
mtlr r9
lg r30,MODE_CHOICE(-8,-16)(r1)
lg r29,MODE_CHOICE(-12,-24)(r1)
lg r28,MODE_CHOICE(-16,-32)(r1)
#if defined(__ppc64__)
ld r27,-40(r1)
#endif
blr
#if defined(__ppc64__)
L(st_return_value):
// Grow the stack enough to fit the registers. Leave room for 8 args
// to trample the 1st 8 slots in param area.
stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
// Store GPRs
std r3,SF_ARG9(r1)
std r4,SF_ARG10(r1)
std r5,SF_ARG11(r1)
std r6,SF_ARG12(r1)
nop
std r7,SF_ARG13(r1)
std r8,SF_ARG14(r1)
std r9,SF_ARG15(r1)
std r10,SF_ARG16(r1)
// Store FPRs
nop
bf 26,L(call_struct_to_ram_form)
stfd f1,SF_ARG17(r1)
stfd f2,SF_ARG18(r1)
stfd f3,SF_ARG19(r1)
stfd f4,SF_ARG20(r1)
nop
stfd f5,SF_ARG21(r1)
stfd f6,SF_ARG22(r1)
stfd f7,SF_ARG23(r1)
stfd f8,SF_ARG24(r1)
nop
stfd f9,SF_ARG25(r1)
stfd f10,SF_ARG26(r1)
stfd f11,SF_ARG27(r1)
stfd f12,SF_ARG28(r1)
nop
stfd f13,SF_ARG29(r1)
L(call_struct_to_ram_form):
ld r3,0(r27) // extended_cif->cif*
ld r3,16(r3) // ffi_cif->rtype*
addi r4,r1,SF_ARG9 // stored GPRs
addi r6,r1,SF_ARG17 // stored FPRs
li r5,0 // GPR size ptr (NULL)
li r7,0 // FPR size ptr (NULL)
li r8,0 // FPR count ptr (NULL)
li r10,0 // struct offset (NULL)
mr r9,r30 // return area
bl Lffi64_struct_to_ram_form$stub
lg r1,0(r1) // Restore stack pointer.
b L(done_return_value)
#endif
L(fp_return_value):
/* Do we have long double to store? */
bf 31,L(fd_return_value)
stfd f1,0(r30)
stfd f2,8(r30)
b L(done_return_value)
L(fd_return_value):
/* Do we have double to store? */
bf 28,L(float_return_value)
stfd f1,0(r30)
b L(done_return_value)
L(float_return_value):
/* We only have a float to store. */
stfs f1,0(r30)
b L(done_return_value)
LFE1:
/* END(_ffi_call_DARWIN) */
/* Provide a null definition of _ffi_call_AIX. */
.text
.align 2
.globl _ffi_call_AIX
.text
.align 2
_ffi_call_AIX:
blr
/* END(_ffi_call_AIX) */
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0 ; Length of Common Information Entry
LSCIE1:
.long 0x0 ; CIE Identifier Tag
.byte 0x1 ; CIE Version
.ascii "zR\0" ; CIE Augmentation
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x10 ; FDE Encoding (pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
.align LOG2_GPR_BYTES
LECIE1:
.globl _ffi_call_DARWIN.eh
_ffi_call_DARWIN.eh:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1 ; FDE Length
LASFDE1:
.long LASFDE1-EH_frame1 ; FDE CIE offset
.g_long LFB0-. ; FDE initial location
.set L$set$3,LFE1-LFB0
.g_long L$set$3 ; FDE address range
.byte 0x0 ; uleb128 0x0; Augmentation size
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$4,LCFI0-LFB1
.long L$set$4
.byte 0xd ; DW_CFA_def_cfa_register
.byte 0x08 ; uleb128 0x08
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$5,LCFI1-LCFI0
.long L$set$5
.byte 0x11 ; DW_CFA_offset_extended_sf
.byte 0x41 ; uleb128 0x41
.byte 0x7e ; sleb128 -2
.byte 0x9f ; DW_CFA_offset, column 0x1f
.byte 0x1 ; uleb128 0x1
.byte 0x9e ; DW_CFA_offset, column 0x1e
.byte 0x2 ; uleb128 0x2
.byte 0x9d ; DW_CFA_offset, column 0x1d
.byte 0x3 ; uleb128 0x3
.byte 0x9c ; DW_CFA_offset, column 0x1c
.byte 0x4 ; uleb128 0x4
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$6,LCFI2-LCFI1
.long L$set$6
.byte 0xd ; DW_CFA_def_cfa_register
.byte 0x1c ; uleb128 0x1c
.align LOG2_GPR_BYTES
LEFDE1:
#if defined(__ppc64__)
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align LOG2_GPR_BYTES
Lffi64_struct_to_ram_form$stub:
.indirect_symbol _ffi64_struct_to_ram_form
mflr r0
bcl 20,31,LO$ffi64_struct_to_ram_form
LO$ffi64_struct_to_ram_form:
mflr r11
addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
mtlr r0
lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_ffi64_struct_to_ram_form$lazy_ptr:
.indirect_symbol _ffi64_struct_to_ram_form
.g_long dyld_stub_binding_helper
#endif // __ppc64__
#endif // __ppc__ || __ppc64__

View File

@ -1,85 +0,0 @@
/* -----------------------------------------------------------------------
ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define L(x) x
#define SF_ARG9 MODE_CHOICE(56,112)
#define SF_ARG10 MODE_CHOICE(60,120)
#define SF_ARG11 MODE_CHOICE(64,128)
#define SF_ARG12 MODE_CHOICE(68,136)
#define SF_ARG13 MODE_CHOICE(72,144)
#define SF_ARG14 MODE_CHOICE(76,152)
#define SF_ARG15 MODE_CHOICE(80,160)
#define SF_ARG16 MODE_CHOICE(84,168)
#define SF_ARG17 MODE_CHOICE(88,176)
#define SF_ARG18 MODE_CHOICE(92,184)
#define SF_ARG19 MODE_CHOICE(96,192)
#define SF_ARG20 MODE_CHOICE(100,200)
#define SF_ARG21 MODE_CHOICE(104,208)
#define SF_ARG22 MODE_CHOICE(108,216)
#define SF_ARG23 MODE_CHOICE(112,224)
#define SF_ARG24 MODE_CHOICE(116,232)
#define SF_ARG25 MODE_CHOICE(120,240)
#define SF_ARG26 MODE_CHOICE(124,248)
#define SF_ARG27 MODE_CHOICE(128,256)
#define SF_ARG28 MODE_CHOICE(132,264)
#define SF_ARG29 MODE_CHOICE(136,272)
#define ASM_NEEDS_REGISTERS 4
#define NUM_GPR_ARG_REGISTERS 8
#define NUM_FPR_ARG_REGISTERS 13
#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
#define FFI_TYPE_4_BYTE(x) \
((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
(x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
#if !defined(LIBFFI_ASM)
enum {
FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
FLAG_RETURNS_FP = 1 << (31 - 29),
FLAG_RETURNS_64BITS = 1 << (31 - 28),
FLAG_RETURNS_128BITS = 1 << (31 - 31),
FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
};
#if defined(__ppc64__)
void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
const char*, unsigned int*, unsigned int*, char*, unsigned int*);
void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
unsigned int*, char*, unsigned int*, char*, unsigned int*);
bool ffi64_stret_needs_ptr(const ffi_type* inType,
unsigned short*, unsigned short*);
#endif
#endif // !defined(LIBFFI_ASM)

View File

@ -1,308 +0,0 @@
#if defined(__ppc__)
/* -----------------------------------------------------------------------
ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
Inc. based on ppc_closure.S
PowerPC Assembly glue.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <ffi.h>
#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE
#include <ppc-darwin.h>
#include <architecture/ppc/mode_independent_asm.h>
.file "ppc-darwin_closure.S"
.text
.align LOG2_GPR_BYTES
.globl _ffi_closure_ASM
.text
.align LOG2_GPR_BYTES
_ffi_closure_ASM:
LFB1:
mflr r0 // Save return address
stg r0,SF_RETURN(r1)
LCFI0:
/* 24/48 bytes (Linkage Area)
32/64 bytes (outgoing parameter area, always reserved)
104 bytes (13*8 from FPR)
16/32 bytes (result)
176/232 total bytes */
/* skip over caller save area and keep stack aligned to 16/32. */
stgu r1,-SF_ROUND(176)(r1)
LCFI1:
/* We want to build up an area for the parameters passed
in registers. (both floating point and integer) */
/* 176/256 bytes (callee stack frame aligned to 16/32)
24/48 bytes (caller linkage area)
200/304 (start of caller parameter area aligned to 4/8)
*/
/* Save GPRs 3 - 10 (aligned to 4/8)
in the parents outgoing area. */
stg r3,200(r1)
stg r4,204(r1)
stg r5,208(r1)
stg r6,212(r1)
stg r7,216(r1)
stg r8,220(r1)
stg r9,224(r1)
stg r10,228(r1)
/* Save FPRs 1 - 13. (aligned to 8) */
stfd f1,56(r1)
stfd f2,64(r1)
stfd f3,72(r1)
stfd f4,80(r1)
stfd f5,88(r1)
stfd f6,96(r1)
stfd f7,104(r1)
stfd f8,112(r1)
stfd f9,120(r1)
stfd f10,128(r1)
stfd f11,136(r1)
stfd f12,144(r1)
stfd f13,152(r1)
// Set up registers for the routine that actually does the work.
mr r3,r11 // context pointer from the trampoline
addi r4,r1,160 // result storage
addi r5,r1,200 // saved GPRs
addi r6,r1,56 // saved FPRs
bl Lffi_closure_helper_DARWIN$stub
/* Now r3 contains the return type. Use it to look up in a table
so we know how to deal with each type. */
addi r5,r1,160 // Copy result storage pointer.
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
mflr r4 // Move to r4.
slwi r3,r3,4 // Multiply return type by 16.
add r3,r3,r4 // Add contents of table to table address.
mtctr r3
bctr
LFE1:
/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
(4 instructions). For cache effectiveness we align to a 16 byte boundary
first. */
.align 4
nop
nop
nop
Lget_ret_type0_addr:
blrl
/* case FFI_TYPE_VOID */
Lret_type0:
b Lfinish
nop
nop
nop
/* case FFI_TYPE_INT */
Lret_type1:
lwz r3,0(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_FLOAT */
Lret_type2:
lfs f1,0(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_DOUBLE */
Lret_type3:
lfd f1,0(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_LONGDOUBLE */
Lret_type4:
lfd f1,0(r5)
lfd f2,8(r5)
b Lfinish
nop
/* case FFI_TYPE_UINT8 */
Lret_type5:
lbz r3,3(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_SINT8 */
Lret_type6:
lbz r3,3(r5)
extsb r3,r3
b Lfinish
nop
/* case FFI_TYPE_UINT16 */
Lret_type7:
lhz r3,2(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_SINT16 */
Lret_type8:
lha r3,2(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_UINT32 */
Lret_type9: // same as Lret_type1
lwz r3,0(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_SINT32 */
Lret_type10: // same as Lret_type1
lwz r3,0(r5)
b Lfinish
nop
nop
/* case FFI_TYPE_UINT64 */
Lret_type11:
lwz r3,0(r5)
lwz r4,4(r5)
b Lfinish
nop
/* case FFI_TYPE_SINT64 */
Lret_type12: // same as Lret_type11
lwz r3,0(r5)
lwz r4,4(r5)
b Lfinish
nop
/* case FFI_TYPE_STRUCT */
Lret_type13:
b Lfinish
nop
nop
nop
/* End 16-byte aligned cases */
/* case FFI_TYPE_POINTER */
// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
// are added in future, the following code will need to be updated and
// padded to 16 bytes.
Lret_type14:
lg r3,0(r5)
// fall through
/* case done */
Lfinish:
addi r1,r1,SF_ROUND(176) // Restore stack pointer.
lg r0,SF_RETURN(r1) // Restore return address.
mtlr r0 // Restore link register.
blr
/* END(ffi_closure_ASM) */
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0 ; Length of Common Information Entry
LSCIE1:
.long 0x0 ; CIE Identifier Tag
.byte 0x1 ; CIE Version
.ascii "zR\0" ; CIE Augmentation
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x10 ; FDE Encoding (pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
.align LOG2_GPR_BYTES
LECIE1:
.globl _ffi_closure_ASM.eh
_ffi_closure_ASM.eh:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1 ; FDE Length
LASFDE1:
.long LASFDE1-EH_frame1 ; FDE CIE offset
.g_long LFB1-. ; FDE initial location
.set L$set$3,LFE1-LFB1
.g_long L$set$3 ; FDE address range
.byte 0x0 ; uleb128 0x0; Augmentation size
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$3,LCFI1-LCFI0
.long L$set$3
.byte 0xe ; DW_CFA_def_cfa_offset
.byte 176,1 ; uleb128 176
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$4,LCFI0-LFB1
.long L$set$4
.byte 0x11 ; DW_CFA_offset_extended_sf
.byte 0x41 ; uleb128 0x41
.byte 0x7e ; sleb128 -2
.align LOG2_GPR_BYTES
LEFDE1:
.data
.align LOG2_GPR_BYTES
LDFCM0:
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align LOG2_GPR_BYTES
Lffi_closure_helper_DARWIN$stub:
.indirect_symbol _ffi_closure_helper_DARWIN
mflr r0
bcl 20,31,LO$ffi_closure_helper_DARWIN
LO$ffi_closure_helper_DARWIN:
mflr r11
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
mtlr r0
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_ffi_closure_helper_DARWIN$lazy_ptr:
.indirect_symbol _ffi_closure_helper_DARWIN
.g_long dyld_stub_binding_helper
#endif // __ppc__

File diff suppressed because it is too large Load Diff

View File

@ -1,418 +0,0 @@
#if defined(__ppc64__)
/* -----------------------------------------------------------------------
ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
Inc. based on ppc_closure.S
PowerPC Assembly glue.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <ffi.h>
#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE
#include <ppc-darwin.h>
#include <architecture/ppc/mode_independent_asm.h>
.file "ppc64-darwin_closure.S"
.text
.align LOG2_GPR_BYTES
.globl _ffi_closure_ASM
.text
.align LOG2_GPR_BYTES
_ffi_closure_ASM:
LFB1:
mflr r0
stg r0,SF_RETURN(r1) // save return address
// Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
stg r3,SF_ARG1(r1)
stg r4,SF_ARG2(r1)
stg r5,SF_ARG3(r1)
stg r6,SF_ARG4(r1)
stg r7,SF_ARG5(r1)
stg r8,SF_ARG6(r1)
stg r9,SF_ARG7(r1)
stg r10,SF_ARG8(r1)
LCFI0:
/* 48 bytes (Linkage Area)
64 bytes (outgoing parameter area, always reserved)
112 bytes (14*8 for incoming FPR)
? bytes (result)
112 bytes (14*8 for outgoing FPR)
16 bytes (2 saved registers)
352 + ? total bytes
*/
std r31,-8(r1) // Save registers we use.
std r30,-16(r1)
mr r30,r1 // Save the old SP.
mr r31,r11 // Save the ffi_closure around ffi64_data_size.
// Calculate the space we need.
stdu r1,-SF_MINSIZE(r1)
ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
ld r3,16(r3) // ffi_cif->rtype*
bl Lffi64_data_size$stub
ld r1,0(r1)
addi r3,r3,352 // Add our overhead.
neg r3,r3
li r0,-32 // Align to 32 bytes.
and r3,r3,r0
stdux r1,r1,r3 // Grow the stack.
mr r11,r31 // Copy the ffi_closure back.
LCFI1:
// We want to build up an area for the parameters passed
// in registers. (both floating point and integer)
/* 320 bytes (callee stack frame aligned to 32)
48 bytes (caller linkage area)
368 (start of caller parameter area aligned to 8)
*/
// Save FPRs 1 - 14. (aligned to 8)
stfd f1,112(r1)
stfd f2,120(r1)
stfd f3,128(r1)
stfd f4,136(r1)
stfd f5,144(r1)
stfd f6,152(r1)
stfd f7,160(r1)
stfd f8,168(r1)
stfd f9,176(r1)
stfd f10,184(r1)
stfd f11,192(r1)
stfd f12,200(r1)
stfd f13,208(r1)
stfd f14,216(r1)
// Set up registers for the routine that actually does the work.
mr r3,r11 // context pointer from the trampoline
addi r4,r1,224 // result storage
addi r5,r30,SF_ARG1 // saved GPRs
addi r6,r1,112 // saved FPRs
bl Lffi_closure_helper_DARWIN$stub
// Look the proper starting point in table
// by using return type as an offset.
addi r5,r1,224 // Get pointer to results area.
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
mflr r4 // Move to r4.
slwi r3,r3,4 // Now multiply return type by 16.
add r3,r3,r4 // Add contents of table to table address.
mtctr r3
bctr
LFE1:
// Each of the ret_typeX code fragments has to be exactly 16 bytes long
// (4 instructions). For cache effectiveness we align to a 16 byte
// boundary first.
.align 4
nop
nop
nop
Lget_ret_type0_addr:
blrl
// case FFI_TYPE_VOID
Lret_type0:
b Lfinish
nop
nop
nop
// case FFI_TYPE_INT
Lret_type1:
lwz r3,4(r5)
b Lfinish
nop
nop
// case FFI_TYPE_FLOAT
Lret_type2:
lfs f1,0(r5)
b Lfinish
nop
nop
// case FFI_TYPE_DOUBLE
Lret_type3:
lfd f1,0(r5)
b Lfinish
nop
nop
// case FFI_TYPE_LONGDOUBLE
Lret_type4:
lfd f1,0(r5)
lfd f2,8(r5)
b Lfinish
nop
// case FFI_TYPE_UINT8
Lret_type5:
lbz r3,7(r5)
b Lfinish
nop
nop
// case FFI_TYPE_SINT8
Lret_type6:
lbz r3,7(r5)
extsb r3,r3
b Lfinish
nop
// case FFI_TYPE_UINT16
Lret_type7:
lhz r3,6(r5)
b Lfinish
nop
nop
// case FFI_TYPE_SINT16
Lret_type8:
lha r3,6(r5)
b Lfinish
nop
nop
// case FFI_TYPE_UINT32
Lret_type9: // same as Lret_type1
lwz r3,4(r5)
b Lfinish
nop
nop
// case FFI_TYPE_SINT32
Lret_type10: // same as Lret_type1
lwz r3,4(r5)
b Lfinish
nop
nop
// case FFI_TYPE_UINT64
Lret_type11:
ld r3,0(r5)
b Lfinish
nop
nop
// case FFI_TYPE_SINT64
Lret_type12: // same as Lret_type11
ld r3,0(r5)
b Lfinish
nop
nop
// case FFI_TYPE_STRUCT
Lret_type13:
b Lret_struct
nop
nop
nop
// ** End 16-byte aligned cases **
// case FFI_TYPE_POINTER
// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
// are added in future, the following code will need to be updated and
// padded to 16 bytes.
Lret_type14:
lg r3,0(r5)
b Lfinish
// copy struct into registers
Lret_struct:
ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
ld r3,16(r31) // ffi_cif->rtype*
ld r31,24(r31) // ffi_cif->flags
mr r4,r5 // copy struct* to 2nd arg
addi r7,r1,SF_ARG9 // GPR return area
addi r9,r30,-16-(14*8) // FPR return area
li r5,0 // struct offset ptr (NULL)
li r6,0 // FPR used count ptr (NULL)
li r8,0 // GPR return area size ptr (NULL)
li r10,0 // FPR return area size ptr (NULL)
bl Lffi64_struct_to_reg_form$stub
// Load GPRs
ld r3,SF_ARG9(r1)
ld r4,SF_ARG10(r1)
ld r5,SF_ARG11(r1)
ld r6,SF_ARG12(r1)
nop
ld r7,SF_ARG13(r1)
ld r8,SF_ARG14(r1)
ld r9,SF_ARG15(r1)
ld r10,SF_ARG16(r1)
nop
// Load FPRs
mtcrf 0x2,r31
bf 26,Lfinish
lfd f1,-16-(14*8)(r30)
lfd f2,-16-(13*8)(r30)
lfd f3,-16-(12*8)(r30)
lfd f4,-16-(11*8)(r30)
nop
lfd f5,-16-(10*8)(r30)
lfd f6,-16-(9*8)(r30)
lfd f7,-16-(8*8)(r30)
lfd f8,-16-(7*8)(r30)
nop
lfd f9,-16-(6*8)(r30)
lfd f10,-16-(5*8)(r30)
lfd f11,-16-(4*8)(r30)
lfd f12,-16-(3*8)(r30)
nop
lfd f13,-16-(2*8)(r30)
lfd f14,-16-(1*8)(r30)
// Fall through
// case done
Lfinish:
lg r1,0(r1) // Restore stack pointer.
ld r31,-8(r1) // Restore registers we used.
ld r30,-16(r1)
lg r0,SF_RETURN(r1) // Get return address.
mtlr r0 // Reset link register.
blr
// END(ffi_closure_ASM)
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0 ; Length of Common Information Entry
LSCIE1:
.long 0x0 ; CIE Identifier Tag
.byte 0x1 ; CIE Version
.ascii "zR\0" ; CIE Augmentation
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x10 ; FDE Encoding (pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
.align LOG2_GPR_BYTES
LECIE1:
.globl _ffi_closure_ASM.eh
_ffi_closure_ASM.eh:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1 ; FDE Length
LASFDE1:
.long LASFDE1-EH_frame1 ; FDE CIE offset
.g_long LFB1-. ; FDE initial location
.set L$set$3,LFE1-LFB1
.g_long L$set$3 ; FDE address range
.byte 0x0 ; uleb128 0x0; Augmentation size
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$3,LCFI1-LCFI0
.long L$set$3
.byte 0xe ; DW_CFA_def_cfa_offset
.byte 176,1 ; uleb128 176
.byte 0x4 ; DW_CFA_advance_loc4
.set L$set$4,LCFI0-LFB1
.long L$set$4
.byte 0x11 ; DW_CFA_offset_extended_sf
.byte 0x41 ; uleb128 0x41
.byte 0x7e ; sleb128 -2
.align LOG2_GPR_BYTES
LEFDE1:
.data
.align LOG2_GPR_BYTES
LDFCM0:
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align LOG2_GPR_BYTES
Lffi_closure_helper_DARWIN$stub:
.indirect_symbol _ffi_closure_helper_DARWIN
mflr r0
bcl 20,31,LO$ffi_closure_helper_DARWIN
LO$ffi_closure_helper_DARWIN:
mflr r11
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
mtlr r0
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_ffi_closure_helper_DARWIN$lazy_ptr:
.indirect_symbol _ffi_closure_helper_DARWIN
.g_long dyld_stub_binding_helper
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align LOG2_GPR_BYTES
Lffi64_struct_to_reg_form$stub:
.indirect_symbol _ffi64_struct_to_reg_form
mflr r0
bcl 20,31,LO$ffi64_struct_to_reg_form
LO$ffi64_struct_to_reg_form:
mflr r11
addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
mtlr r0
lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
mtctr r12
bctr
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
.align LOG2_GPR_BYTES
Lffi64_data_size$stub:
.indirect_symbol _ffi64_data_size
mflr r0
bcl 20,31,LO$ffi64_data_size
LO$ffi64_data_size:
mflr r11
addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
mtlr r0
lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
mtctr r12
bctr
.lazy_symbol_pointer
L_ffi64_struct_to_reg_form$lazy_ptr:
.indirect_symbol _ffi64_struct_to_reg_form
.g_long dyld_stub_binding_helper
L_ffi64_data_size$lazy_ptr:
.indirect_symbol _ffi64_data_size
.g_long dyld_stub_binding_helper
#endif // __ppc64__

View File

@ -1,115 +0,0 @@
/* -----------------------------------------------------------------------
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Predefined ffi_types needed by libffi.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
/* Type definitions */
#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \
ffi_type ffi_type_##n = { s, a, t, NULL }
#define FFI_AGGREGATE_TYPEDEF(n, e) \
ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
/* Size and alignment are fake here. They must not be 0. */
FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
#if defined ALPHA || defined SPARC64 || defined X86_64 || \
defined S390X || defined IA64 || defined POWERPC64
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
#else
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
#endif
#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN)
# ifdef X86_64
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
# else
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
# endif
#elif defined(POWERPC_DARWIN)
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
#elif defined SH
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
#else
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
#endif
#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN)
# if defined X86_WIN32 || defined X86_64
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
# else
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
# endif
# ifdef X86_DARWIN
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
# else
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
# endif
#elif defined ARM || defined SH || defined POWERPC_AIX
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
#elif defined POWERPC_DARWIN
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
# if __GNUC__ >= 4
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
# else
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
# endif
#elif defined SPARC
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
# ifdef SPARC64
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
# else
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
# endif
#elif defined X86_64 || defined POWERPC64
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
#else
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
#endif

View File

@ -1,417 +0,0 @@
/* -----------------------------------------------------------------------
darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc.
derived from unix64.S
x86-64 Foreign Function Interface for Darwin.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifdef __x86_64__
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
.file "darwin64.S"
.text
/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
void *raddr, void (*fnaddr)());
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
for this function. This has been allocated by ffi_call. We also
deallocate some of the stack that has been alloca'd. */
.align 3
.globl _ffi_call_unix64
_ffi_call_unix64:
LUW0:
movq (%rsp), %r10 /* Load return address. */
movq %rdi, %r12 /* Save a copy of the register area. */
leaq (%rdi, %rsi), %rax /* Find local stack base. */
movq %rdx, (%rax) /* Save flags. */
movq %rcx, 8(%rax) /* Save raddr. */
movq %rbp, 16(%rax) /* Save old frame pointer. */
movq %r10, 24(%rax) /* Relocate return address. */
movq %rax, %rbp /* Finalize local stack frame. */
LUW1:
/* movq %rdi, %r10 // Save a copy of the register area. */
movq %r12, %r10
movq %r8, %r11 /* Save a copy of the target fn. */
movl %r9d, %eax /* Set number of SSE registers. */
/* Load up all argument registers. */
movq (%r10), %rdi
movq 8(%r10), %rsi
movq 16(%r10), %rdx
movq 24(%r10), %rcx
movq 32(%r10), %r8
movq 40(%r10), %r9
testl %eax, %eax
jnz Lload_sse
Lret_from_load_sse:
/* Deallocate the reg arg area. */
leaq 176(%r10), %rsp
/* Call the user function. */
call *%r11
/* Deallocate stack arg area; local stack frame in redzone. */
leaq 24(%rbp), %rsp
movq 0(%rbp), %rcx /* Reload flags. */
movq 8(%rbp), %rdi /* Reload raddr. */
movq 16(%rbp), %rbp /* Reload old frame pointer. */
LUW2:
/* The first byte of the flags contains the FFI_TYPE. */
movzbl %cl, %r10d
leaq Lstore_table(%rip), %r11
movslq (%r11, %r10, 4), %r10
addq %r11, %r10
jmp *%r10
Lstore_table:
.long Lst_void-Lstore_table /* FFI_TYPE_VOID */
.long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
.long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
.long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
.long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
.long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
.long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
.long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
.long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
.long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
.long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
.long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
.long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
.long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
.long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
.text
.align 3
Lst_void:
ret
.align 3
Lst_uint8:
movzbq %al, %rax
movq %rax, (%rdi)
ret
.align 3
Lst_sint8:
movsbq %al, %rax
movq %rax, (%rdi)
ret
.align 3
Lst_uint16:
movzwq %ax, %rax
movq %rax, (%rdi)
.align 3
Lst_sint16:
movswq %ax, %rax
movq %rax, (%rdi)
ret
.align 3
Lst_uint32:
movl %eax, %eax
movq %rax, (%rdi)
.align 3
Lst_sint32:
cltq
movq %rax, (%rdi)
ret
.align 3
Lst_int64:
movq %rax, (%rdi)
ret
.align 3
Lst_float:
movss %xmm0, (%rdi)
ret
.align 3
Lst_double:
movsd %xmm0, (%rdi)
ret
Lst_ldouble:
fstpt (%rdi)
ret
.align 3
Lst_struct:
leaq -20(%rsp), %rsi /* Scratch area in redzone. */
/* We have to locate the values now, and since we don't want to
write too much data into the user's return value, we spill the
value to a 16 byte scratch area first. Bits 8, 9, and 10
control where the values are located. Only one of the three
bits will be set; see ffi_prep_cif_machdep for the pattern. */
movd %xmm0, %r10
movd %xmm1, %r11
testl $0x100, %ecx
cmovnz %rax, %rdx
cmovnz %r10, %rax
testl $0x200, %ecx
cmovnz %r10, %rdx
testl $0x400, %ecx
cmovnz %r10, %rax
cmovnz %r11, %rdx
movq %rax, (%rsi)
movq %rdx, 8(%rsi)
/* Bits 12-31 contain the true size of the structure. Copy from
the scratch area to the true destination. */
shrl $12, %ecx
rep movsb
ret
/* Many times we can avoid loading any SSE registers at all.
It's not worth an indirect jump to load the exact set of
SSE registers needed; zero or all is a good compromise. */
.align 3
LUW3:
Lload_sse:
movdqa 48(%r10), %xmm0
movdqa 64(%r10), %xmm1
movdqa 80(%r10), %xmm2
movdqa 96(%r10), %xmm3
movdqa 112(%r10), %xmm4
movdqa 128(%r10), %xmm5
movdqa 144(%r10), %xmm6
movdqa 160(%r10), %xmm7
jmp Lret_from_load_sse
LUW4:
.align 3
.globl _ffi_closure_unix64
_ffi_closure_unix64:
LUW5:
/* The carry flag is set by the trampoline iff SSE registers
are used. Don't clobber it before the branch instruction. */
leaq -200(%rsp), %rsp
LUW6:
movq %rdi, (%rsp)
movq %rsi, 8(%rsp)
movq %rdx, 16(%rsp)
movq %rcx, 24(%rsp)
movq %r8, 32(%rsp)
movq %r9, 40(%rsp)
jc Lsave_sse
Lret_from_save_sse:
movq %r10, %rdi
leaq 176(%rsp), %rsi
movq %rsp, %rdx
leaq 208(%rsp), %rcx
call _ffi_closure_unix64_inner
/* Deallocate stack frame early; return value is now in redzone. */
addq $200, %rsp
LUW7:
/* The first byte of the return value contains the FFI_TYPE. */
movzbl %al, %r10d
leaq Lload_table(%rip), %r11
movslq (%r11, %r10, 4), %r10
addq %r11, %r10
jmp *%r10
Lload_table:
.long Lld_void-Lload_table /* FFI_TYPE_VOID */
.long Lld_int32-Lload_table /* FFI_TYPE_INT */
.long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
.long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
.long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
.long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
.long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
.long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
.long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
.long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
.long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
.long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
.long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
.long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
.long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
.text
.align 3
Lld_void:
ret
.align 3
Lld_int8:
movzbl -24(%rsp), %eax
ret
.align 3
Lld_int16:
movzwl -24(%rsp), %eax
ret
.align 3
Lld_int32:
movl -24(%rsp), %eax
ret
.align 3
Lld_int64:
movq -24(%rsp), %rax
ret
.align 3
Lld_float:
movss -24(%rsp), %xmm0
ret
.align 3
Lld_double:
movsd -24(%rsp), %xmm0
ret
.align 3
Lld_ldouble:
fldt -24(%rsp)
ret
.align 3
Lld_struct:
/* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
%rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
both rdx and xmm1 with the second word. For the remaining,
bit 8 set means xmm0 gets the second word, and bit 9 means
that rax gets the second word. */
movq -24(%rsp), %rcx
movq -16(%rsp), %rdx
movq -16(%rsp), %xmm1
testl $0x100, %eax
cmovnz %rdx, %rcx
movd %rcx, %xmm0
testl $0x200, %eax
movq -24(%rsp), %rax
cmovnz %rdx, %rax
ret
/* See the comment above Lload_sse; the same logic applies here. */
.align 3
LUW8:
Lsave_sse:
movdqa %xmm0, 48(%rsp)
movdqa %xmm1, 64(%rsp)
movdqa %xmm2, 80(%rsp)
movdqa %xmm3, 96(%rsp)
movdqa %xmm4, 112(%rsp)
movdqa %xmm5, 128(%rsp)
movdqa %xmm6, 144(%rsp)
movdqa %xmm7, 160(%rsp)
jmp Lret_from_save_sse
LUW9:
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1 /* CIE Length */
.long L$set$0
LSCIE1:
.long 0x0 /* CIE Identifier Tag */
.byte 0x1 /* CIE Version */
.ascii "zR\0" /* CIE Augmentation */
.byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
.byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
.byte 0x10 /* CIE RA Column */
.byte 0x1 /* uleb128 0x1; Augmentation size */
.byte 0x10 /* FDE Encoding (pcrel sdata4) */
.byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
.byte 0x7 /* uleb128 0x7 */
.byte 0x8 /* uleb128 0x8 */
.byte 0x90 /* DW_CFA_offset, column 0x10 */
.byte 0x1
.align 3
LECIE1:
.globl _ffi_call_unix64.eh
_ffi_call_unix64.eh:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
.long L$set$1
LASFDE1:
.long LASFDE1-EH_frame1 /* FDE CIE offset */
.quad LUW0-. /* FDE initial location */
.set L$set$2,LUW4-LUW0 /* FDE address range */
.quad L$set$2
.byte 0x0 /* Augmentation size */
.byte 0x4 /* DW_CFA_advance_loc4 */
.set L$set$3,LUW1-LUW0
.long L$set$3
/* New stack frame based off rbp. This is an itty bit of unwind
trickery in that the CFA *has* changed. There is no easy way
to describe it correctly on entry to the function. Fortunately,
it doesn't matter too much since at all points we can correctly
unwind back to ffi_call. Note that the location to which we
moved the return address is (the new) CFA-8, so from the
perspective of the unwind info, it hasn't moved. */
.byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */
.byte 0x6
.byte 0x20
.byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */
.byte 0x2
.byte 0xa /* DW_CFA_remember_state */
.byte 0x4 /* DW_CFA_advance_loc4 */
.set L$set$4,LUW2-LUW1
.long L$set$4
.byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
.byte 0x7
.byte 0x8
.byte 0xc0+6 /* DW_CFA_restore, %rbp */
.byte 0x4 /* DW_CFA_advance_loc4 */
.set L$set$5,LUW3-LUW2
.long L$set$5
.byte 0xb /* DW_CFA_restore_state */
.align 3
LEFDE1:
.globl _ffi_closure_unix64.eh
_ffi_closure_unix64.eh:
LSFDE3:
.set L$set$6,LEFDE3-LASFDE3 /* FDE Length */
.long L$set$6
LASFDE3:
.long LASFDE3-EH_frame1 /* FDE CIE offset */
.quad LUW5-. /* FDE initial location */
.set L$set$7,LUW9-LUW5 /* FDE address range */
.quad L$set$7
.byte 0x0 /* Augmentation size */
.byte 0x4 /* DW_CFA_advance_loc4 */
.set L$set$8,LUW6-LUW5
.long L$set$8
.byte 0xe /* DW_CFA_def_cfa_offset */
.byte 208,1 /* uleb128 208 */
.byte 0xa /* DW_CFA_remember_state */
.byte 0x4 /* DW_CFA_advance_loc4 */
.set L$set$9,LUW7-LUW6
.long L$set$9
.byte 0xe /* DW_CFA_def_cfa_offset */
.byte 0x8
.byte 0x4 /* DW_CFA_advance_loc4 */
.set L$set$10,LUW8-LUW7
.long L$set$10
.byte 0xb /* DW_CFA_restore_state */
.align 3
LEFDE3:
.subsections_via_symbols
#endif /* __x86_64__ */

View File

@ -1,422 +0,0 @@
#ifdef __i386__
/* -----------------------------------------------------------------------
darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc.
X86 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/*
* This file is based on sysv.S and then hacked up by Ronald who hasn't done
* assembly programming in 8 years.
*/
#ifndef __x86_64__
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#ifdef PyObjC_STRICT_DEBUGGING
/* XXX: Debugging of stack alignment, to be removed */
#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
#else
#define ASSERT_STACK_ALIGNED
#endif
.text
.globl _ffi_prep_args
.align 4
.globl _ffi_call_SYSV
_ffi_call_SYSV:
LFB1:
pushl %ebp
LCFI0:
movl %esp,%ebp
LCFI1:
subl $8,%esp
/* Make room for all of the new args. */
movl 16(%ebp),%ecx
subl %ecx,%esp
movl %esp,%eax
/* Place all of the ffi_prep_args in position */
subl $8,%esp
pushl 12(%ebp)
pushl %eax
call *8(%ebp)
/* Return stack to previous state and call the function */
addl $16,%esp
call *28(%ebp)
/* Remove the space we pushed for the args */
movl 16(%ebp),%ecx
addl %ecx,%esp
/* Load %ecx with the return type code */
movl 20(%ebp),%ecx
/* If the return value pointer is NULL, assume no return value. */
cmpl $0,24(%ebp)
jne Lretint
/* Even if there is no space for the return value, we are
obliged to handle floating-point values. */
cmpl $FFI_TYPE_FLOAT,%ecx
jne Lnoretval
fstp %st(0)
jmp Lepilogue
Lretint:
cmpl $FFI_TYPE_INT,%ecx
jne Lretfloat
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
jmp Lepilogue
Lretfloat:
cmpl $FFI_TYPE_FLOAT,%ecx
jne Lretdouble
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
fstps (%ecx)
jmp Lepilogue
Lretdouble:
cmpl $FFI_TYPE_DOUBLE,%ecx
jne Lretlongdouble
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
fstpl (%ecx)
jmp Lepilogue
Lretlongdouble:
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
jne Lretint64
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
fstpt (%ecx)
jmp Lepilogue
Lretint64:
cmpl $FFI_TYPE_SINT64,%ecx
jne Lretstruct1b
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
movl %edx,4(%ecx)
jmp Lepilogue
Lretstruct1b:
cmpl $FFI_TYPE_SINT8,%ecx
jne Lretstruct2b
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
movb %al,0(%ecx)
jmp Lepilogue
Lretstruct2b:
cmpl $FFI_TYPE_SINT16,%ecx
jne Lretstruct
/* Load %ecx with the pointer to storage for the return value */
movl 24(%ebp),%ecx
movw %ax,0(%ecx)
jmp Lepilogue
Lretstruct:
cmpl $FFI_TYPE_STRUCT,%ecx
jne Lnoretval
/* Nothing to do! */
addl $4,%esp
popl %ebp
ret
Lnoretval:
Lepilogue:
addl $8,%esp
movl %ebp,%esp
popl %ebp
ret
LFE1:
.ffi_call_SYSV_end:
.align 4
FFI_HIDDEN (ffi_closure_SYSV)
.globl _ffi_closure_SYSV
_ffi_closure_SYSV:
LFB2:
pushl %ebp
LCFI2:
movl %esp, %ebp
LCFI3:
subl $56, %esp
leal -40(%ebp), %edx
movl %edx, -12(%ebp) /* resp */
leal 8(%ebp), %edx
movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
leal -12(%ebp), %edx
movl %edx, (%esp) /* &resp */
movl %ebx, 8(%esp)
LCFI7:
call L_ffi_closure_SYSV_inner$stub
movl 8(%esp), %ebx
movl -12(%ebp), %ecx
cmpl $FFI_TYPE_INT, %eax
je Lcls_retint
cmpl $FFI_TYPE_FLOAT, %eax
je Lcls_retfloat
cmpl $FFI_TYPE_DOUBLE, %eax
je Lcls_retdouble
cmpl $FFI_TYPE_LONGDOUBLE, %eax
je Lcls_retldouble
cmpl $FFI_TYPE_SINT64, %eax
je Lcls_retllong
cmpl $FFI_TYPE_UINT8, %eax
je Lcls_retstruct1
cmpl $FFI_TYPE_SINT8, %eax
je Lcls_retstruct1
cmpl $FFI_TYPE_UINT16, %eax
je Lcls_retstruct2
cmpl $FFI_TYPE_SINT16, %eax
je Lcls_retstruct2
cmpl $FFI_TYPE_STRUCT, %eax
je Lcls_retstruct
Lcls_epilogue:
movl %ebp, %esp
popl %ebp
ret
Lcls_retint:
movl (%ecx), %eax
jmp Lcls_epilogue
Lcls_retfloat:
flds (%ecx)
jmp Lcls_epilogue
Lcls_retdouble:
fldl (%ecx)
jmp Lcls_epilogue
Lcls_retldouble:
fldt (%ecx)
jmp Lcls_epilogue
Lcls_retllong:
movl (%ecx), %eax
movl 4(%ecx), %edx
jmp Lcls_epilogue
Lcls_retstruct1:
movsbl (%ecx), %eax
jmp Lcls_epilogue
Lcls_retstruct2:
movswl (%ecx), %eax
jmp Lcls_epilogue
Lcls_retstruct:
lea -8(%ebp),%esp
movl %ebp, %esp
popl %ebp
ret $4
LFE2:
#if !FFI_NO_RAW_API
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
.align 4
FFI_HIDDEN (ffi_closure_raw_SYSV)
.globl _ffi_closure_raw_SYSV
_ffi_closure_raw_SYSV:
LFB3:
pushl %ebp
LCFI4:
movl %esp, %ebp
LCFI5:
pushl %esi
LCFI6:
subl $36, %esp
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
movl %edx, 12(%esp) /* user_data */
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
movl %edx, 8(%esp) /* raw_args */
leal -24(%ebp), %edx
movl %edx, 4(%esp) /* &res */
movl %esi, (%esp) /* cif */
call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
cmpl $FFI_TYPE_INT, %eax
je Lrcls_retint
cmpl $FFI_TYPE_FLOAT, %eax
je Lrcls_retfloat
cmpl $FFI_TYPE_DOUBLE, %eax
je Lrcls_retdouble
cmpl $FFI_TYPE_LONGDOUBLE, %eax
je Lrcls_retldouble
cmpl $FFI_TYPE_SINT64, %eax
je Lrcls_retllong
Lrcls_epilogue:
addl $36, %esp
popl %esi
popl %ebp
ret
Lrcls_retint:
movl -24(%ebp), %eax
jmp Lrcls_epilogue
Lrcls_retfloat:
flds -24(%ebp)
jmp Lrcls_epilogue
Lrcls_retdouble:
fldl -24(%ebp)
jmp Lrcls_epilogue
Lrcls_retldouble:
fldt -24(%ebp)
jmp Lrcls_epilogue
Lrcls_retllong:
movl -24(%ebp), %eax
movl -20(%ebp), %edx
jmp Lrcls_epilogue
LFE3:
#endif
.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
L_ffi_closure_SYSV_inner$stub:
.indirect_symbol _ffi_closure_SYSV_inner
hlt ; hlt ; hlt ; hlt ; hlt
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0
LSCIE1:
.long 0x0
.byte 0x1
.ascii "zR\0"
.byte 0x1
.byte 0x7c
.byte 0x8
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x5
.byte 0x4
.byte 0x88
.byte 0x1
.align 2
LECIE1:
.globl _ffi_call_SYSV.eh
_ffi_call_SYSV.eh:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1
LASFDE1:
.long LASFDE1-EH_frame1
.long LFB1-.
.set L$set$2,LFE1-LFB1
.long L$set$2
.byte 0x0
.byte 0x4
.set L$set$3,LCFI0-LFB1
.long L$set$3
.byte 0xe
.byte 0x8
.byte 0x84
.byte 0x2
.byte 0x4
.set L$set$4,LCFI1-LCFI0
.long L$set$4
.byte 0xd
.byte 0x4
.align 2
LEFDE1:
.globl _ffi_closure_SYSV.eh
_ffi_closure_SYSV.eh:
LSFDE2:
.set L$set$5,LEFDE2-LASFDE2
.long L$set$5
LASFDE2:
.long LASFDE2-EH_frame1
.long LFB2-.
.set L$set$6,LFE2-LFB2
.long L$set$6
.byte 0x0
.byte 0x4
.set L$set$7,LCFI2-LFB2
.long L$set$7
.byte 0xe
.byte 0x8
.byte 0x84
.byte 0x2
.byte 0x4
.set L$set$8,LCFI3-LCFI2
.long L$set$8
.byte 0xd
.byte 0x4
.align 2
LEFDE2:
#if !FFI_NO_RAW_API
.globl _ffi_closure_raw_SYSV.eh
_ffi_closure_raw_SYSV.eh:
LSFDE3:
.set L$set$10,LEFDE3-LASFDE3
.long L$set$10
LASFDE3:
.long LASFDE3-EH_frame1
.long LFB3-.
.set L$set$11,LFE3-LFB3
.long L$set$11
.byte 0x0
.byte 0x4
.set L$set$12,LCFI4-LFB3
.long L$set$12
.byte 0xe
.byte 0x8
.byte 0x84
.byte 0x2
.byte 0x4
.set L$set$13,LCFI5-LCFI4
.long L$set$13
.byte 0xd
.byte 0x4
.byte 0x4
.set L$set$14,LCFI6-LCFI5
.long L$set$14
.byte 0x85
.byte 0x3
.align 2
LEFDE3:
#endif
#endif /* ifndef __x86_64__ */
#endif /* defined __i386__ */

View File

@ -1,737 +0,0 @@
#ifdef __x86_64__
/* -----------------------------------------------------------------------
x86-ffi64.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
x86-64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdarg.h>
#define MAX_GPR_REGS 6
#define MAX_SSE_REGS 8
typedef struct RegisterArgs {
/* Registers for argument passing. */
UINT64 gpr[MAX_GPR_REGS];
__int128_t sse[MAX_SSE_REGS];
} RegisterArgs;
extern void
ffi_call_unix64(
void* args,
unsigned long bytes,
unsigned flags,
void* raddr,
void (*fnaddr)(void),
unsigned ssecount);
/* All reference to register classes here is identical to the code in
gcc/config/i386/i386.c. Do *not* change one without the other. */
/* Register class used for passing given 64bit part of the argument.
These represent classes as documented by the PS ABI, with the exception
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
use SF or DFmode move instead of DImode to avoid reformating penalties.
Similarly we play games with INTEGERSI_CLASS to use cheaper SImode moves
whenever possible (upper half does contain padding). */
enum x86_64_reg_class
{
X86_64_NO_CLASS,
X86_64_INTEGER_CLASS,
X86_64_INTEGERSI_CLASS,
X86_64_SSE_CLASS,
X86_64_SSESF_CLASS,
X86_64_SSEDF_CLASS,
X86_64_SSEUP_CLASS,
X86_64_X87_CLASS,
X86_64_X87UP_CLASS,
X86_64_COMPLEX_X87_CLASS,
X86_64_MEMORY_CLASS
};
#define MAX_CLASSES 4
#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
of this code is to classify each 8bytes of incoming argument by the register
class and assign registers accordingly. */
/* Return the union class of CLASS1 and CLASS2.
See the x86-64 PS ABI for details. */
static enum x86_64_reg_class
merge_classes(
enum x86_64_reg_class class1,
enum x86_64_reg_class class2)
{
/* Rule #1: If both classes are equal, this is the resulting class. */
if (class1 == class2)
return class1;
/* Rule #2: If one of the classes is NO_CLASS, the resulting class is
the other class. */
if (class1 == X86_64_NO_CLASS)
return class2;
if (class2 == X86_64_NO_CLASS)
return class1;
/* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
return X86_64_MEMORY_CLASS;
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
|| (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
return X86_64_INTEGERSI_CLASS;
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
return X86_64_INTEGER_CLASS;
/* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
MEMORY is used. */
if (class1 == X86_64_X87_CLASS
|| class1 == X86_64_X87UP_CLASS
|| class1 == X86_64_COMPLEX_X87_CLASS
|| class2 == X86_64_X87_CLASS
|| class2 == X86_64_X87UP_CLASS
|| class2 == X86_64_COMPLEX_X87_CLASS)
return X86_64_MEMORY_CLASS;
/* Rule #6: Otherwise class SSE is used. */
return X86_64_SSE_CLASS;
}
/* Classify the argument of type TYPE and mode MODE.
CLASSES will be filled by the register class used to pass each word
of the operand. The number of words is returned. In case the parameter
should be passed in memory, 0 is returned. As a special case for zero
sized containers, classes[0] will be NO_CLASS and 1 is returned.
See the x86-64 PS ABI for details. */
static int
classify_argument(
ffi_type* type,
enum x86_64_reg_class classes[],
size_t byte_offset)
{
switch (type->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_POINTER:
#if 0
if (byte_offset + type->size <= 4)
classes[0] = X86_64_INTEGERSI_CLASS;
else
classes[0] = X86_64_INTEGER_CLASS;
return 1;
#else
{
int size = byte_offset + type->size;
if (size <= 4)
{
classes[0] = X86_64_INTEGERSI_CLASS;
return 1;
}
else if (size <= 8)
{
classes[0] = X86_64_INTEGER_CLASS;
return 1;
}
else if (size <= 12)
{
classes[0] = X86_64_INTEGER_CLASS;
classes[1] = X86_64_INTEGERSI_CLASS;
return 2;
}
else if (size <= 16)
{
classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
return 2;
}
else
FFI_ASSERT (0);
}
#endif
case FFI_TYPE_FLOAT:
if (byte_offset == 0)
classes[0] = X86_64_SSESF_CLASS;
else
classes[0] = X86_64_SSE_CLASS;
return 1;
case FFI_TYPE_DOUBLE:
classes[0] = X86_64_SSEDF_CLASS;
return 1;
case FFI_TYPE_LONGDOUBLE:
classes[0] = X86_64_X87_CLASS;
classes[1] = X86_64_X87UP_CLASS;
return 2;
case FFI_TYPE_STRUCT:
{
ffi_type** ptr;
int i;
enum x86_64_reg_class subclasses[MAX_CLASSES];
const int UNITS_PER_WORD = 8;
int words =
(type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
/* If the struct is larger than 16 bytes, pass it on the stack. */
if (type->size > 16)
return 0;
for (i = 0; i < words; i++)
classes[i] = X86_64_NO_CLASS;
/* Merge the fields of structure. */
for (ptr = type->elements; *ptr != NULL; ptr++)
{
int num, pos;
byte_offset = ALIGN(byte_offset, (*ptr)->alignment);
num = classify_argument(*ptr, subclasses, byte_offset % 8);
if (num == 0)
return 0;
pos = byte_offset / 8;
for (i = 0; i < num; i++)
{
classes[i + pos] =
merge_classes(subclasses[i], classes[i + pos]);
}
byte_offset += (*ptr)->size;
}
if (words > 2)
{
/* When size > 16 bytes, if the first one isn't
X86_64_SSE_CLASS or any other ones aren't
X86_64_SSEUP_CLASS, everything should be passed in
memory. */
if (classes[0] != X86_64_SSE_CLASS)
return 0;
for (i = 1; i < words; i++)
if (classes[i] != X86_64_SSEUP_CLASS)
return 0;
}
/* Final merger cleanup. */
for (i = 0; i < words; i++)
{
/* If one class is MEMORY, everything should be passed in
memory. */
if (classes[i] == X86_64_MEMORY_CLASS)
return 0;
/* The X86_64_SSEUP_CLASS should be always preceded by
X86_64_SSE_CLASS. */
if (classes[i] == X86_64_SSEUP_CLASS
&& classes[i - 1] != X86_64_SSE_CLASS
&& classes[i - 1] != X86_64_SSEUP_CLASS)
{
FFI_ASSERT(i != 0);
classes[i] = X86_64_SSE_CLASS;
}
/* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
if (classes[i] == X86_64_X87UP_CLASS
&& classes[i - 1] != X86_64_X87_CLASS)
{
FFI_ASSERT(i != 0);
classes[i] = X86_64_SSE_CLASS;
}
}
return words;
}
default:
FFI_ASSERT(0);
}
return 0; /* Never reached. */
}
/* Examine the argument and return set number of register required in each
class. Return zero if parameter should be passed in memory, otherwise
the number of registers. */
static int
examine_argument(
ffi_type* type,
enum x86_64_reg_class classes[MAX_CLASSES],
_Bool in_return,
int* pngpr,
int* pnsse)
{
int n = classify_argument(type, classes, 0);
int ngpr = 0;
int nsse = 0;
int i;
if (n == 0)
return 0;
for (i = 0; i < n; ++i)
{
switch (classes[i])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
ngpr++;
break;
case X86_64_SSE_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSEDF_CLASS:
nsse++;
break;
case X86_64_NO_CLASS:
case X86_64_SSEUP_CLASS:
break;
case X86_64_X87_CLASS:
case X86_64_X87UP_CLASS:
case X86_64_COMPLEX_X87_CLASS:
return in_return != 0;
default:
abort();
}
}
*pngpr = ngpr;
*pnsse = nsse;
return n;
}
/* Perform machine dependent cif processing. */
ffi_status
ffi_prep_cif_machdep(
ffi_cif* cif)
{
int gprcount = 0;
int ssecount = 0;
int flags = cif->rtype->type;
int i, avn, n, ngpr, nsse;
enum x86_64_reg_class classes[MAX_CLASSES];
size_t bytes;
if (flags != FFI_TYPE_VOID)
{
n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
if (n == 0)
{
/* The return value is passed in memory. A pointer to that
memory is the first argument. Allocate a register for it. */
gprcount++;
/* We don't have to do anything in asm for the return. */
flags = FFI_TYPE_VOID;
}
else if (flags == FFI_TYPE_STRUCT)
{
/* Mark which registers the result appears in. */
_Bool sse0 = SSE_CLASS_P(classes[0]);
_Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
if (sse0 && !sse1)
flags |= 1 << 8;
else if (!sse0 && sse1)
flags |= 1 << 9;
else if (sse0 && sse1)
flags |= 1 << 10;
/* Mark the true size of the structure. */
flags |= cif->rtype->size << 12;
}
}
/* Go over all arguments and determine the way they should be passed.
If it's in a register and there is space for it, let that be so. If
not, add it's size to the stack byte count. */
for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
{
if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
|| gprcount + ngpr > MAX_GPR_REGS
|| ssecount + nsse > MAX_SSE_REGS)
{
long align = cif->arg_types[i]->alignment;
if (align < 8)
align = 8;
bytes = ALIGN(bytes, align);
bytes += cif->arg_types[i]->size;
}
else
{
gprcount += ngpr;
ssecount += nsse;
}
}
if (ssecount)
flags |= 1 << 11;
cif->flags = flags;
cif->bytes = bytes;
cif->bytes = ALIGN(bytes,8);
return FFI_OK;
}
void
ffi_call(
ffi_cif* cif,
void (*fn)(void),
void* rvalue,
void** avalue)
{
enum x86_64_reg_class classes[MAX_CLASSES];
char* stack;
char* argp;
ffi_type** arg_types;
int gprcount, ssecount, ngpr, nsse, i, avn;
_Bool ret_in_memory;
RegisterArgs* reg_args;
/* Can't call 32-bit mode from 64-bit mode. */
FFI_ASSERT(cif->abi == FFI_UNIX64);
/* If the return value is a struct and we don't have a return value
address then we need to make one. Note the setting of flags to
VOID above in ffi_prep_cif_machdep. */
ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
&& (cif->flags & 0xff) == FFI_TYPE_VOID);
if (rvalue == NULL && ret_in_memory)
rvalue = alloca (cif->rtype->size);
/* Allocate the space for the arguments, plus 4 words of temp space. */
stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
reg_args = (RegisterArgs*)stack;
argp = stack + sizeof(RegisterArgs);
gprcount = ssecount = 0;
/* If the return value is passed in memory, add the pointer as the
first integer argument. */
if (ret_in_memory)
reg_args->gpr[gprcount++] = (long) rvalue;
avn = cif->nargs;
arg_types = cif->arg_types;
for (i = 0; i < avn; ++i)
{
size_t size = arg_types[i]->size;
int n;
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
if (n == 0
|| gprcount + ngpr > MAX_GPR_REGS
|| ssecount + nsse > MAX_SSE_REGS)
{
long align = arg_types[i]->alignment;
/* Stack arguments are *always* at least 8 byte aligned. */
if (align < 8)
align = 8;
/* Pass this argument in memory. */
argp = (void *) ALIGN (argp, align);
memcpy (argp, avalue[i], size);
argp += size;
}
else
{ /* The argument is passed entirely in registers. */
char *a = (char *) avalue[i];
int j;
for (j = 0; j < n; j++, a += 8, size -= 8)
{
switch (classes[j])
{
case X86_64_INTEGER_CLASS:
case X86_64_INTEGERSI_CLASS:
reg_args->gpr[gprcount] = 0;
switch (arg_types[i]->type) {
case FFI_TYPE_SINT8:
{
int8_t shortval = *(int8_t*)a;
int64_t actval = (int64_t)shortval;
reg_args->gpr[gprcount] = actval;
/*memcpy (&reg_args->gpr[gprcount], &actval, 8);*/
break;
}
case FFI_TYPE_SINT16:
{
int16_t shortval = *(int16_t*)a;
int64_t actval = (int64_t)shortval;
memcpy (&reg_args->gpr[gprcount], &actval, 8);
break;
}
case FFI_TYPE_SINT32:
{
int32_t shortval = *(int32_t*)a;
int64_t actval = (int64_t)shortval;
memcpy (&reg_args->gpr[gprcount], &actval, 8);
break;
}
case FFI_TYPE_UINT8:
{
u_int8_t shortval = *(u_int8_t*)a;
u_int64_t actval = (u_int64_t)shortval;
/*memcpy (&reg_args->gpr[gprcount], &actval, 8);*/
reg_args->gpr[gprcount] = actval;
break;
}
case FFI_TYPE_UINT16:
{
u_int16_t shortval = *(u_int16_t*)a;
u_int64_t actval = (u_int64_t)shortval;
memcpy (&reg_args->gpr[gprcount], &actval, 8);
break;
}
case FFI_TYPE_UINT32:
{
u_int32_t shortval = *(u_int32_t*)a;
u_int64_t actval = (u_int64_t)shortval;
memcpy (&reg_args->gpr[gprcount], &actval, 8);
break;
}
default:
//memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
reg_args->gpr[gprcount] = *(int64_t*)a;
}
gprcount++;
break;
case X86_64_SSE_CLASS:
case X86_64_SSEDF_CLASS:
reg_args->sse[ssecount++] = *(UINT64 *) a;
break;
case X86_64_SSESF_CLASS:
reg_args->sse[ssecount++] = *(UINT32 *) a;
break;
default:
abort();
}
}
}
}
ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
cif->flags, rvalue, fn, ssecount);
}
extern void ffi_closure_unix64(void);
ffi_status
ffi_prep_closure(
ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void* user_data)
{
volatile unsigned short* tramp;
if (cif->abi != FFI_UNIX64)
return FFI_BAD_ABI;
tramp = (volatile unsigned short*)&closure->tramp[0];
tramp[0] = 0xbb49; /* mov <code>, %r11 */
*(void* volatile*)&tramp[1] = ffi_closure_unix64;
tramp[5] = 0xba49; /* mov <data>, %r10 */
*(void* volatile*)&tramp[6] = closure;
/* Set the carry bit if the function uses any sse registers.
This is clc or stc, together with the first byte of the jmp. */
tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
tramp[11] = 0xe3ff; /* jmp *%r11 */
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
return FFI_OK;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-prototypes"
int
ffi_closure_unix64_inner(
ffi_closure* closure,
void* rvalue,
RegisterArgs* reg_args,
char* argp)
#pragma clang diagnostic pop
{
ffi_cif* cif = closure->cif;
void** avalue = alloca(cif->nargs * sizeof(void *));
ffi_type** arg_types;
long i, avn;
int gprcount = 0;
int ssecount = 0;
int ngpr, nsse;
int ret;
ret = cif->rtype->type;
if (ret != FFI_TYPE_VOID)
{
enum x86_64_reg_class classes[MAX_CLASSES];
int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
if (n == 0)
{
/* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */
rvalue = (void *) reg_args->gpr[gprcount++];
/* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID;
}
else if (ret == FFI_TYPE_STRUCT && n == 2)
{
/* Mark which register the second word of the structure goes in. */
_Bool sse0 = SSE_CLASS_P (classes[0]);
_Bool sse1 = SSE_CLASS_P (classes[1]);
if (!sse0 && sse1)
ret |= 1 << 8;
else if (sse0 && !sse1)
ret |= 1 << 9;
}
}
avn = cif->nargs;
arg_types = cif->arg_types;
for (i = 0; i < avn; ++i)
{
enum x86_64_reg_class classes[MAX_CLASSES];
int n;
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
if (n == 0
|| gprcount + ngpr > MAX_GPR_REGS
|| ssecount + nsse > MAX_SSE_REGS)
{
long align = arg_types[i]->alignment;
/* Stack arguments are *always* at least 8 byte aligned. */
if (align < 8)
align = 8;
/* Pass this argument in memory. */
argp = (void *) ALIGN (argp, align);
avalue[i] = argp;
argp += arg_types[i]->size;
}
#if !defined(X86_DARWIN)
/* If the argument is in a single register, or two consecutive
registers, then we can use that address directly. */
else if (n == 1 || (n == 2 &&
SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
{
// The argument is in a single register.
if (SSE_CLASS_P (classes[0]))
{
avalue[i] = &reg_args->sse[ssecount];
ssecount += n;
}
else
{
avalue[i] = &reg_args->gpr[gprcount];
gprcount += n;
}
}
#endif
/* Otherwise, allocate space to make them consecutive. */
else
{
char *a = alloca (16);
int j;
avalue[i] = a;
for (j = 0; j < n; j++, a += 8)
{
if (SSE_CLASS_P (classes[j]))
memcpy (a, &reg_args->sse[ssecount++], 8);
else
memcpy (a, &reg_args->gpr[gprcount++], 8);
}
}
}
/* Invoke the closure. */
closure->fun (cif, rvalue, avalue, closure->user_data);
/* Tell assembly how to perform return type promotions. */
return ret;
}
#endif /* __x86_64__ */

View File

@ -1,438 +0,0 @@
#ifdef __i386__
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
Copyright (c) 2002 Ranjit Mathew
Copyright (c) 2002 Bo Thorsen
Copyright (c) 2002 Roger Sayle
x86 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
void ffi_prep_args(char *stack, extended_cif *ecif);
void ffi_prep_args(char *stack, extended_cif *ecif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if (ecif->cif->flags == 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;
/* Align if necessary */
if ((sizeof(int) - 1) & (unsigned) argp)
argp = (char *) ALIGN(argp, sizeof(int));
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_SINT32:
*(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
break;
case FFI_TYPE_UINT32:
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
break;
case FFI_TYPE_STRUCT:
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
break;
default:
FFI_ASSERT(0);
}
}
else
{
memcpy(argp, *p_argv, z);
}
p_argv++;
argp += z;
}
return;
}
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
#ifdef X86
case FFI_TYPE_STRUCT:
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
#endif
case FFI_TYPE_SINT64:
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
cif->flags = (unsigned) cif->rtype->type;
break;
case FFI_TYPE_UINT64:
cif->flags = FFI_TYPE_SINT64;
break;
#ifndef X86
case FFI_TYPE_STRUCT:
if (cif->rtype->size == 1)
{
cif->flags = FFI_TYPE_SINT8; /* same as char size */
}
else if (cif->rtype->size == 2)
{
cif->flags = FFI_TYPE_SINT16; /* same as short size */
}
else if (cif->rtype->size == 4)
{
cif->flags = FFI_TYPE_INT; /* same as int type */
}
else if (cif->rtype->size == 8)
{
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
}
else
{
cif->flags = FFI_TYPE_STRUCT;
}
break;
#endif
default:
cif->flags = FFI_TYPE_INT;
break;
}
#ifdef X86_DARWIN
cif->bytes = (cif->bytes + 15) & ~0xF;
#endif
return FFI_OK;
}
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
#ifdef X86_WIN32
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
#endif /* X86_WIN32 */
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
{
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
if ((rvalue == NULL) &&
(cif->flags == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
}
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
fn);
break;
#ifdef X86_WIN32
case FFI_STDCALL:
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
break;
#endif /* X86_WIN32 */
default:
FFI_ASSERT(0);
break;
}
}
/** private members **/
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
void** args, ffi_cif* cif);
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
__attribute__ ((regparm(1)));
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
__attribute__ ((regparm(1)));
/* This function is jumped to by the trampoline */
unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (closure, respp, args)
ffi_closure *closure;
void **respp;
void *args;
{
// our various things...
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);
(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)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if ( cif->flags == FFI_TYPE_STRUCT ) {
*rvalue = *(void **) argp;
argp += 4;
}
p_argv = avalue;
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
{
size_t z;
/* Align if necessary */
if ((sizeof(int) - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, sizeof(int));
}
z = (*p_arg)->size;
/* because we're little endian, this is what it turns into. */
*p_argv = (void*) argp;
p_argv++;
argp += z;
}
return;
}
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
*(unsigned char*) &__tramp[0] = 0xb8; \
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
*(unsigned char *) &__tramp[5] = 0xe9; \
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
})
/* the cif must already be prep'ed */
ffi_status
ffi_prep_closure (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
{
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
&ffi_closure_SYSV, \
(void*)closure);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
/* ------- Native raw API support -------------------------------- */
#if !FFI_NO_RAW_API
ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc)
{
int i;
FFI_ASSERT (cif->abi == FFI_SYSV);
// we currently don't support certain kinds of arguments for raw
// closures. This should be implemented by a separate assembly language
// routine, since it would require argument processing, something we
// don't do now for performance.
for (i = cif->nargs-1; i >= 0; i--)
{
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
}
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
codeloc);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
static void
ffi_prep_args_raw(char *stack, extended_cif *ecif)
{
memcpy (stack, ecif->avalue, ecif->cif->bytes);
}
/* we borrow this routine from libffi (it must be changed, though, to
* actually call the function passed in the first argument. as of
* libffi-1.20, this is not the case.)
*/
extern void
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)());
#ifdef X86_WIN32
extern void
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)());
#endif /* X86_WIN32 */
void
ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
{
extended_cif ecif;
void **avalue = (void **)fake_avalue;
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_raw, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
break;
#ifdef X86_WIN32
case FFI_STDCALL:
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
break;
#endif /* X86_WIN32 */
default:
FFI_ASSERT(0);
break;
}
}
#endif
#endif // __i386__

View File

@ -52,7 +52,6 @@ EXCLUDED = clean_lines('''
# OSX
#Modules/_ctypes/darwin/*.c
#Modules/_ctypes/libffi_osx/*.c
Modules/_scproxy.c # SystemConfiguration/SystemConfiguration.h
# Windows

View File

@ -13,11 +13,11 @@ import untabify
# Excluded directories which are copies of external libraries:
# don't check their coding style
EXCLUDE_DIRS = [os.path.join('Modules', '_ctypes', 'libffi_osx'),
os.path.join('Modules', '_ctypes', 'libffi_msvc'),
os.path.join('Modules', '_decimal', 'libmpdec'),
os.path.join('Modules', 'expat'),
os.path.join('Modules', 'zlib')]
EXCLUDE_DIRS = [
os.path.join('Modules', '_decimal', 'libmpdec'),
os.path.join('Modules', 'expat'),
os.path.join('Modules', 'zlib'),
]
SRCDIR = sysconfig.get_config_var('srcdir')