summaryrefslogtreecommitdiffstats
path: root/Modules/_ctypes/libffi_osx
diff options
context:
space:
mode:
authorChristian Heimes <christian@cheimes.de>2008-03-04 23:39:23 (GMT)
committerChristian Heimes <christian@cheimes.de>2008-03-04 23:39:23 (GMT)
commit7864476afa402a0537c33ba9630e77351720baf8 (patch)
treecb9113e14d6a0b56696398f4d61d107ea7055e08 /Modules/_ctypes/libffi_osx
parent227c800f4397764a20b77fd58467e2bb27fbf510 (diff)
downloadcpython-7864476afa402a0537c33ba9630e77351720baf8.zip
cpython-7864476afa402a0537c33ba9630e77351720baf8.tar.gz
cpython-7864476afa402a0537c33ba9630e77351720baf8.tar.bz2
Merged revisions 61209-61214,61217-61222,61224-61226,61233-61237 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r61209 | georg.brandl | 2008-03-03 21:37:55 +0100 (Mon, 03 Mar 2008) | 2 lines There are now sixteen isfoo functions. ........ r61210 | georg.brandl | 2008-03-03 21:39:00 +0100 (Mon, 03 Mar 2008) | 2 lines 15 -> 16, the 2nd ........ r61211 | georg.brandl | 2008-03-03 22:22:47 +0100 (Mon, 03 Mar 2008) | 2 lines Actually import itertools. ........ r61212 | georg.brandl | 2008-03-03 22:31:50 +0100 (Mon, 03 Mar 2008) | 2 lines Expand a bit on genexp scopes. ........ r61213 | raymond.hettinger | 2008-03-03 23:04:55 +0100 (Mon, 03 Mar 2008) | 1 line Remove dependency on itertools -- a simple genexp suffices. ........ r61214 | raymond.hettinger | 2008-03-03 23:19:58 +0100 (Mon, 03 Mar 2008) | 1 line Issue 2226: Callable checked for the wrong abstract method. ........ r61217 | andrew.kuchling | 2008-03-04 01:40:32 +0100 (Tue, 04 Mar 2008) | 1 line Typo fix ........ r61218 | andrew.kuchling | 2008-03-04 02:30:10 +0100 (Tue, 04 Mar 2008) | 1 line Grammar fix; markup fix ........ r61219 | andrew.kuchling | 2008-03-04 02:47:38 +0100 (Tue, 04 Mar 2008) | 1 line Fix sentence fragment ........ r61220 | andrew.kuchling | 2008-03-04 02:48:26 +0100 (Tue, 04 Mar 2008) | 1 line Typo fix ........ r61221 | andrew.kuchling | 2008-03-04 02:49:37 +0100 (Tue, 04 Mar 2008) | 1 line Add versionadded tags ........ r61222 | andrew.kuchling | 2008-03-04 02:50:32 +0100 (Tue, 04 Mar 2008) | 1 line Thesis night results: add various items ........ r61224 | raymond.hettinger | 2008-03-04 05:17:08 +0100 (Tue, 04 Mar 2008) | 1 line Beef-up docs and tests for itertools. Fix-up end-case for product(). ........ r61225 | georg.brandl | 2008-03-04 08:25:54 +0100 (Tue, 04 Mar 2008) | 2 lines Fix some patch attributions. ........ r61226 | georg.brandl | 2008-03-04 08:33:30 +0100 (Tue, 04 Mar 2008) | 2 lines #2230: document that PyArg_* leaves addresses alone on error. ........ r61233 | neal.norwitz | 2008-03-04 17:22:46 +0100 (Tue, 04 Mar 2008) | 3 lines Close the file before trying to remove the directory so it works on Windows. As reported by Trent Nelson on python-dev. ........ r61234 | thomas.heller | 2008-03-04 21:09:11 +0100 (Tue, 04 Mar 2008) | 9 lines Merged changes from libffi3-branch. The bundled libffi copy is now in sync with the recently released libffi3.0.4 version, apart from some small changes to Modules/_ctypes/libffi/configure.ac. I gave up on using libffi3 files on os x. Instead, static configuration with files from pyobjc is used. ........ r61235 | thomas.heller | 2008-03-04 21:21:42 +0100 (Tue, 04 Mar 2008) | 1 line Try to fix the build for PY_LINUX. ........ r61236 | fred.drake | 2008-03-04 22:14:04 +0100 (Tue, 04 Mar 2008) | 2 lines fix typo ........ r61237 | raymond.hettinger | 2008-03-04 23:29:44 +0100 (Tue, 04 Mar 2008) | 1 line Fix refleak in chain(). ........
Diffstat (limited to 'Modules/_ctypes/libffi_osx')
-rw-r--r--Modules/_ctypes/libffi_osx/LICENSE20
-rw-r--r--Modules/_ctypes/libffi_osx/README500
-rw-r--r--Modules/_ctypes/libffi_osx/README.pyobjc5
-rw-r--r--Modules/_ctypes/libffi_osx/ffi.c226
-rw-r--r--Modules/_ctypes/libffi_osx/include/ffi.h352
-rw-r--r--Modules/_ctypes/libffi_osx/include/ffi_common.h102
-rw-r--r--Modules/_ctypes/libffi_osx/include/fficonfig.h150
-rw-r--r--Modules/_ctypes/libffi_osx/include/ffitarget.h13
-rw-r--r--Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h104
-rw-r--r--Modules/_ctypes/libffi_osx/include/x86-ffitarget.h88
-rw-r--r--Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S369
-rw-r--r--Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h106
-rw-r--r--Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S325
-rw-r--r--Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c1775
-rw-r--r--Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S423
-rw-r--r--Modules/_ctypes/libffi_osx/types.c115
-rw-r--r--Modules/_ctypes/libffi_osx/x86/darwin64.S415
-rw-r--r--Modules/_ctypes/libffi_osx/x86/x86-darwin.S243
-rw-r--r--Modules/_ctypes/libffi_osx/x86/x86-ffi64.c624
-rw-r--r--Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c569
20 files changed, 6524 insertions, 0 deletions
diff --git a/Modules/_ctypes/libffi_osx/LICENSE b/Modules/_ctypes/libffi_osx/LICENSE
new file mode 100644
index 0000000..f591795
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/LICENSE
@@ -0,0 +1,20 @@
+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.
diff --git a/Modules/_ctypes/libffi_osx/README b/Modules/_ctypes/libffi_osx/README
new file mode 100644
index 0000000..1fc2747
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/README
@@ -0,0 +1,500 @@
+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 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 Crazy 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.
diff --git a/Modules/_ctypes/libffi_osx/README.pyobjc b/Modules/_ctypes/libffi_osx/README.pyobjc
new file mode 100644
index 0000000..405d85f
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/README.pyobjc
@@ -0,0 +1,5 @@
+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.
diff --git a/Modules/_ctypes/libffi_osx/ffi.c b/Modules/_ctypes/libffi_osx/ffi.c
new file mode 100644
index 0000000..bf42093
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/ffi.c
@@ -0,0 +1,226 @@
+/* -----------------------------------------------------------------------
+ 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@*/
+
+ if (arg == NULL || arg->elements == NULL ||
+ arg->size != 0 || arg->alignment != 0)
+ return FFI_BAD_TYPEDEF;
+
+ ffi_type** 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)
+
+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)
+
+// 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)
+{
+ if (cif == NULL)
+ return FFI_BAD_TYPEDEF;
+
+ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI)
+ return FFI_BAD_ABI;
+
+ unsigned int bytes = 0;
+ unsigned int i;
+ ffi_type** ptr;
+
+ 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__ */
diff --git a/Modules/_ctypes/libffi_osx/include/ffi.h b/Modules/_ctypes/libffi_osx/include/ffi.h
new file mode 100644
index 0000000..3d39064
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/include/ffi.h
@@ -0,0 +1,352 @@
+/* -----------------------------------------------------------------*-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);
+
+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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/include/ffi_common.h b/Modules/_ctypes/libffi_osx/include/ffi_common.h
new file mode 100644
index 0000000..685a358
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/include/ffi_common.h
@@ -0,0 +1,102 @@
+/* -----------------------------------------------------------------------
+ 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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/include/fficonfig.h b/Modules/_ctypes/libffi_osx/include/fficonfig.h
new file mode 100644
index 0000000..2172490
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/include/fficonfig.h
@@ -0,0 +1,150 @@
+/* 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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/include/ffitarget.h b/Modules/_ctypes/libffi_osx/include/ffitarget.h
new file mode 100644
index 0000000..faaa30d
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/include/ffitarget.h
@@ -0,0 +1,13 @@
+/* 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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h b/Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
new file mode 100644
index 0000000..2318421
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
@@ -0,0 +1,104 @@
+/* -----------------------------------------------------------------*-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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/include/x86-ffitarget.h b/Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
new file mode 100644
index 0000000..55c2b6c
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
@@ -0,0 +1,88 @@
+/* -----------------------------------------------------------------*-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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
new file mode 100644
index 0000000..0a95771
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
@@ -0,0 +1,369 @@
+#if defined(__ppc__) || defined(__ppc64__)
+
+/* -----------------------------------------------------------------------
+ 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 0x90 ; FDE Encoding (indirect pcrel)
+ .byte 0xc ; DW_CFA_def_cfa
+ .byte 0x1 ; uleb128 0x1
+ .byte 0x0 ; uleb128 0x0
+ .align LOG2_GPR_BYTES
+LECIE1:
+.globl _ffi_call_DARWIN.eh
+_ffi_call_DARWIN.eh:
+LSFDE1:
+ .set L$set$1,LEFDE1-LASFDE1
+ .long L$set$1 ; FDE Length
+
+LASFDE1:
+ .long LASFDE1-EH_frame1 ; FDE CIE offset
+ .g_long LLFB0$non_lazy_ptr-. ; FDE initial location
+ .set L$set$3,LFE1-LFB0
+ .g_long L$set$3 ; FDE address range
+ .byte 0x0 ; uleb128 0x0; Augmentation size
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$4,LCFI0-LFB1
+ .long L$set$4
+ .byte 0xd ; DW_CFA_def_cfa_register
+ .byte 0x08 ; uleb128 0x08
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$5,LCFI1-LCFI0
+ .long L$set$5
+ .byte 0x11 ; DW_CFA_offset_extended_sf
+ .byte 0x41 ; uleb128 0x41
+ .byte 0x7e ; sleb128 -2
+ .byte 0x9f ; DW_CFA_offset, column 0x1f
+ .byte 0x1 ; uleb128 0x1
+ .byte 0x9e ; DW_CFA_offset, column 0x1e
+ .byte 0x2 ; uleb128 0x2
+ .byte 0x9d ; DW_CFA_offset, column 0x1d
+ .byte 0x3 ; uleb128 0x3
+ .byte 0x9c ; DW_CFA_offset, column 0x1c
+ .byte 0x4 ; uleb128 0x4
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$6,LCFI2-LCFI1
+ .long L$set$6
+ .byte 0xd ; DW_CFA_def_cfa_register
+ .byte 0x1c ; uleb128 0x1c
+ .align LOG2_GPR_BYTES
+LEFDE1:
+.data
+ .align LOG2_GPR_BYTES
+LLFB0$non_lazy_ptr:
+ .g_long LFB0
+
+#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__
diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
new file mode 100644
index 0000000..00e7e4d
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
@@ -0,0 +1,106 @@
+/* -----------------------------------------------------------------------
+ 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)
+};
+
+
+void ffi_prep_args(extended_cif* inEcif, unsigned *const stack);
+
+typedef union
+{
+ float f;
+ double d;
+} ffi_dblfl;
+
+int ffi_closure_helper_DARWIN( ffi_closure* closure,
+ void* rvalue, unsigned long* pgr,
+ ffi_dblfl* pfr);
+
+
+#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*);
+bool ffi64_struct_contains_fp(const ffi_type* inType);
+unsigned int ffi64_data_size(const ffi_type* inType);
+
+
+
+#endif
+
+#endif // !defined(LIBFFI_ASM)
diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
new file mode 100644
index 0000000..227dd1a
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
@@ -0,0 +1,325 @@
+#if defined(__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 /* extract return address */
+ stg r0,MODE_CHOICE(8,16)(r1) /* save return address */
+
+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(MODE_CHOICE(176,248))(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,MODE_CHOICE(200,304)(r1)
+ stg r4,MODE_CHOICE(204,312)(r1)
+ stg r5,MODE_CHOICE(208,320)(r1)
+ stg r6,MODE_CHOICE(212,328)(r1)
+ stg r7,MODE_CHOICE(216,336)(r1)
+ stg r8,MODE_CHOICE(220,344)(r1)
+ stg r9,MODE_CHOICE(224,352)(r1)
+ stg r10,MODE_CHOICE(228,360)(r1)
+
+ /* Save FPRs 1 - 13. (aligned to 8) */
+ stfd f1,MODE_CHOICE(56,112)(r1)
+ stfd f2,MODE_CHOICE(64,120)(r1)
+ stfd f3,MODE_CHOICE(72,128)(r1)
+ stfd f4,MODE_CHOICE(80,136)(r1)
+ stfd f5,MODE_CHOICE(88,144)(r1)
+ stfd f6,MODE_CHOICE(96,152)(r1)
+ stfd f7,MODE_CHOICE(104,160)(r1)
+ stfd f8,MODE_CHOICE(112,168)(r1)
+ stfd f9,MODE_CHOICE(120,176)(r1)
+ stfd f10,MODE_CHOICE(128,184)(r1)
+ stfd f11,MODE_CHOICE(136,192)(r1)
+ stfd f12,MODE_CHOICE(144,200)(r1)
+ stfd f13,MODE_CHOICE(152,208)(r1)
+
+ /* Set up registers for the routine that actually does the work.
+ Get the context pointer from the trampoline. */
+ mr r3,r11
+
+ /* Load the pointer to the result storage. */
+ /* current stack frame size - ((4/8 * 4) + saved registers) */
+ addi r4,r1,MODE_CHOICE(160,216)
+
+ /* Load the pointer to the saved gpr registers. */
+ addi r5,r1,MODE_CHOICE(200,304)
+
+ /* Load the pointer to the saved fpr registers. */
+ addi r6,r1,MODE_CHOICE(56,112)
+
+ /* Make the call. */
+ bl Lffi_closure_helper_DARWIN$stub
+
+ /* Now r3 contains the return type
+ so use it to look up in a table
+ so we know how to deal with each type. */
+
+ /* Look the proper starting point in table
+ by using return type as offset. */
+ addi r5,r1,MODE_CHOICE(160,216) // 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,MODE_CHOICE(0,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,MODE_CHOICE(3,7)(r5)
+ b Lfinish
+ nop
+ nop
+
+/* case FFI_TYPE_SINT8 */
+Lret_type6:
+ lbz r3,MODE_CHOICE(3,7)(r5)
+ extsb r3,r3
+ b Lfinish
+ nop
+
+/* case FFI_TYPE_UINT16 */
+Lret_type7:
+ lhz r3,MODE_CHOICE(2,6)(r5)
+ b Lfinish
+ nop
+ nop
+
+/* case FFI_TYPE_SINT16 */
+Lret_type8:
+ lha r3,MODE_CHOICE(2,6)(r5)
+ b Lfinish
+ nop
+ nop
+
+/* case FFI_TYPE_UINT32 */
+Lret_type9: // same as Lret_type1
+ lwz r3,MODE_CHOICE(0,4)(r5)
+ b Lfinish
+ nop
+ nop
+
+/* case FFI_TYPE_SINT32 */
+Lret_type10: // same as Lret_type1
+ lwz r3,MODE_CHOICE(0,4)(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 MODE_CHOICE(Lfinish,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)
+
+/* case done */
+Lfinish:
+ addi r1,r1,SF_ROUND(MODE_CHOICE(176,248)) // Restore stack pointer.
+ lg r0,MODE_CHOICE(8,16)(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 0x90 ; FDE Encoding (indirect pcrel)
+ .byte 0xc ; DW_CFA_def_cfa
+ .byte 0x1 ; uleb128 0x1
+ .byte 0x0 ; uleb128 0x0
+ .align LOG2_GPR_BYTES
+LECIE1:
+.globl _ffi_closure_ASM.eh
+_ffi_closure_ASM.eh:
+LSFDE1:
+ .set L$set$1,LEFDE1-LASFDE1
+ .long L$set$1 ; FDE Length
+
+LASFDE1:
+ .long LASFDE1-EH_frame1 ; FDE CIE offset
+ .g_long LLFB1$non_lazy_ptr-. ; FDE initial location
+ .set L$set$3,LFE1-LFB1
+ .g_long L$set$3 ; FDE address range
+ .byte 0x0 ; uleb128 0x0; Augmentation size
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$3,LCFI1-LCFI0
+ .long L$set$3
+ .byte 0xe ; DW_CFA_def_cfa_offset
+ .byte 176,1 ; uleb128 176
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$4,LCFI0-LFB1
+ .long L$set$4
+ .byte 0x11 ; DW_CFA_offset_extended_sf
+ .byte 0x41 ; uleb128 0x41
+ .byte 0x7e ; sleb128 -2
+ .align LOG2_GPR_BYTES
+
+LEFDE1:
+.data
+ .align LOG2_GPR_BYTES
+LDFCM0:
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+ .align LOG2_GPR_BYTES
+
+Lffi_closure_helper_DARWIN$stub:
+ .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
+
+.data
+ .align LOG2_GPR_BYTES
+LLFB1$non_lazy_ptr:
+ .g_long LFB1
+
+#endif // __ppc__
diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c b/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
new file mode 100644
index 0000000..3c682ca
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
@@ -0,0 +1,1775 @@
+#if defined(__ppc__) || defined(__ppc64__)
+
+/* -----------------------------------------------------------------------
+ ffi.c - Copyright (c) 1998 Geoffrey Keating
+
+ PowerPC Foreign Function Interface
+
+ Darwin ABI support (c) 2001 John Hornkvist
+ AIX ABI support (c) 2002 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.
+ ----------------------------------------------------------------------- */
+
+#include "ffi.h"
+#include "ffi_common.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "ppc-darwin.h"
+#include <architecture/ppc/mode_independent_asm.h>
+
+#if 0
+#if defined(POWERPC_DARWIN)
+#include <libkern/OSCacheControl.h> // for sys_icache_invalidate()
+#endif
+
+#else
+
+/* Explicit prototype instead of including a header to allow compilation
+ * on Tiger systems.
+ */
+
+#pragma weak sys_icache_invalidate
+extern void sys_icache_invalidate(void *start, size_t len);
+
+#endif
+
+extern void ffi_closure_ASM(void);
+
+// The layout of a function descriptor. A C function pointer really
+// points to one of these.
+typedef struct aix_fd_struct {
+ void* code_pointer;
+ void* toc;
+} aix_fd;
+
+/* ffi_prep_args is called by the assembly routine once stack space
+ has been allocated for the function's arguments.
+
+ The stack layout we want looks like this:
+
+ | Return address from ffi_call_DARWIN | higher addresses
+ |--------------------------------------------|
+ | Previous backchain pointer 4/8 | stack pointer here
+ |--------------------------------------------|-\ <<< on entry to
+ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN
+ |--------------------------------------------| |
+ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288
+ |--------------------------------------------| |
+ | Space for GPR2 4/8 | |
+ |--------------------------------------------| | stack |
+ | Reserved (4/8)*2 | | grows |
+ |--------------------------------------------| | down V
+ | Space for callee's LR 4/8 | |
+ |--------------------------------------------| | lower addresses
+ | Saved CR 4/8 | |
+ |--------------------------------------------| | stack pointer here
+ | Current backchain pointer 4/8 | | during
+ |--------------------------------------------|-/ <<< ffi_call_DARWIN
+
+ Note: ppc64 CR is saved in the low word of a long on the stack.
+*/
+
+/*@-exportheader@*/
+void
+ffi_prep_args(
+ extended_cif* inEcif,
+ unsigned *const stack)
+/*@=exportheader@*/
+{
+ /* Copy the ecif to a local var so we can trample the arg.
+ BC note: test this with GP later for possible problems... */
+ volatile extended_cif* ecif = inEcif;
+
+ const unsigned bytes = ecif->cif->bytes;
+ const unsigned flags = ecif->cif->flags;
+
+ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode
+ and 8 in 64-bit mode. */
+ unsigned long *const longStack = (unsigned long *const)stack;
+
+ /* 'stacktop' points at the previous backchain pointer. */
+#if defined(__ppc64__)
+ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area,
+ // saved registers, and an extra FPR.
+ unsigned long *const stacktop =
+ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96);
+#elif defined(__ppc__)
+ unsigned long *const stacktop = longStack + (bytes / sizeof(long));
+#else
+#error undefined architecture
+#endif
+
+ /* 'fpr_base' points at the space for fpr1, and grows upwards as
+ we use FPR registers. */
+ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) -
+ NUM_FPR_ARG_REGISTERS;
+
+#if defined(__ppc64__)
+ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base
+ // down a couple pegs.
+ fpr_base -= 2;
+#endif
+
+ unsigned int fparg_count = 0;
+
+ /* 'next_arg' grows up as we put parameters in it. */
+ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */
+
+ int i;
+ double double_tmp;
+ void** p_argv = ecif->avalue;
+ unsigned long gprvalue;
+ ffi_type** ptr = ecif->cif->arg_types;
+
+ /* Check that everything starts aligned properly. */
+ FFI_ASSERT(stack == SF_ROUND(stack));
+ FFI_ASSERT(stacktop == SF_ROUND(stacktop));
+ FFI_ASSERT(bytes == SF_ROUND(bytes));
+
+ /* Deal with return values that are actually pass-by-reference.
+ Rule:
+ Return values are referenced by r3, so r4 is the first parameter. */
+
+ if (flags & FLAG_RETVAL_REFERENCE)
+ *next_arg++ = (unsigned long)(char*)ecif->rvalue;
+
+ /* Now for the arguments. */
+ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++)
+ {
+ switch ((*ptr)->type)
+ {
+ /* If a floating-point parameter appears before all of the general-
+ purpose registers are filled, the corresponding GPRs that match
+ the size of the floating-point parameter are shadowed for the
+ benefit of vararg and pre-ANSI functions. */
+ case FFI_TYPE_FLOAT:
+ double_tmp = *(float*)*p_argv;
+
+ if (fparg_count < NUM_FPR_ARG_REGISTERS)
+ *fpr_base++ = double_tmp;
+
+ *(double*)next_arg = double_tmp;
+
+ next_arg++;
+ fparg_count++;
+ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ double_tmp = *(double*)*p_argv;
+
+ if (fparg_count < NUM_FPR_ARG_REGISTERS)
+ *fpr_base++ = double_tmp;
+
+ *(double*)next_arg = double_tmp;
+
+ next_arg += MODE_CHOICE(2,1);
+ fparg_count++;
+ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+
+ break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+#if defined(__ppc64__)
+ if (fparg_count < NUM_FPR_ARG_REGISTERS)
+ *(long double*)fpr_base = *(long double*)*p_argv;
+#elif defined(__ppc__)
+ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1)
+ *(long double*)fpr_base = *(long double*)*p_argv;
+ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1)
+ *(double*)fpr_base = *(double*)*p_argv;
+#else
+#error undefined architecture
+#endif
+
+ *(long double*)next_arg = *(long double*)*p_argv;
+ fparg_count += 2;
+ fpr_base += 2;
+ next_arg += MODE_CHOICE(4,2);
+ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+
+ break;
+#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+#if defined(__ppc64__)
+ gprvalue = *(long long*)*p_argv;
+ goto putgpr;
+#elif defined(__ppc__)
+ *(long long*)next_arg = *(long long*)*p_argv;
+ next_arg += 2;
+ break;
+#else
+#error undefined architecture
+#endif
+
+ case FFI_TYPE_POINTER:
+ gprvalue = *(unsigned long*)*p_argv;
+ goto putgpr;
+
+ case FFI_TYPE_UINT8:
+ gprvalue = *(unsigned char*)*p_argv;
+ goto putgpr;
+
+ case FFI_TYPE_SINT8:
+ gprvalue = *(signed char*)*p_argv;
+ goto putgpr;
+
+ case FFI_TYPE_UINT16:
+ gprvalue = *(unsigned short*)*p_argv;
+ goto putgpr;
+
+ case FFI_TYPE_SINT16:
+ gprvalue = *(signed short*)*p_argv;
+ goto putgpr;
+
+ case FFI_TYPE_STRUCT:
+ {
+#if defined(__ppc64__)
+ unsigned int gprSize = 0;
+ unsigned int fprSize = 0;
+
+ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count,
+ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize);
+ next_arg += gprSize / sizeof(long);
+ fpr_base += fprSize / sizeof(double);
+
+#elif defined(__ppc__)
+ char* dest_cpy = (char*)next_arg;
+
+ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+ SI 4 bytes) are aligned as if they were those modes.
+ Structures with 3 byte in size are padded upwards. */
+ unsigned size_al = (*ptr)->size;
+
+ /* If the first member of the struct is a double, then align
+ the struct to double-word. */
+ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
+ size_al = ALIGN((*ptr)->size, 8);
+
+ if (ecif->cif->abi == FFI_DARWIN)
+ {
+ if (size_al < 3)
+ dest_cpy += 4 - size_al;
+ }
+
+ memcpy((char*)dest_cpy, (char*)*p_argv, size_al);
+ next_arg += (size_al + 3) / 4;
+#else
+#error undefined architecture
+#endif
+ break;
+ }
+
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ gprvalue = *(unsigned*)*p_argv;
+
+putgpr:
+ *next_arg++ = gprvalue;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Check that we didn't overrun the stack... */
+ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+ //FFI_ASSERT((unsigned *)fpr_base
+ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+#if defined(__ppc64__)
+
+bool
+ffi64_struct_contains_fp(
+ const ffi_type* inType)
+{
+ bool containsFP = false;
+ unsigned int i;
+
+ for (i = 0; inType->elements[i] != NULL && !containsFP; i++)
+ {
+ if (inType->elements[i]->type == FFI_TYPE_FLOAT ||
+ inType->elements[i]->type == FFI_TYPE_DOUBLE ||
+ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE)
+ containsFP = true;
+ else if (inType->elements[i]->type == FFI_TYPE_STRUCT)
+ containsFP = ffi64_struct_contains_fp(inType->elements[i]);
+ }
+
+ return containsFP;
+}
+
+#endif // defined(__ppc64__)
+
+/* Perform machine dependent cif processing. */
+ffi_status
+ffi_prep_cif_machdep(
+ ffi_cif* cif)
+{
+ /* All this is for the DARWIN ABI. */
+ int i;
+ ffi_type** ptr;
+ int intarg_count = 0;
+ int fparg_count = 0;
+ unsigned int flags = 0;
+ unsigned int size_al = 0;
+
+ /* All the machine-independent calculation of cif->bytes will be wrong.
+ Redo the calculation for DARWIN. */
+
+ /* Space for the frame pointer, callee's LR, CR, etc, and for
+ the asm's temp regs. */
+ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
+
+ /* Return value handling. The rules are as follows:
+ - 32-bit (or less) integer values are returned in gpr3;
+ - Structures of size <= 4 bytes also returned in gpr3;
+ - 64-bit integer values and structures between 5 and 8 bytes are
+ returned in gpr3 and gpr4;
+ - Single/double FP values are returned in fpr1;
+ - Long double FP (if not equivalent to double) values are returned in
+ fpr1 and fpr2;
+ - Larger structures values are allocated space and a pointer is passed
+ as the first argument. */
+ switch (cif->rtype->type)
+ {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+ flags |= FLAG_RETURNS_128BITS;
+ flags |= FLAG_RETURNS_FP;
+ break;
+#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+ case FFI_TYPE_DOUBLE:
+ flags |= FLAG_RETURNS_64BITS;
+ /* Fall through. */
+ case FFI_TYPE_FLOAT:
+ flags |= FLAG_RETURNS_FP;
+ break;
+
+#if defined(__ppc64__)
+ case FFI_TYPE_POINTER:
+#endif
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ flags |= FLAG_RETURNS_64BITS;
+ break;
+
+ case FFI_TYPE_STRUCT:
+ {
+#if defined(__ppc64__)
+
+ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL))
+ {
+ flags |= FLAG_RETVAL_REFERENCE;
+ flags |= FLAG_RETURNS_NOTHING;
+ intarg_count++;
+ }
+ else
+ {
+ flags |= FLAG_RETURNS_STRUCT;
+
+ if (ffi64_struct_contains_fp(cif->rtype))
+ flags |= FLAG_STRUCT_CONTAINS_FP;
+ }
+
+#elif defined(__ppc__)
+
+ flags |= FLAG_RETVAL_REFERENCE;
+ flags |= FLAG_RETURNS_NOTHING;
+ intarg_count++;
+
+#else
+#error undefined architecture
+#endif
+ break;
+ }
+
+ case FFI_TYPE_VOID:
+ flags |= FLAG_RETURNS_NOTHING;
+ break;
+
+ default:
+ /* Returns 32-bit integer, or similar. Nothing to do here. */
+ break;
+ }
+
+ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
+ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
+ goes on the stack. Structures are passed as a pointer to a copy of
+ the structure. Stuff on the stack needs to keep proper alignment. */
+ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+ {
+ switch ((*ptr)->type)
+ {
+ case FFI_TYPE_FLOAT:
+ case FFI_TYPE_DOUBLE:
+ fparg_count++;
+ /* If this FP arg is going on the stack, it must be
+ 8-byte-aligned. */
+ if (fparg_count > NUM_FPR_ARG_REGISTERS
+ && intarg_count % 2 != 0)
+ intarg_count++;
+ break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+ fparg_count += 2;
+ /* If this FP arg is going on the stack, it must be
+ 8-byte-aligned. */
+
+ if (
+#if defined(__ppc64__)
+ fparg_count > NUM_FPR_ARG_REGISTERS + 1
+#elif defined(__ppc__)
+ fparg_count > NUM_FPR_ARG_REGISTERS
+#else
+#error undefined architecture
+#endif
+ && intarg_count % 2 != 0)
+ intarg_count++;
+
+ intarg_count += 2;
+ break;
+#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ /* 'long long' arguments are passed as two words, but
+ either both words must fit in registers or both go
+ on the stack. If they go on the stack, they must
+ be 8-byte-aligned. */
+ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1
+ || (intarg_count >= NUM_GPR_ARG_REGISTERS
+ && intarg_count % 2 != 0))
+ intarg_count++;
+
+ intarg_count += MODE_CHOICE(2,1);
+
+ break;
+
+ case FFI_TYPE_STRUCT:
+ size_al = (*ptr)->size;
+ /* If the first member of the struct is a double, then align
+ the struct to double-word. */
+ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
+ size_al = ALIGN((*ptr)->size, 8);
+
+#if defined(__ppc64__)
+ // Look for FP struct members.
+ unsigned int j;
+
+ for (j = 0; (*ptr)->elements[j] != NULL; j++)
+ {
+ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT ||
+ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE)
+ {
+ fparg_count++;
+
+ if (fparg_count > NUM_FPR_ARG_REGISTERS)
+ intarg_count++;
+ }
+ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE)
+ {
+ fparg_count += 2;
+
+ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1)
+ intarg_count += 2;
+ }
+ else
+ intarg_count++;
+ }
+#elif defined(__ppc__)
+ intarg_count += (size_al + 3) / 4;
+#else
+#error undefined architecture
+#endif
+
+ break;
+
+ default:
+ /* Everything else is passed as a 4/8-byte word in a GPR, either
+ the object itself or a pointer to it. */
+ intarg_count++;
+ break;
+ }
+ }
+
+ /* Space for the FPR registers, if needed. */
+ if (fparg_count != 0)
+ {
+ flags |= FLAG_FP_ARGUMENTS;
+#if defined(__ppc64__)
+ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double);
+#elif defined(__ppc__)
+ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
+#else
+#error undefined architecture
+#endif
+ }
+
+ /* Stack space. */
+#if defined(__ppc64__)
+ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
+ bytes += (intarg_count + fparg_count) * sizeof(long);
+#elif defined(__ppc__)
+ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
+ bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
+#else
+#error undefined architecture
+#endif
+ else
+ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
+
+ /* The stack space allocated needs to be a multiple of 16/32 bytes. */
+ bytes = SF_ROUND(bytes);
+
+ cif->flags = flags;
+ cif->bytes = bytes;
+
+ return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void
+ffi_call_AIX(
+/*@out@*/ extended_cif*,
+ unsigned,
+ unsigned,
+/*@out@*/ unsigned*,
+ void (*fn)(void),
+ void (*fn2)(extended_cif*, unsigned *const));
+
+extern void
+ffi_call_DARWIN(
+/*@out@*/ extended_cif*,
+ unsigned long,
+ unsigned,
+/*@out@*/ unsigned*,
+ void (*fn)(void),
+ void (*fn2)(extended_cif*, unsigned *const));
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void
+ffi_call(
+/*@dependent@*/ ffi_cif* cif,
+ void (*fn)(void),
+/*@out@*/ void* rvalue,
+/*@dependent@*/ void** avalue)
+{
+ extended_cif ecif;
+
+ ecif.cif = cif;
+ ecif.avalue = avalue;
+
+ /* If the return value is a struct and we don't have a return
+ value address then we need to make one. */
+ if ((rvalue == NULL) &&
+ (cif->rtype->type == FFI_TYPE_STRUCT))
+ {
+ /*@-sysunrecog@*/
+ ecif.rvalue = alloca(cif->rtype->size);
+ /*@=sysunrecog@*/
+ }
+ else
+ ecif.rvalue = rvalue;
+
+ switch (cif->abi)
+ {
+ case FFI_AIX:
+ /*@-usedef@*/
+ ffi_call_AIX(&ecif, -cif->bytes,
+ cif->flags, ecif.rvalue, fn, ffi_prep_args);
+ /*@=usedef@*/
+ break;
+
+ case FFI_DARWIN:
+ /*@-usedef@*/
+ ffi_call_DARWIN(&ecif, -(long)cif->bytes,
+ cif->flags, ecif.rvalue, fn, ffi_prep_args);
+ /*@=usedef@*/
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+}
+
+/* here I'd like to add the stack frame layout we use in darwin_closure.S
+ and aix_clsoure.S
+
+ SP previous -> +---------------------------------------+ <--- child frame
+ | back chain to caller 4 |
+ +---------------------------------------+ 4
+ | saved CR 4 |
+ +---------------------------------------+ 8
+ | saved LR 4 |
+ +---------------------------------------+ 12
+ | reserved for compilers 4 |
+ +---------------------------------------+ 16
+ | reserved for binders 4 |
+ +---------------------------------------+ 20
+ | saved TOC pointer 4 |
+ +---------------------------------------+ 24
+ | always reserved 8*4=32 (previous GPRs)|
+ | according to the linkage convention |
+ | from AIX |
+ +---------------------------------------+ 56
+ | our FPR area 13*8=104 |
+ | f1 |
+ | . |
+ | f13 |
+ +---------------------------------------+ 160
+ | result area 8 |
+ +---------------------------------------+ 168
+ | alignement to the next multiple of 16 |
+SP current --> +---------------------------------------+ 176 <- parent frame
+ | back chain to caller 4 |
+ +---------------------------------------+ 180
+ | saved CR 4 |
+ +---------------------------------------+ 184
+ | saved LR 4 |
+ +---------------------------------------+ 188
+ | reserved for compilers 4 |
+ +---------------------------------------+ 192
+ | reserved for binders 4 |
+ +---------------------------------------+ 196
+ | saved TOC pointer 4 |
+ +---------------------------------------+ 200
+ | always reserved 8*4=32 we store our |
+ | GPRs here |
+ | r3 |
+ | . |
+ | r10 |
+ +---------------------------------------+ 232
+ | overflow part |
+ +---------------------------------------+ xxx
+ | ???? |
+ +---------------------------------------+ xxx
+*/
+
+#if !defined(POWERPC_DARWIN)
+
+#define MIN_LINE_SIZE 32
+
+static void
+flush_icache(
+ char* addr)
+{
+#ifndef _AIX
+ __asm__ volatile (
+ "dcbf 0,%0\n"
+ "sync\n"
+ "icbi 0,%0\n"
+ "sync\n"
+ "isync"
+ : : "r" (addr) : "memory");
+#endif
+}
+
+static void
+flush_range(
+ char* addr,
+ int size)
+{
+ int i;
+
+ for (i = 0; i < size; i += MIN_LINE_SIZE)
+ flush_icache(addr + i);
+
+ flush_icache(addr + size - 1);
+}
+
+#endif // !defined(POWERPC_DARWIN)
+
+ffi_status
+ffi_prep_closure(
+ ffi_closure* closure,
+ ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*),
+ void* user_data)
+{
+ switch (cif->abi)
+ {
+ case FFI_DARWIN:
+ {
+ FFI_ASSERT (cif->abi == FFI_DARWIN);
+
+ unsigned int* tramp = (unsigned int*)&closure->tramp[0];
+
+#if defined(__ppc64__)
+ tramp[0] = 0x7c0802a6; // mflr r0
+ tramp[1] = 0x429f0005; // bcl 20,31,+0x8
+ tramp[2] = 0x7d6802a6; // mflr r11
+ tramp[3] = 0x7c0803a6; // mtlr r0
+ tramp[4] = 0xe98b0018; // ld r12,24(r11)
+ tramp[5] = 0x7d8903a6; // mtctr r12
+ tramp[6] = 0xe96b0020; // ld r11,32(r11)
+ tramp[7] = 0x4e800420; // bctr
+ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM;
+ *(unsigned long*)&tramp[10] = (unsigned long)closure;
+#elif defined(__ppc__)
+ tramp[0] = 0x7c0802a6; // mflr r0
+ tramp[1] = 0x429f0005; // bcl 20,31,+0x8
+ tramp[2] = 0x7d6802a6; // mflr r11
+ tramp[3] = 0x7c0803a6; // mtlr r0
+ tramp[4] = 0x818b0018; // lwz r12,24(r11)
+ tramp[5] = 0x7d8903a6; // mtctr r12
+ tramp[6] = 0x816b001c; // lwz r11,28(r11)
+ tramp[7] = 0x4e800420; // bctr
+ tramp[8] = (unsigned long)ffi_closure_ASM;
+ tramp[9] = (unsigned long)closure;
+#else
+#error undefined architecture
+#endif
+
+ closure->cif = cif;
+ closure->fun = fun;
+ closure->user_data = user_data;
+
+ // Flush the icache. Only necessary on Darwin.
+#if defined(POWERPC_DARWIN)
+ if (sys_icache_invalidate) {
+ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
+ }
+#else
+ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE);
+#endif
+
+ break;
+ }
+
+ case FFI_AIX:
+ {
+ FFI_ASSERT (cif->abi == FFI_AIX);
+
+ ffi_aix_trampoline_struct* tramp_aix =
+ (ffi_aix_trampoline_struct*)(closure->tramp);
+ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM;
+
+ tramp_aix->code_pointer = fd->code_pointer;
+ tramp_aix->toc = fd->toc;
+ tramp_aix->static_chain = closure;
+ closure->cif = cif;
+ closure->fun = fun;
+ closure->user_data = user_data;
+ break;
+ }
+
+ default:
+ return FFI_BAD_ABI;
+ }
+
+ return FFI_OK;
+}
+
+#if defined(__ppc__)
+ typedef double ldbits[2];
+
+ typedef union
+ {
+ ldbits lb;
+ long double ld;
+ } ldu;
+#endif
+
+/* The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the
+ address of the closure. After storing the registers that could possibly
+ contain parameters to be passed into the stack frame and setting up space
+ for a return value, ffi_closure_ASM invokes the following helper function
+ to do most of the work. */
+int
+ffi_closure_helper_DARWIN(
+ ffi_closure* closure,
+ void* rvalue,
+ unsigned long* pgr,
+ ffi_dblfl* pfr)
+{
+ /* rvalue is the pointer to space for return value in closure assembly
+ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
+ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
+
+#if defined(__ppc__)
+ ldu temp_ld;
+#endif
+
+ double temp;
+ unsigned int i;
+ unsigned int nf = 0; /* number of FPRs already used. */
+ unsigned int ng = 0; /* number of GPRs already used. */
+ ffi_cif* cif = closure->cif;
+ unsigned int avn = cif->nargs;
+ void** avalue = alloca(cif->nargs * sizeof(void*));
+ ffi_type** arg_types = cif->arg_types;
+
+ /* Copy the caller's structure return value address so that the closure
+ returns the data directly to the caller. */
+#if defined(__ppc64__)
+ if (cif->rtype->type == FFI_TYPE_STRUCT &&
+ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL))
+#elif defined(__ppc__)
+ if (cif->rtype->type == FFI_TYPE_STRUCT)
+#else
+#error undefined architecture
+#endif
+ {
+ rvalue = (void*)*pgr;
+ pgr++;
+ ng++;
+ }
+
+ /* Grab the addresses of the arguments from the stack frame. */
+ for (i = 0; i < avn; i++)
+ {
+ switch (arg_types[i]->type)
+ {
+ case FFI_TYPE_SINT8:
+ case FFI_TYPE_UINT8:
+ avalue[i] = (char*)pgr + MODE_CHOICE(3,7);
+ ng++;
+ pgr++;
+ break;
+
+ case FFI_TYPE_SINT16:
+ case FFI_TYPE_UINT16:
+ avalue[i] = (char*)pgr + MODE_CHOICE(2,6);
+ ng++;
+ pgr++;
+ break;
+
+#if defined(__ppc__)
+ case FFI_TYPE_POINTER:
+#endif
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_UINT32:
+ avalue[i] = (char*)pgr + MODE_CHOICE(0,4);
+ ng++;
+ pgr++;
+
+ break;
+
+ case FFI_TYPE_STRUCT:
+ if (cif->abi == FFI_DARWIN)
+ {
+#if defined(__ppc64__)
+ unsigned int gprSize = 0;
+ unsigned int fprSize = 0;
+ unsigned int savedFPRSize = fprSize;
+
+ avalue[i] = alloca(arg_types[i]->size);
+ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr,
+ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL);
+
+ ng += gprSize / sizeof(long);
+ pgr += gprSize / sizeof(long);
+ pfr += (fprSize - savedFPRSize) / sizeof(double);
+
+#elif defined(__ppc__)
+ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+ SI 4 bytes) are aligned as if they were those modes. */
+ unsigned int size_al = size_al = arg_types[i]->size;
+
+ /* If the first member of the struct is a double, then align
+ the struct to double-word. */
+ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
+ size_al = ALIGN(arg_types[i]->size, 8);
+
+ if (size_al < 3)
+ avalue[i] = (char*)pgr + MODE_CHOICE(4,8) - size_al;
+ else
+ avalue[i] = (char*)pgr;
+
+ ng += (size_al + 3) / sizeof(long);
+ pgr += (size_al + 3) / sizeof(long);
+#else
+#error undefined architecture
+#endif
+ }
+
+ break;
+
+#if defined(__ppc64__)
+ case FFI_TYPE_POINTER:
+#endif
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_UINT64:
+ /* Long long ints are passed in 1 or 2 GPRs. */
+ avalue[i] = pgr;
+ ng += MODE_CHOICE(2,1);
+ pgr += MODE_CHOICE(2,1);
+
+ break;
+
+ case FFI_TYPE_FLOAT:
+ /* A float value consumes a GPR.
+ There are 13 64-bit floating point registers. */
+ if (nf < NUM_FPR_ARG_REGISTERS)
+ {
+ temp = pfr->d;
+ pfr->f = (float)temp;
+ avalue[i] = pfr;
+ pfr++;
+ }
+ else
+ avalue[i] = pgr;
+
+ nf++;
+ ng++;
+ pgr++;
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ /* A double value consumes one or two GPRs.
+ There are 13 64bit floating point registers. */
+ if (nf < NUM_FPR_ARG_REGISTERS)
+ {
+ avalue[i] = pfr;
+ pfr++;
+ }
+ else
+ avalue[i] = pgr;
+
+ nf++;
+ ng += MODE_CHOICE(2,1);
+ pgr += MODE_CHOICE(2,1);
+
+ break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+ case FFI_TYPE_LONGDOUBLE:
+#if defined(__ppc64__)
+ if (nf < NUM_FPR_ARG_REGISTERS)
+ {
+ avalue[i] = pfr;
+ pfr += 2;
+ }
+#elif defined(__ppc__)
+ /* A long double value consumes 2/4 GPRs and 2 FPRs.
+ There are 13 64bit floating point registers. */
+ if (nf < NUM_FPR_ARG_REGISTERS - 1)
+ {
+ avalue[i] = pfr;
+ pfr += 2;
+ }
+ /* Here we have the situation where one part of the long double
+ is stored in fpr13 and the other part is already on the stack.
+ We use a union to pass the long double to avalue[i]. */
+ else if (nf == NUM_FPR_ARG_REGISTERS - 1)
+ {
+ memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
+ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
+ avalue[i] = &temp_ld.ld;
+ }
+#else
+#error undefined architecture
+#endif
+ else
+ avalue[i] = pgr;
+
+ nf += 2;
+ ng += MODE_CHOICE(4,2);
+ pgr += MODE_CHOICE(4,2);
+
+ break;
+
+#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+ }
+
+ (closure->fun)(cif, rvalue, avalue, closure->user_data);
+
+ /* Tell ffi_closure_ASM to perform return type promotions. */
+ return cif->rtype->type;
+}
+
+#if defined(__ppc64__)
+
+/* ffi64_struct_to_ram_form
+
+ Rebuild a struct's natural layout from buffers of concatenated registers.
+ Return the number of registers used.
+ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ...
+*/
+void
+ffi64_struct_to_ram_form(
+ const ffi_type* inType,
+ const char* inGPRs,
+ unsigned int* ioGPRMarker,
+ const char* inFPRs,
+ unsigned int* ioFPRMarker,
+ unsigned int* ioFPRsUsed,
+ char* outStruct, // caller-allocated
+ unsigned int* ioStructMarker)
+{
+ unsigned int srcGMarker = 0;
+ unsigned int srcFMarker = 0;
+ unsigned int savedFMarker = 0;
+ unsigned int fprsUsed = 0;
+ unsigned int savedFPRsUsed = 0;
+ unsigned int destMarker = 0;
+
+ static unsigned int recurseCount = 0;
+
+ if (ioGPRMarker)
+ srcGMarker = *ioGPRMarker;
+
+ if (ioFPRMarker)
+ {
+ srcFMarker = *ioFPRMarker;
+ savedFMarker = srcFMarker;
+ }
+
+ if (ioFPRsUsed)
+ {
+ fprsUsed = *ioFPRsUsed;
+ savedFPRsUsed = fprsUsed;
+ }
+
+ if (ioStructMarker)
+ destMarker = *ioStructMarker;
+
+ size_t i;
+
+ switch (inType->size)
+ {
+ case 1: case 2: case 4:
+ srcGMarker += 8 - inType->size;
+ break;
+
+ default:
+ break;
+ }
+
+ for (i = 0; inType->elements[i] != NULL; i++)
+ {
+ switch (inType->elements[i]->type)
+ {
+ case FFI_TYPE_FLOAT:
+ srcFMarker = ALIGN(srcFMarker, 4);
+ srcGMarker = ALIGN(srcGMarker, 4);
+ destMarker = ALIGN(destMarker, 4);
+
+ if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+ {
+ *(float*)&outStruct[destMarker] =
+ (float)*(double*)&inFPRs[srcFMarker];
+ srcFMarker += 8;
+ fprsUsed++;
+ }
+ else
+ *(float*)&outStruct[destMarker] =
+ (float)*(double*)&inGPRs[srcGMarker];
+
+ srcGMarker += 4;
+ destMarker += 4;
+
+ // Skip to next GPR if next element won't fit and we're
+ // not already at a register boundary.
+ if (inType->elements[i + 1] != NULL && (destMarker % 8))
+ {
+ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) &&
+ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(srcGMarker, 8) - srcGMarker) < 4))
+ srcGMarker = ALIGN(srcGMarker, 8);
+ }
+
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ srcFMarker = ALIGN(srcFMarker, 8);
+ destMarker = ALIGN(destMarker, 8);
+
+ if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+ {
+ *(double*)&outStruct[destMarker] =
+ *(double*)&inFPRs[srcFMarker];
+ srcFMarker += 8;
+ fprsUsed++;
+ }
+ else
+ *(double*)&outStruct[destMarker] =
+ *(double*)&inGPRs[srcGMarker];
+
+ destMarker += 8;
+
+ // Skip next GPR
+ srcGMarker += 8;
+ srcGMarker = ALIGN(srcGMarker, 8);
+
+ break;
+
+ case FFI_TYPE_LONGDOUBLE:
+ destMarker = ALIGN(destMarker, 16);
+
+ if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+ {
+ srcFMarker = ALIGN(srcFMarker, 8);
+ srcGMarker = ALIGN(srcGMarker, 8);
+ *(long double*)&outStruct[destMarker] =
+ *(long double*)&inFPRs[srcFMarker];
+ srcFMarker += 16;
+ fprsUsed += 2;
+ }
+ else
+ {
+ srcFMarker = ALIGN(srcFMarker, 16);
+ srcGMarker = ALIGN(srcGMarker, 16);
+ *(long double*)&outStruct[destMarker] =
+ *(long double*)&inGPRs[srcGMarker];
+ }
+
+ destMarker += 16;
+
+ // Skip next 2 GPRs
+ srcGMarker += 16;
+ srcGMarker = ALIGN(srcGMarker, 8);
+
+ break;
+
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_SINT8:
+ {
+ if (inType->alignment == 1) // chars only
+ {
+ if (inType->size == 1)
+ outStruct[destMarker++] = inGPRs[srcGMarker++];
+ else if (inType->size == 2)
+ {
+ outStruct[destMarker++] = inGPRs[srcGMarker++];
+ outStruct[destMarker++] = inGPRs[srcGMarker++];
+ i++;
+ }
+ else
+ {
+ memcpy(&outStruct[destMarker],
+ &inGPRs[srcGMarker], inType->size);
+ srcGMarker += inType->size;
+ destMarker += inType->size;
+ i += inType->size - 1;
+ }
+ }
+ else // chars and other stuff
+ {
+ outStruct[destMarker++] = inGPRs[srcGMarker++];
+
+ // Skip to next GPR if next element won't fit and we're
+ // not already at a register boundary.
+ if (inType->elements[i + 1] != NULL && (srcGMarker % 8))
+ {
+ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) &&
+ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(srcGMarker, 8) - srcGMarker) < 4))
+ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8
+ }
+ }
+
+ break;
+ }
+
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_SINT16:
+ srcGMarker = ALIGN(srcGMarker, 2);
+ destMarker = ALIGN(destMarker, 2);
+
+ *(short*)&outStruct[destMarker] =
+ *(short*)&inGPRs[srcGMarker];
+ srcGMarker += 2;
+ destMarker += 2;
+
+ break;
+
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ srcGMarker = ALIGN(srcGMarker, 4);
+ destMarker = ALIGN(destMarker, 4);
+
+ *(int*)&outStruct[destMarker] =
+ *(int*)&inGPRs[srcGMarker];
+ srcGMarker += 4;
+ destMarker += 4;
+
+ break;
+
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ srcGMarker = ALIGN(srcGMarker, 8);
+ destMarker = ALIGN(destMarker, 8);
+
+ *(long long*)&outStruct[destMarker] =
+ *(long long*)&inGPRs[srcGMarker];
+ srcGMarker += 8;
+ destMarker += 8;
+
+ break;
+
+ case FFI_TYPE_STRUCT:
+ recurseCount++;
+ ffi64_struct_to_ram_form(inType->elements[i], inGPRs,
+ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed,
+ outStruct, &destMarker);
+ recurseCount--;
+ break;
+
+ default:
+ FFI_ASSERT(0); // unknown element type
+ break;
+ }
+ }
+
+ srcGMarker = ALIGN(srcGMarker, inType->alignment);
+
+ // Take care of the special case for 16-byte structs, but not for
+ // nested structs.
+ if (recurseCount == 0 && srcGMarker == 16)
+ {
+ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0];
+ srcFMarker = savedFMarker;
+ fprsUsed = savedFPRsUsed;
+ }
+
+ if (ioGPRMarker)
+ *ioGPRMarker = ALIGN(srcGMarker, 8);
+
+ if (ioFPRMarker)
+ *ioFPRMarker = srcFMarker;
+
+ if (ioFPRsUsed)
+ *ioFPRsUsed = fprsUsed;
+
+ if (ioStructMarker)
+ *ioStructMarker = ALIGN(destMarker, 8);
+}
+
+/* ffi64_struct_to_reg_form
+
+ Copy a struct's elements into buffers that can be sliced into registers.
+ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers
+ to calculate size only.
+ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ...
+*/
+void
+ffi64_struct_to_reg_form(
+ const ffi_type* inType,
+ const char* inStruct,
+ unsigned int* ioStructMarker,
+ unsigned int* ioFPRsUsed,
+ char* outGPRs, // caller-allocated
+ unsigned int* ioGPRSize,
+ char* outFPRs, // caller-allocated
+ unsigned int* ioFPRSize)
+{
+ size_t i;
+ unsigned int srcMarker = 0;
+ unsigned int destGMarker = 0;
+ unsigned int destFMarker = 0;
+ unsigned int savedFMarker = 0;
+ unsigned int fprsUsed = 0;
+ unsigned int savedFPRsUsed = 0;
+
+ static unsigned int recurseCount = 0;
+
+ if (ioStructMarker)
+ srcMarker = *ioStructMarker;
+
+ if (ioFPRsUsed)
+ {
+ fprsUsed = *ioFPRsUsed;
+ savedFPRsUsed = fprsUsed;
+ }
+
+ if (ioGPRSize)
+ destGMarker = *ioGPRSize;
+
+ if (ioFPRSize)
+ {
+ destFMarker = *ioFPRSize;
+ savedFMarker = destFMarker;
+ }
+
+ switch (inType->size)
+ {
+ case 1: case 2: case 4:
+ destGMarker += 8 - inType->size;
+ break;
+
+ default:
+ break;
+ }
+
+ for (i = 0; inType->elements[i] != NULL; i++)
+ {
+ switch (inType->elements[i]->type)
+ {
+ // Shadow floating-point types in GPRs for vararg and pre-ANSI
+ // functions.
+ case FFI_TYPE_FLOAT:
+ // Nudge markers to next 4/8-byte boundary
+ srcMarker = ALIGN(srcMarker, 4);
+ destGMarker = ALIGN(destGMarker, 4);
+ destFMarker = ALIGN(destFMarker, 8);
+
+ if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+ {
+ if (outFPRs != NULL && inStruct != NULL)
+ *(double*)&outFPRs[destFMarker] =
+ (double)*(float*)&inStruct[srcMarker];
+
+ destFMarker += 8;
+ fprsUsed++;
+ }
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(double*)&outGPRs[destGMarker] =
+ (double)*(float*)&inStruct[srcMarker];
+
+ srcMarker += 4;
+ destGMarker += 4;
+
+ // Skip to next GPR if next element won't fit and we're
+ // not already at a register boundary.
+ if (inType->elements[i + 1] != NULL && (srcMarker % 8))
+ {
+ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(destGMarker, 8) - destGMarker) < 2) &&
+ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(destGMarker, 8) - destGMarker) < 4))
+ destGMarker = ALIGN(destGMarker, 8);
+ }
+
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ srcMarker = ALIGN(srcMarker, 8);
+ destFMarker = ALIGN(destFMarker, 8);
+
+ if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+ {
+ if (outFPRs != NULL && inStruct != NULL)
+ *(double*)&outFPRs[destFMarker] =
+ *(double*)&inStruct[srcMarker];
+
+ destFMarker += 8;
+ fprsUsed++;
+ }
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(double*)&outGPRs[destGMarker] =
+ *(double*)&inStruct[srcMarker];
+
+ srcMarker += 8;
+
+ // Skip next GPR
+ destGMarker += 8;
+ destGMarker = ALIGN(destGMarker, 8);
+
+ break;
+
+ case FFI_TYPE_LONGDOUBLE:
+ srcMarker = ALIGN(srcMarker, 16);
+
+ if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+ {
+ destFMarker = ALIGN(destFMarker, 8);
+ destGMarker = ALIGN(destGMarker, 8);
+
+ if (outFPRs != NULL && inStruct != NULL)
+ *(long double*)&outFPRs[destFMarker] =
+ *(long double*)&inStruct[srcMarker];
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(long double*)&outGPRs[destGMarker] =
+ *(long double*)&inStruct[srcMarker];
+
+ destFMarker += 16;
+ fprsUsed += 2;
+ }
+ else
+ {
+ destGMarker = ALIGN(destGMarker, 16);
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(long double*)&outGPRs[destGMarker] =
+ *(long double*)&inStruct[srcMarker];
+ }
+
+ srcMarker += 16;
+ destGMarker += 16; // Skip next 2 GPRs
+ destGMarker = ALIGN(destGMarker, 8); // was 16
+
+ break;
+
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_SINT8:
+ if (inType->alignment == 1) // bytes only
+ {
+ if (inType->size == 1)
+ {
+ if (outGPRs != NULL && inStruct != NULL)
+ outGPRs[destGMarker] = inStruct[srcMarker];
+
+ srcMarker++;
+ destGMarker++;
+ }
+ else if (inType->size == 2)
+ {
+ if (outGPRs != NULL && inStruct != NULL)
+ {
+ outGPRs[destGMarker] = inStruct[srcMarker];
+ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1];
+ }
+
+ srcMarker += 2;
+ destGMarker += 2;
+
+ i++;
+ }
+ else
+ {
+ if (outGPRs != NULL && inStruct != NULL)
+ {
+ // Avoid memcpy for small chunks.
+ if (inType->size <= sizeof(long))
+ *(long*)&outGPRs[destGMarker] =
+ *(long*)&inStruct[srcMarker];
+ else
+ memcpy(&outGPRs[destGMarker],
+ &inStruct[srcMarker], inType->size);
+ }
+
+ srcMarker += inType->size;
+ destGMarker += inType->size;
+ i += inType->size - 1;
+ }
+ }
+ else // bytes and other stuff
+ {
+ if (outGPRs != NULL && inStruct != NULL)
+ outGPRs[destGMarker] = inStruct[srcMarker];
+
+ srcMarker++;
+ destGMarker++;
+
+ // Skip to next GPR if next element won't fit and we're
+ // not already at a register boundary.
+ if (inType->elements[i + 1] != NULL && (destGMarker % 8))
+ {
+ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(destGMarker, 8) - destGMarker) < 2) &&
+ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+ (ALIGN(destGMarker, 8) - destGMarker) < 4))
+ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8
+ }
+ }
+
+ break;
+
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_SINT16:
+ srcMarker = ALIGN(srcMarker, 2);
+ destGMarker = ALIGN(destGMarker, 2);
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(short*)&outGPRs[destGMarker] =
+ *(short*)&inStruct[srcMarker];
+
+ srcMarker += 2;
+ destGMarker += 2;
+
+ if (inType->elements[i + 1] == NULL)
+ destGMarker = ALIGN(destGMarker, inType->alignment);
+
+ break;
+
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ srcMarker = ALIGN(srcMarker, 4);
+ destGMarker = ALIGN(destGMarker, 4);
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(int*)&outGPRs[destGMarker] =
+ *(int*)&inStruct[srcMarker];
+
+ srcMarker += 4;
+ destGMarker += 4;
+
+ break;
+
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ srcMarker = ALIGN(srcMarker, 8);
+ destGMarker = ALIGN(destGMarker, 8);
+
+ if (outGPRs != NULL && inStruct != NULL)
+ *(long long*)&outGPRs[destGMarker] =
+ *(long long*)&inStruct[srcMarker];
+
+ srcMarker += 8;
+ destGMarker += 8;
+
+ if (inType->elements[i + 1] == NULL)
+ destGMarker = ALIGN(destGMarker, inType->alignment);
+
+ break;
+
+ case FFI_TYPE_STRUCT:
+ recurseCount++;
+ ffi64_struct_to_reg_form(inType->elements[i],
+ inStruct, &srcMarker, &fprsUsed, outGPRs,
+ &destGMarker, outFPRs, &destFMarker);
+ recurseCount--;
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+ }
+
+ destGMarker = ALIGN(destGMarker, inType->alignment);
+
+ // Take care of the special case for 16-byte structs, but not for
+ // nested structs.
+ if (recurseCount == 0 && destGMarker == 16)
+ {
+ if (outGPRs != NULL && inStruct != NULL)
+ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0];
+
+ destFMarker = savedFMarker;
+ fprsUsed = savedFPRsUsed;
+ }
+
+ if (ioStructMarker)
+ *ioStructMarker = ALIGN(srcMarker, 8);
+
+ if (ioFPRsUsed)
+ *ioFPRsUsed = fprsUsed;
+
+ if (ioGPRSize)
+ *ioGPRSize = ALIGN(destGMarker, 8);
+
+ if (ioFPRSize)
+ *ioFPRSize = ALIGN(destFMarker, 8);
+}
+
+/* ffi64_stret_needs_ptr
+
+ Determine whether a returned struct needs a pointer in r3 or can fit
+ in registers.
+*/
+
+bool
+ffi64_stret_needs_ptr(
+ const ffi_type* inType,
+ unsigned short* ioGPRCount,
+ unsigned short* ioFPRCount)
+{
+ // Obvious case first- struct is larger than combined FPR size.
+ if (inType->size > 14 * 8)
+ return true;
+
+ // Now the struct can physically fit in registers, determine if it
+ // also fits logically.
+ bool needsPtr = false;
+ unsigned short gprsUsed = 0;
+ unsigned short fprsUsed = 0;
+ size_t i;
+
+ if (ioGPRCount)
+ gprsUsed = *ioGPRCount;
+
+ if (ioFPRCount)
+ fprsUsed = *ioFPRCount;
+
+ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++)
+ {
+ switch (inType->elements[i]->type)
+ {
+ case FFI_TYPE_FLOAT:
+ case FFI_TYPE_DOUBLE:
+ gprsUsed++;
+ fprsUsed++;
+
+ if (fprsUsed > 13)
+ needsPtr = true;
+
+ break;
+
+ case FFI_TYPE_LONGDOUBLE:
+ gprsUsed += 2;
+ fprsUsed += 2;
+
+ if (fprsUsed > 14)
+ needsPtr = true;
+
+ break;
+
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_SINT8:
+ {
+ gprsUsed++;
+
+ if (gprsUsed > 8)
+ {
+ needsPtr = true;
+ break;
+ }
+
+ if (inType->elements[i + 1] == NULL) // last byte in the struct
+ break;
+
+ // Count possible contiguous bytes ahead, up to 8.
+ unsigned short j;
+
+ for (j = 1; j < 8; j++)
+ {
+ if (inType->elements[i + j] == NULL ||
+ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type))
+ break;
+ }
+
+ i += j - 1; // allow for i++ before the test condition
+
+ break;
+ }
+
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_SINT16:
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ gprsUsed++;
+
+ if (gprsUsed > 8)
+ needsPtr = true;
+
+ break;
+
+ case FFI_TYPE_STRUCT:
+ needsPtr = ffi64_stret_needs_ptr(
+ inType->elements[i], &gprsUsed, &fprsUsed);
+
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+ }
+
+ if (ioGPRCount)
+ *ioGPRCount = gprsUsed;
+
+ if (ioFPRCount)
+ *ioFPRCount = fprsUsed;
+
+ return needsPtr;
+}
+
+/* ffi64_data_size
+
+ Calculate the size in bytes of an ffi type.
+*/
+
+unsigned int
+ffi64_data_size(
+ const ffi_type* inType)
+{
+ unsigned int size = 0;
+
+ switch (inType->type)
+ {
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_SINT8:
+ size = 1;
+ break;
+
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_SINT16:
+ size = 2;
+ break;
+
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_FLOAT:
+ size = 4;
+ break;
+
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_DOUBLE:
+ size = 8;
+ break;
+
+ case FFI_TYPE_LONGDOUBLE:
+ size = 16;
+ break;
+
+ case FFI_TYPE_STRUCT:
+ ffi64_struct_to_reg_form(
+ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL);
+ break;
+
+ case FFI_TYPE_VOID:
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+
+ return size;
+}
+
+#endif /* defined(__ppc64__) */
+#endif /* __ppc__ || __ppc64__ */
diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S b/Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
new file mode 100644
index 0000000..248d43a
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
@@ -0,0 +1,423 @@
+#if defined(__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 0x90 ; FDE Encoding (indirect pcrel)
+ .byte 0xc ; DW_CFA_def_cfa
+ .byte 0x1 ; uleb128 0x1
+ .byte 0x0 ; uleb128 0x0
+ .align LOG2_GPR_BYTES
+LECIE1:
+.globl _ffi_closure_ASM.eh
+_ffi_closure_ASM.eh:
+LSFDE1:
+ .set L$set$1,LEFDE1-LASFDE1
+ .long L$set$1 ; FDE Length
+
+LASFDE1:
+ .long LASFDE1-EH_frame1 ; FDE CIE offset
+ .g_long LLFB1$non_lazy_ptr-. ; FDE initial location
+ .set L$set$3,LFE1-LFB1
+ .g_long L$set$3 ; FDE address range
+ .byte 0x0 ; uleb128 0x0; Augmentation size
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$3,LCFI1-LCFI0
+ .long L$set$3
+ .byte 0xe ; DW_CFA_def_cfa_offset
+ .byte 176,1 ; uleb128 176
+ .byte 0x4 ; DW_CFA_advance_loc4
+ .set L$set$4,LCFI0-LFB1
+ .long L$set$4
+ .byte 0x11 ; DW_CFA_offset_extended_sf
+ .byte 0x41 ; uleb128 0x41
+ .byte 0x7e ; sleb128 -2
+ .align LOG2_GPR_BYTES
+
+LEFDE1:
+.data
+ .align LOG2_GPR_BYTES
+LDFCM0:
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+ .align LOG2_GPR_BYTES
+
+Lffi_closure_helper_DARWIN$stub:
+ .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
+
+.data
+ .align LOG2_GPR_BYTES
+LLFB1$non_lazy_ptr:
+ .g_long LFB1
+
+.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__
diff --git a/Modules/_ctypes/libffi_osx/types.c b/Modules/_ctypes/libffi_osx/types.c
new file mode 100644
index 0000000..44806ae
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/types.c
@@ -0,0 +1,115 @@
+/* -----------------------------------------------------------------------
+ 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 \ No newline at end of file
diff --git a/Modules/_ctypes/libffi_osx/x86/darwin64.S b/Modules/_ctypes/libffi_osx/x86/darwin64.S
new file mode 100644
index 0000000..eba451e
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/x86/darwin64.S
@@ -0,0 +1,415 @@
+/* -----------------------------------------------------------------------
+ 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. */
+ 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 %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 a 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__ */
diff --git a/Modules/_ctypes/libffi_osx/x86/x86-darwin.S b/Modules/_ctypes/libffi_osx/x86/x86-darwin.S
new file mode 100644
index 0000000..d91bdc0
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/x86/x86-darwin.S
@@ -0,0 +1,243 @@
+#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
+ subl $8,%esp
+ ASSERT_STACK_ALIGNED
+.LCFI1:
+ /* Make room for all of the new args. */
+ movl 16(%ebp),%ecx
+ subl %ecx,%esp
+
+ ASSERT_STACK_ALIGNED
+
+ movl %esp,%eax
+
+ /* Place all of the ffi_prep_args in position */
+ subl $8,%esp
+ pushl 12(%ebp)
+ pushl %eax
+ call *8(%ebp)
+
+ ASSERT_STACK_ALIGNED
+
+ /* Return stack to previous state and call the function */
+ addl $16,%esp
+
+ ASSERT_STACK_ALIGNED
+
+ call *28(%ebp)
+
+ /* XXX: return returns return with 'ret $4', that upsets the stack! */
+ 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 retint
+
+ /* Even if there is no space for the return value, we are
+ obliged to handle floating-point values. */
+ cmpl $FFI_TYPE_FLOAT,%ecx
+ jne noretval
+ fstp %st(0)
+
+ jmp epilogue
+
+retint:
+ cmpl $FFI_TYPE_INT,%ecx
+ jne retfloat
+ /* Load %ecx with the pointer to storage for the return value */
+ movl 24(%ebp),%ecx
+ movl %eax,0(%ecx)
+ jmp epilogue
+
+retfloat:
+ cmpl $FFI_TYPE_FLOAT,%ecx
+ jne retdouble
+ /* Load %ecx with the pointer to storage for the return value */
+ movl 24(%ebp),%ecx
+ fstps (%ecx)
+ jmp epilogue
+
+retdouble:
+ cmpl $FFI_TYPE_DOUBLE,%ecx
+ jne retlongdouble
+ /* Load %ecx with the pointer to storage for the return value */
+ movl 24(%ebp),%ecx
+ fstpl (%ecx)
+ jmp epilogue
+
+retlongdouble:
+ cmpl $FFI_TYPE_LONGDOUBLE,%ecx
+ jne retint64
+ /* Load %ecx with the pointer to storage for the return value */
+ movl 24(%ebp),%ecx
+ fstpt (%ecx)
+ jmp epilogue
+
+retint64:
+ cmpl $FFI_TYPE_SINT64,%ecx
+ jne retstruct1b
+ /* Load %ecx with the pointer to storage for the return value */
+ movl 24(%ebp),%ecx
+ movl %eax,0(%ecx)
+ movl %edx,4(%ecx)
+ jmp epilogue
+
+retstruct1b:
+ cmpl $FFI_TYPE_SINT8,%ecx
+ jne retstruct2b
+ movl 24(%ebp),%ecx
+ movb %al,0(%ecx)
+ jmp epilogue
+
+retstruct2b:
+ cmpl $FFI_TYPE_SINT16,%ecx
+ jne retstruct
+ movl 24(%ebp),%ecx
+ movw %ax,0(%ecx)
+ jmp epilogue
+
+retstruct:
+ cmpl $FFI_TYPE_STRUCT,%ecx
+ jne noretval
+ /* Nothing to do! */
+
+ subl $4,%esp
+
+ ASSERT_STACK_ALIGNED
+
+ addl $8,%esp
+ movl %ebp, %esp
+ popl %ebp
+ ret
+
+noretval:
+epilogue:
+ ASSERT_STACK_ALIGNED
+ addl $8, %esp
+
+
+ movl %ebp,%esp
+ popl %ebp
+ ret
+.LFE1:
+.ffi_call_SYSV_end:
+#if 0
+ .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+#endif
+
+#if 0
+ .section .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+ .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+ .long 0x0 /* CIE Identifier Tag */
+ .byte 0x1 /* CIE Version */
+#ifdef __PIC__
+ .ascii "zR\0" /* CIE Augmentation */
+#else
+ .ascii "\0" /* CIE Augmentation */
+#endif
+ .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
+ .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
+ .byte 0x8 /* CIE RA Column */
+#ifdef __PIC__
+ .byte 0x1 /* .uleb128 0x1; Augmentation size */
+ .byte 0x1b /* FDE Encoding (pcrel sdata4) */
+#endif
+ .byte 0xc /* DW_CFA_def_cfa */
+ .byte 0x4 /* .uleb128 0x4 */
+ .byte 0x4 /* .uleb128 0x4 */
+ .byte 0x88 /* DW_CFA_offset, column 0x8 */
+ .byte 0x1 /* .uleb128 0x1 */
+ .align 4
+.LECIE1:
+.LSFDE1:
+ .long .LEFDE1-.LASFDE1 /* FDE Length */
+.LASFDE1:
+ .long .LASFDE1-.Lframe1 /* FDE CIE offset */
+#ifdef __PIC__
+ .long .LFB1-. /* FDE initial location */
+#else
+ .long .LFB1 /* FDE initial location */
+#endif
+ .long .LFE1-.LFB1 /* FDE address range */
+#ifdef __PIC__
+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
+#endif
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI0-.LFB1
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .byte 0x8 /* .uleb128 0x8 */
+ .byte 0x85 /* DW_CFA_offset, column 0x5 */
+ .byte 0x2 /* .uleb128 0x2 */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI1-.LCFI0
+ .byte 0xd /* DW_CFA_def_cfa_register */
+ .byte 0x5 /* .uleb128 0x5 */
+ .align 4
+.LEFDE1:
+#endif
+
+#endif /* ifndef __x86_64__ */
+
+#endif /* defined __i386__ */
diff --git a/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c b/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
new file mode 100644
index 0000000..ac37fb7
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
@@ -0,0 +1,624 @@
+#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)(),
+ 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.
+
+ Similary 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 (byte_offset + type->size <= 4)
+ classes[0] = X86_64_INTEGERSI_CLASS;
+ else
+ classes[0] = X86_64_INTEGER_CLASS;
+
+ return 1;
+
+ 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++)
+ {
+ byte_offset = ALIGN(byte_offset, (*ptr)->alignment);
+
+ int num = classify_argument(*ptr, subclasses, byte_offset % 8);
+
+ if (num == 0)
+ return 0;
+
+ int pos = byte_offset / 8;
+
+ for (i = 0; i < num; i++)
+ {
+ classes[i + pos] =
+ merge_classes(subclasses[i], classes[i + pos]);
+ }
+
+ byte_offset += (*ptr)->size;
+ }
+
+ /* 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
+ && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
+ 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
+ && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
+ 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;
+
+ return FFI_OK;
+}
+
+void
+ffi_call(
+ ffi_cif* cif,
+ void (*fn)(),
+ 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;
+ memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
+ 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)
+{
+ if (cif->abi != FFI_UNIX64)
+ return FFI_BAD_ABI;
+
+ volatile unsigned short* 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;
+}
+
+int
+ffi_closure_unix64_inner(
+ ffi_closure* closure,
+ void* rvalue,
+ RegisterArgs* reg_args,
+ char* argp)
+{
+ ffi_cif* cif = closure->cif;
+ void** avalue = alloca(cif->nargs * sizeof(void *));
+ ffi_type** arg_types;
+ long i, avn;
+ int gprcount = 0;
+ int ssecount = 0;
+ int ngpr, nsse;
+ int ret;
+
+ ret = cif->rtype->type;
+
+ if (ret != FFI_TYPE_VOID)
+ {
+ enum x86_64_reg_class classes[MAX_CLASSES];
+ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+
+ if (n == 0)
+ {
+ /* The return value goes in memory. Arrange for the closure
+ return value to go directly back to the original caller. */
+ rvalue = (void *) reg_args->gpr[gprcount++];
+
+ /* We don't have to do anything in asm for the return. */
+ ret = FFI_TYPE_VOID;
+ }
+ else if (ret == FFI_TYPE_STRUCT && n == 2)
+ {
+ /* Mark which register the second word of the structure goes in. */
+ _Bool sse0 = SSE_CLASS_P (classes[0]);
+ _Bool sse1 = SSE_CLASS_P (classes[1]);
+
+ if (!sse0 && sse1)
+ ret |= 1 << 8;
+ else if (sse0 && !sse1)
+ ret |= 1 << 9;
+ }
+ }
+
+ avn = cif->nargs;
+ arg_types = cif->arg_types;
+
+ for (i = 0; i < avn; ++i)
+ {
+ enum x86_64_reg_class classes[MAX_CLASSES];
+ int n;
+
+ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+
+ if (n == 0
+ || gprcount + ngpr > MAX_GPR_REGS
+ || ssecount + nsse > MAX_SSE_REGS)
+ {
+ long align = arg_types[i]->alignment;
+
+ /* Stack arguments are *always* at least 8 byte aligned. */
+ if (align < 8)
+ align = 8;
+
+ /* Pass this argument in memory. */
+ argp = (void *) ALIGN (argp, align);
+ avalue[i] = argp;
+ argp += arg_types[i]->size;
+ }
+
+#if !defined(X86_DARWIN)
+ /* If the argument is in a single register, or two consecutive
+ registers, then we can use that address directly. */
+ else if (n == 1 || (n == 2 &&
+ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
+ {
+ // The argument is in a single register.
+ if (SSE_CLASS_P (classes[0]))
+ {
+ avalue[i] = &reg_args->sse[ssecount];
+ ssecount += n;
+ }
+ else
+ {
+ avalue[i] = &reg_args->gpr[gprcount];
+ gprcount += n;
+ }
+ }
+#endif
+
+ /* Otherwise, allocate space to make them consecutive. */
+ else
+ {
+ char *a = alloca (16);
+ int j;
+
+ avalue[i] = a;
+
+ for (j = 0; j < n; j++, a += 8)
+ {
+ if (SSE_CLASS_P (classes[j]))
+ memcpy (a, &reg_args->sse[ssecount++], 8);
+ else
+ memcpy (a, &reg_args->gpr[gprcount++], 8);
+ }
+ }
+ }
+
+ /* Invoke the closure. */
+ closure->fun (cif, rvalue, avalue, closure->user_data);
+
+ /* Tell assembly how to perform return type promotions. */
+ return ret;
+}
+
+#endif /* __x86_64__ */
diff --git a/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c b/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
new file mode 100644
index 0000000..ce8687d
--- /dev/null
+++ b/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
@@ -0,0 +1,569 @@
+#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.
+ ----------------------------------------------------------------------- */
+
+//#ifndef __x86_64__
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+//void ffi_prep_args(char *stack, extended_cif *ecif);
+
+static inline int
+retval_on_stack(
+ ffi_type* tp)
+{
+ if (tp->type == FFI_TYPE_STRUCT)
+ {
+// int size = tp->size;
+
+ if (tp->size > 8)
+ return 1;
+
+ switch (tp->size)
+ {
+ case 1: case 2: case 4: case 8:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+ has been allocated for the function's arguments */
+/*@-exportheader@*/
+extern void ffi_prep_args(char*, extended_cif*);
+void
+ffi_prep_args(
+ char* stack,
+ extended_cif* ecif)
+/*@=exportheader@*/
+{
+ register unsigned int i;
+ register void** p_argv = ecif->avalue;
+ register char* argp = stack;
+ register ffi_type** p_arg;
+
+ if (retval_on_stack(ecif->cif->rtype))
+ {
+ *(void**)argp = ecif->rvalue;
+ argp += 4;
+ }
+
+ p_arg = ecif->cif->arg_types;
+
+ for (i = ecif->cif->nargs; i > 0; i--, p_arg++, p_argv++)
+ {
+ size_t z = (*p_arg)->size;
+
+ /* Align if necessary */
+ if ((sizeof(int) - 1) & (unsigned)argp)
+ argp = (char*)ALIGN(argp, sizeof(int));
+
+ 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);
+ break;
+ }
+ }
+ else
+ memcpy(argp, *p_argv, z);
+
+ argp += z;
+ }
+}
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep(
+ ffi_cif* cif)
+{
+ /* Set the return type flag */
+ switch (cif->rtype->type)
+ {
+#if !defined(X86_WIN32) && !defined(X86_DARWIN)
+ case FFI_TYPE_STRUCT:
+#endif
+ case FFI_TYPE_VOID:
+ 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;
+
+#if defined(X86_WIN32) || defined(X86_DARWIN)
+ case FFI_TYPE_STRUCT:
+ switch (cif->rtype->size)
+ {
+ case 1:
+ cif->flags = FFI_TYPE_SINT8;
+ break;
+
+ case 2:
+ cif->flags = FFI_TYPE_SINT16;
+ break;
+
+ case 4:
+ cif->flags = FFI_TYPE_INT;
+ break;
+
+ case 8:
+ cif->flags = FFI_TYPE_SINT64;
+ break;
+
+ default:
+ cif->flags = FFI_TYPE_STRUCT;
+ break;
+ }
+
+ break;
+#endif
+
+ default:
+ cif->flags = FFI_TYPE_INT;
+ break;
+ }
+
+ /* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
+ cif->bytes = (cif->bytes + 15) & ~0xF;
+
+ return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void
+ffi_call_SYSV(
+ void (*)(char *, extended_cif *),
+/*@out@*/ extended_cif* ,
+ unsigned ,
+ unsigned ,
+/*@out@*/ unsigned* ,
+ void (*fn)(void));
+/*@=declundef@*/
+/*@=exportheader@*/
+
+#ifdef X86_WIN32
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void
+ffi_call_STDCALL(
+ void (char *, extended_cif *),
+/*@out@*/ extended_cif* ,
+ unsigned ,
+ unsigned ,
+/*@out@*/ unsigned* ,
+ void (*fn)(void));
+/*@=declundef@*/
+/*@=exportheader@*/
+#endif /* X86_WIN32 */
+
+void
+ffi_call(
+/*@dependent@*/ ffi_cif* cif,
+ void (*fn)(void),
+/*@out@*/ void* rvalue,
+/*@dependent@*/ void** avalue)
+{
+ extended_cif ecif;
+
+ ecif.cif = cif;
+ ecif.avalue = avalue;
+
+ /* If the return value is a struct and we don't have a return
+ value address then we need to make one. */
+
+ if ((rvalue == NULL) && retval_on_stack(cif->rtype))
+ {
+ /*@-sysunrecog@*/
+ ecif.rvalue = alloca(cif->rtype->size);
+ /*@=sysunrecog@*/
+ }
+ else
+ ecif.rvalue = rvalue;
+
+ switch (cif->abi)
+ {
+ case FFI_SYSV:
+ /*@-usedef@*/
+ /* To avoid changing the assembly code make sure the size of the argument
+ block is a multiple of 16. Then add 8 to compensate for local variables
+ in ffi_call_SYSV. */
+ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
+ /*@=usedef@*/
+ break;
+
+#ifdef X86_WIN32
+ case FFI_STDCALL:
+ /*@-usedef@*/
+ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
+ /*@=usedef@*/
+ break;
+#endif /* X86_WIN32 */
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+}
+
+/** private members **/
+
+static void
+ffi_closure_SYSV(
+ ffi_closure* closure) __attribute__((regparm(1)));
+
+#if !FFI_NO_RAW_API
+static void
+ffi_closure_raw_SYSV(
+ ffi_raw_closure* closure) __attribute__((regparm(1)));
+#endif
+
+/*@-exportheader@*/
+static inline
+void
+ffi_prep_incoming_args_SYSV(
+ char* stack,
+ void** rvalue,
+ void** avalue,
+ ffi_cif* cif)
+/*@=exportheader@*/
+{
+ register unsigned int i;
+ register void** p_argv = avalue;
+ register char* argp = stack;
+ register ffi_type** p_arg;
+
+ if (retval_on_stack(cif->rtype))
+ {
+ *rvalue = *(void**)argp;
+ argp += 4;
+ }
+
+ for (i = cif->nargs, p_arg = cif->arg_types; i > 0; i--, p_arg++, p_argv++)
+ {
+// 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;
+
+ argp += (*p_arg)->size;
+ }
+}
+
+/* This function is jumped to by the trampoline */
+__attribute__((regparm(1)))
+static void
+ffi_closure_SYSV(
+ ffi_closure* closure)
+{
+ long double res;
+ ffi_cif* cif = closure->cif;
+ void** arg_area = (void**)alloca(cif->nargs * sizeof(void*));
+ void* resp = (void*)&res;
+ void* args = __builtin_dwarf_cfa();
+
+ /* 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 reset RESP to point to the
+ structure return address. */
+ ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
+
+ (closure->fun)(cif, resp, arg_area, closure->user_data);
+
+ /* now, do a generic return based on the value of rtype */
+ if (cif->flags == FFI_TYPE_INT)
+ asm("movl (%0),%%eax"
+ : : "r" (resp) : "eax");
+ else if (cif->flags == FFI_TYPE_FLOAT)
+ asm("flds (%0)"
+ : : "r" (resp) : "st");
+ else if (cif->flags == FFI_TYPE_DOUBLE)
+ asm("fldl (%0)"
+ : : "r" (resp) : "st", "st(1)");
+ else if (cif->flags == FFI_TYPE_LONGDOUBLE)
+ asm("fldt (%0)"
+ : : "r" (resp) : "st", "st(1)");
+ else if (cif->flags == FFI_TYPE_SINT64)
+ asm("movl 0(%0),%%eax;"
+ "movl 4(%0),%%edx"
+ : : "r" (resp)
+ : "eax", "edx");
+
+#if defined(X86_WIN32) || defined(X86_DARWIN)
+ else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct */
+ asm("movsbl (%0),%%eax"
+ : : "r" (resp) : "eax");
+ else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
+ asm("movswl (%0),%%eax"
+ : : "r" (resp) : "eax");
+#endif
+
+ else if (cif->flags == FFI_TYPE_STRUCT)
+ asm("lea -8(%ebp),%esp;"
+ "pop %esi;"
+ "pop %edi;"
+ "pop %ebp;"
+ "ret $4");
+}
+
+
+/* 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 - ((unsigned int)__tramp + 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)
+{
+// FFI_ASSERT(cif->abi == FFI_SYSV);
+ if (cif->abi != FFI_SYSV)
+ return FFI_BAD_ABI;
+
+ FFI_INIT_TRAMPOLINE(closure->tramp, &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
+
+__attribute__((regparm(1)))
+static void
+ffi_closure_raw_SYSV(
+ ffi_raw_closure* closure)
+{
+ long double res;
+ ffi_raw* raw_args = (ffi_raw*)__builtin_dwarf_cfa();
+ ffi_cif* cif = closure->cif;
+ unsigned short rtype = cif->flags;
+ void* resp = (void*)&res;
+
+ (closure->fun)(cif, resp, raw_args, closure->user_data);
+
+ /* now, do a generic return based on the value of rtype */
+ if (rtype == FFI_TYPE_INT)
+ asm("movl (%0),%%eax"
+ : : "r" (resp) : "eax");
+ else if (rtype == FFI_TYPE_FLOAT)
+ asm("flds (%0)"
+ : : "r" (resp) : "st");
+ else if (rtype == FFI_TYPE_DOUBLE)
+ asm("fldl (%0)"
+ : : "r" (resp) : "st", "st(1)");
+ else if (rtype == FFI_TYPE_LONGDOUBLE)
+ asm("fldt (%0)"
+ : : "r" (resp) : "st", "st(1)");
+ else if (rtype == FFI_TYPE_SINT64)
+ asm("movl 0(%0),%%eax;"
+ "movl 4(%0),%%edx"
+ : : "r" (resp) : "eax", "edx");
+}
+
+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_ASSERT (cif->abi == FFI_SYSV);
+ if (cif->abi != FFI_SYSV)
+ return FFI_BAD_ABI;
+
+ int i;
+
+/* 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, &ffi_closure_raw_SYSV, (void*)closure);
+
+ 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 *),
+///*@out@*/ extended_cif* ,
+// unsigned ,
+// unsigned ,
+//*@out@*/ unsigned* ,
+// void (*fn)());
+
+#ifdef X86_WIN32
+extern void
+ffi_call_STDCALL(
+ void (*)(char *, extended_cif *),
+/*@out@*/ extended_cif* ,
+ unsigned ,
+ unsigned ,
+/*@out@*/ unsigned* ,
+ void (*fn)());
+#endif // X86_WIN32
+
+void
+ffi_raw_call(
+/*@dependent@*/ ffi_cif* cif,
+ void (*fn)(),
+/*@out@*/ void* rvalue,
+/*@dependent@*/ 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) && retval_on_stack(cif->rtype))
+ {
+ /*@-sysunrecog@*/
+ ecif.rvalue = alloca(cif->rtype->size);
+ /*@=sysunrecog@*/
+ }
+ else
+ ecif.rvalue = rvalue;
+
+ switch (cif->abi)
+ {
+ case FFI_SYSV:
+ /*@-usedef@*/
+ ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
+ /*@=usedef@*/
+ break;
+#ifdef X86_WIN32
+ case FFI_STDCALL:
+ /*@-usedef@*/
+ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
+ /*@=usedef@*/
+ break;
+#endif /* X86_WIN32 */
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+}
+
+#endif // !FFI_NO_RAW_API
+//#endif // !__x86_64__
+#endif // __i386__