mirror of https://github.com/python/cpython
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:
parent
25590eb5de
commit
025b5c3780
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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__ */
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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__
|
|
@ -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)
|
|
@ -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
|
@ -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__
|
|
@ -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
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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 (®_args->gpr[gprcount], &actval, 8);*/
|
||||
break;
|
||||
}
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
{
|
||||
int16_t shortval = *(int16_t*)a;
|
||||
int64_t actval = (int64_t)shortval;
|
||||
memcpy (®_args->gpr[gprcount], &actval, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
{
|
||||
int32_t shortval = *(int32_t*)a;
|
||||
int64_t actval = (int64_t)shortval;
|
||||
memcpy (®_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 (®_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 (®_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 (®_args->gpr[gprcount], &actval, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
//memcpy (®_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] = ®_args->sse[ssecount];
|
||||
ssecount += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = ®_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, ®_args->sse[ssecount++], 8);
|
||||
else
|
||||
memcpy (a, ®_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__ */
|
|
@ -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__
|
|
@ -52,7 +52,6 @@ EXCLUDED = clean_lines('''
|
|||
|
||||
# OSX
|
||||
#Modules/_ctypes/darwin/*.c
|
||||
#Modules/_ctypes/libffi_osx/*.c
|
||||
Modules/_scproxy.c # SystemConfiguration/SystemConfiguration.h
|
||||
|
||||
# Windows
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue