diff --git a/plugins/python-build/share/python-build/patches/2.5.1/Python-2.5.1/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.1/Python-2.5.1/004_osx_libffi.patch
new file mode 100644
index 00000000..cd500771
--- /dev/null
+++ b/plugins/python-build/share/python-build/patches/2.5.1/Python-2.5.1/004_osx_libffi.patch
@@ -0,0 +1,6881 @@
+diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE
+new file mode 100644
+index 0000000..f591795
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README
+new file mode 100644
+index 0000000..1fc2747
+--- /dev/null
++++ ./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: .
++
++
++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
++ #include
++
++ 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
++.
++
++
++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
++ .
++
++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 .
++
++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 . Further enhancements were
++made by Gordon Irlam at Cygnus Solutions .
++
++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 ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc
+new file mode 100644
+index 0000000..405d85f
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c
+new file mode 100644
+index 0000000..bf42093
+--- /dev/null
++++ ./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
++#include
++
++#include
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h
+new file mode 100644
+index 0000000..c104a5c
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/include/ffi.h
+@@ -0,0 +1,355 @@
++/* -----------------------------------------------------------------*-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
++#include
++
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# endif
++#endif
++
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++#error "char size not supported"
++#endif
++
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
++#else
++#error "short size not supported"
++#endif
++
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++#error "int size not supported"
++#endif
++
++#define ffi_type_ulong ffi_type_uint64
++#define ffi_type_slong ffi_type_sint64
++
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != 9223372036854775807
++# error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != 9223372036854775807
++#error "long size not supported"
++#endif
++
++/* The closure code assumes that this works on pointers, i.e. a size_t
++ can hold a pointer. */
++
++typedef struct _ffi_type {
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++/*@null@*/ struct _ffi_type** elements;
++} ffi_type;
++
++/* These are defined in types.c */
++extern ffi_type ffi_type_void;
++extern ffi_type ffi_type_uint8;
++extern ffi_type ffi_type_sint8;
++extern ffi_type ffi_type_uint16;
++extern ffi_type ffi_type_sint16;
++extern ffi_type ffi_type_uint32;
++extern ffi_type ffi_type_sint32;
++extern ffi_type ffi_type_uint64;
++extern ffi_type ffi_type_sint64;
++extern ffi_type ffi_type_float;
++extern ffi_type ffi_type_double;
++extern ffi_type ffi_type_longdouble;
++extern ffi_type ffi_type_pointer;
++
++typedef enum ffi_status {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
++
++typedef unsigned FFI_TYPE;
++
++typedef struct ffi_cif {
++ ffi_abi abi;
++ unsigned nargs;
++/*@dependent@*/ ffi_type** arg_types;
++/*@dependent@*/ ffi_type* rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
++
++/* ---- Definitions for the raw API -------------------------------------- */
++
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == 9223372036854775807
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
++
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
++
++void
++ffi_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_raw_size(
++ ffi_cif* cif);
++
++/* This is analogous to the raw API, except it uses Java parameter
++ packing, even on 64-bit machines. I.e. on 64-bit machines
++ longs and doubles are followed by an empty 64-bit word. */
++void
++ffi_java_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_java_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_java_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_java_raw_size(
++ ffi_cif* cif);
++
++/* ---- Definitions for closures ----------------------------------------- */
++
++#if FFI_CLOSURES
++
++typedef struct ffi_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void* user_data;
++} ffi_closure;
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void* user_data);
++
++void ffi_closure_free(void *);
++void *ffi_closure_alloc (size_t size, void **code);
++
++typedef struct ffi_raw_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++
++#if !FFI_NATIVE_RAW_API
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void* this_closure;
++#endif
++
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void* user_data;
++} ffi_raw_closure;
++
++ffi_status
++ffi_prep_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++ffi_status
++ffi_prep_java_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++#endif // FFI_CLOSURES
++
++/* ---- Public interface definition -------------------------------------- */
++
++ffi_status
++ffi_prep_cif(
++/*@out@*/ /*@partial@*/ ffi_cif* cif,
++ ffi_abi abi,
++ unsigned int nargs,
++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
++/*@dependent@*/ ffi_type** atypes);
++
++void
++ffi_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ void** avalue);
++
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
++
++#endif // #ifndef LIBFFI_ASM
++/* ---- Definitions shared with assembly code ---------------------------- */
++
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++
++#ifdef HAVE_LONG_DOUBLE
++# define FFI_TYPE_LONGDOUBLE 4
++#else
++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_POINTER
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // #ifndef LIBFFI_H
+diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h
+new file mode 100644
+index 0000000..685a358
+--- /dev/null
++++ ./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
++# 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
++#else
++# ifndef HAVE_MEMCPY
++# define memcpy(d, s, n) bcopy((s), (d), (n))
++# endif
++#endif
++
++/*#if defined(FFI_DEBUG)
++#include
++#endif*/
++
++#ifdef FFI_DEBUG
++#include
++
++/*@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 ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h
+new file mode 100644
+index 0000000..2172490
+--- /dev/null
++++ ./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 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 ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h
+new file mode 100644
+index 0000000..faaa30d
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
+new file mode 100644
+index 0000000..2318421
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
+new file mode 100644
+index 0000000..55c2b6c
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+new file mode 100644
+index 0000000..f143dbd
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+@@ -0,0 +1,365 @@
++#if defined(__ppc__) || defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist
++ Copyright (c) 2004 Free Software Foundation, Inc.
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include
++#include
++#include
++
++.text
++ .align 2
++.globl _ffi_prep_args
++
++.text
++ .align 2
++.globl _ffi_call_DARWIN
++
++.text
++ .align 2
++_ffi_call_DARWIN:
++LFB0:
++ mr r12,r8 /* We only need r12 until the call,
++ so it doesn't have to be saved. */
++
++LFB1:
++ /* Save the old stack pointer as AP. */
++ mr r8,r1
++
++LCFI0:
++#if defined(__ppc64__)
++ /* Allocate the stack space we need.
++ r4 (size of input data)
++ 48 bytes (linkage area)
++ 40 bytes (saved registers)
++ 8 bytes (extra FPR)
++ r4 + 96 bytes total
++ */
++
++ addi r4,r4,-96 // Add our overhead.
++ li r0,-32 // Align to 32 bytes.
++ and r4,r4,r0
++#endif
++ stgux r1,r1,r4 // Grow the stack.
++ mflr r9
++
++ /* Save registers we use. */
++#if defined(__ppc64__)
++ std r27,-40(r8)
++#endif
++ stg r28,MODE_CHOICE(-16,-32)(r8)
++ stg r29,MODE_CHOICE(-12,-24)(r8)
++ stg r30,MODE_CHOICE(-8,-16)(r8)
++ stg r31,MODE_CHOICE(-4,-8)(r8)
++ stg r9,SF_RETURN(r8) /* return address */
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ stg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++LCFI1:
++#if defined(__ppc64__)
++ mr r27,r3 // our extended_cif
++#endif
++ /* Save arguments over call. */
++ mr r31,r5 /* flags, */
++ mr r30,r6 /* rvalue, */
++ mr r29,r7 /* function address, */
++ mr r28,r8 /* our AP. */
++
++LCFI2:
++ /* Call ffi_prep_args. */
++ mr r4,r1
++ li r9,0
++ mtctr r12 /* r12 holds address of _ffi_prep_args. */
++ bctrl
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ lg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++ /* Now do the call.
++ Set up cr1 with bits 4-7 of the flags. */
++ mtcrf 0x40,r31
++
++ /* Load all those argument registers.
++ We have set up a nice stack frame, just load it into registers. */
++ lg r3,SF_ARG1(r1)
++ lg r4,SF_ARG2(r1)
++ lg r5,SF_ARG3(r1)
++ lg r6,SF_ARG4(r1)
++ nop
++ lg r7,SF_ARG5(r1)
++ lg r8,SF_ARG6(r1)
++ lg r9,SF_ARG7(r1)
++ lg r10,SF_ARG8(r1)
++
++ /* Load all the FP registers. */
++ bf 6,L2 /* No floats to load. */
++#if defined(__ppc64__)
++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#elif defined(__ppc__)
++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#else
++#error undefined architecture
++#endif
++
++L2:
++ mr r12,r29 // Put the target address in r12 as specified.
++ mtctr r12 // Get the address to call into CTR.
++ nop
++ nop
++ bctrl // Make the call.
++
++ // Deal with the return value.
++#if defined(__ppc64__)
++ mtcrf 0x3,r31 // flags in cr6 and cr7
++ bt 27,L(st_return_value)
++#elif defined(__ppc__)
++ mtcrf 0x1,r31 // flags in cr7
++#else
++#error undefined architecture
++#endif
++
++ bt 30,L(done_return_value)
++ bt 29,L(fp_return_value)
++ stg r3,0(r30)
++#if defined(__ppc__)
++ bf 28,L(done_return_value) // Store the second long if necessary.
++ stg r4,4(r30)
++#endif
++ // Fall through
++
++L(done_return_value):
++ lg r1,0(r1) // Restore stack pointer.
++ // Restore the registers we used.
++ lg r9,SF_RETURN(r1) // return address
++ lg r31,MODE_CHOICE(-4,-8)(r1)
++ mtlr r9
++ lg r30,MODE_CHOICE(-8,-16)(r1)
++ lg r29,MODE_CHOICE(-12,-24)(r1)
++ lg r28,MODE_CHOICE(-16,-32)(r1)
++#if defined(__ppc64__)
++ ld r27,-40(r1)
++#endif
++ blr
++
++#if defined(__ppc64__)
++L(st_return_value):
++ // Grow the stack enough to fit the registers. Leave room for 8 args
++ // to trample the 1st 8 slots in param area.
++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
++
++ // Store GPRs
++ std r3,SF_ARG9(r1)
++ std r4,SF_ARG10(r1)
++ std r5,SF_ARG11(r1)
++ std r6,SF_ARG12(r1)
++ nop
++ std r7,SF_ARG13(r1)
++ std r8,SF_ARG14(r1)
++ std r9,SF_ARG15(r1)
++ std r10,SF_ARG16(r1)
++
++ // Store FPRs
++ nop
++ bf 26,L(call_struct_to_ram_form)
++ stfd f1,SF_ARG17(r1)
++ stfd f2,SF_ARG18(r1)
++ stfd f3,SF_ARG19(r1)
++ stfd f4,SF_ARG20(r1)
++ nop
++ stfd f5,SF_ARG21(r1)
++ stfd f6,SF_ARG22(r1)
++ stfd f7,SF_ARG23(r1)
++ stfd f8,SF_ARG24(r1)
++ nop
++ stfd f9,SF_ARG25(r1)
++ stfd f10,SF_ARG26(r1)
++ stfd f11,SF_ARG27(r1)
++ stfd f12,SF_ARG28(r1)
++ nop
++ stfd f13,SF_ARG29(r1)
++
++L(call_struct_to_ram_form):
++ ld r3,0(r27) // extended_cif->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ addi r4,r1,SF_ARG9 // stored GPRs
++ addi r6,r1,SF_ARG17 // stored FPRs
++ li r5,0 // GPR size ptr (NULL)
++ li r7,0 // FPR size ptr (NULL)
++ li r8,0 // FPR count ptr (NULL)
++ li r10,0 // struct offset (NULL)
++ mr r9,r30 // return area
++ bl Lffi64_struct_to_ram_form$stub
++ lg r1,0(r1) // Restore stack pointer.
++ b L(done_return_value)
++#endif
++
++L(fp_return_value):
++ /* Do we have long double to store? */
++ bf 31,L(fd_return_value)
++ stfd f1,0(r30)
++ stfd f2,8(r30)
++ b L(done_return_value)
++
++L(fd_return_value):
++ /* Do we have double to store? */
++ bf 28,L(float_return_value)
++ stfd f1,0(r30)
++ b L(done_return_value)
++
++L(float_return_value):
++ /* We only have a float to store. */
++ stfs f1,0(r30)
++ b L(done_return_value)
++
++LFE1:
++/* END(_ffi_call_DARWIN) */
++
++/* Provide a null definition of _ffi_call_AIX. */
++.text
++ .align 2
++.globl _ffi_call_AIX
++.text
++ .align 2
++_ffi_call_AIX:
++ blr
++/* END(_ffi_call_AIX) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_call_DARWIN.eh
++_ffi_call_DARWIN.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB0-. ; FDE initial location
++ .set L$set$3,LFE1-LFB0
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x08 ; uleb128 0x08
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$5,LCFI1-LCFI0
++ .long L$set$5
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .byte 0x9f ; DW_CFA_offset, column 0x1f
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x9e ; DW_CFA_offset, column 0x1e
++ .byte 0x2 ; uleb128 0x2
++ .byte 0x9d ; DW_CFA_offset, column 0x1d
++ .byte 0x3 ; uleb128 0x3
++ .byte 0x9c ; DW_CFA_offset, column 0x1c
++ .byte 0x4 ; uleb128 0x4
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$6,LCFI2-LCFI1
++ .long L$set$6
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x1c ; uleb128 0x1c
++ .align LOG2_GPR_BYTES
++LEFDE1:
++
++#if defined(__ppc64__)
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_ram_form$stub:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_ram_form
++
++LO$ffi64_struct_to_ram_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_ram_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
++#endif // __ppc__ || __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+new file mode 100644
+index 0000000..cf4bd50
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+@@ -0,0 +1,85 @@
++/* -----------------------------------------------------------------------
++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define L(x) x
++
++#define SF_ARG9 MODE_CHOICE(56,112)
++#define SF_ARG10 MODE_CHOICE(60,120)
++#define SF_ARG11 MODE_CHOICE(64,128)
++#define SF_ARG12 MODE_CHOICE(68,136)
++#define SF_ARG13 MODE_CHOICE(72,144)
++#define SF_ARG14 MODE_CHOICE(76,152)
++#define SF_ARG15 MODE_CHOICE(80,160)
++#define SF_ARG16 MODE_CHOICE(84,168)
++#define SF_ARG17 MODE_CHOICE(88,176)
++#define SF_ARG18 MODE_CHOICE(92,184)
++#define SF_ARG19 MODE_CHOICE(96,192)
++#define SF_ARG20 MODE_CHOICE(100,200)
++#define SF_ARG21 MODE_CHOICE(104,208)
++#define SF_ARG22 MODE_CHOICE(108,216)
++#define SF_ARG23 MODE_CHOICE(112,224)
++#define SF_ARG24 MODE_CHOICE(116,232)
++#define SF_ARG25 MODE_CHOICE(120,240)
++#define SF_ARG26 MODE_CHOICE(124,248)
++#define SF_ARG27 MODE_CHOICE(128,256)
++#define SF_ARG28 MODE_CHOICE(132,264)
++#define SF_ARG29 MODE_CHOICE(136,272)
++
++#define ASM_NEEDS_REGISTERS 4
++#define NUM_GPR_ARG_REGISTERS 8
++#define NUM_FPR_ARG_REGISTERS 13
++
++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
++#define FFI_TYPE_4_BYTE(x) \
++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
++
++#if !defined(LIBFFI_ASM)
++
++enum {
++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
++ FLAG_RETURNS_FP = 1 << (31 - 29),
++ FLAG_RETURNS_64BITS = 1 << (31 - 28),
++ FLAG_RETURNS_128BITS = 1 << (31 - 31),
++
++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
++
++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
++};
++
++#if defined(__ppc64__)
++void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
++ const char*, unsigned int*, unsigned int*, char*, unsigned int*);
++void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
++ unsigned int*, char*, unsigned int*, char*, unsigned int*);
++bool ffi64_stret_needs_ptr(const ffi_type* inType,
++ unsigned short*, unsigned short*);
++#endif
++
++#endif // !defined(LIBFFI_ASM)
+\ No newline at end of file
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+new file mode 100644
+index 0000000..c3d30c2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+@@ -0,0 +1,308 @@
++#if defined(__ppc__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0 // Save return address
++ stg r0,SF_RETURN(r1)
++
++LCFI0:
++ /* 24/48 bytes (Linkage Area)
++ 32/64 bytes (outgoing parameter area, always reserved)
++ 104 bytes (13*8 from FPR)
++ 16/32 bytes (result)
++ 176/232 total bytes */
++
++ /* skip over caller save area and keep stack aligned to 16/32. */
++ stgu r1,-SF_ROUND(176)(r1)
++
++LCFI1:
++ /* We want to build up an area for the parameters passed
++ in registers. (both floating point and integer) */
++
++ /* 176/256 bytes (callee stack frame aligned to 16/32)
++ 24/48 bytes (caller linkage area)
++ 200/304 (start of caller parameter area aligned to 4/8)
++ */
++
++ /* Save GPRs 3 - 10 (aligned to 4/8)
++ in the parents outgoing area. */
++ stg r3,200(r1)
++ stg r4,204(r1)
++ stg r5,208(r1)
++ stg r6,212(r1)
++ stg r7,216(r1)
++ stg r8,220(r1)
++ stg r9,224(r1)
++ stg r10,228(r1)
++
++ /* Save FPRs 1 - 13. (aligned to 8) */
++ stfd f1,56(r1)
++ stfd f2,64(r1)
++ stfd f3,72(r1)
++ stfd f4,80(r1)
++ stfd f5,88(r1)
++ stfd f6,96(r1)
++ stfd f7,104(r1)
++ stfd f8,112(r1)
++ stfd f9,120(r1)
++ stfd f10,128(r1)
++ stfd f11,136(r1)
++ stfd f12,144(r1)
++ stfd f13,152(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,160 // result storage
++ addi r5,r1,200 // saved GPRs
++ addi r6,r1,56 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ /* Now r3 contains the return type. Use it to look up in a table
++ so we know how to deal with each type. */
++ addi r5,r1,160 // Copy result storage pointer.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ (4 instructions). For cache effectiveness we align to a 16 byte boundary
++ first. */
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++/* case FFI_TYPE_VOID */
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* case FFI_TYPE_INT */
++Lret_type1:
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_FLOAT */
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_DOUBLE */
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_LONGDOUBLE */
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT8 */
++Lret_type5:
++ lbz r3,3(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT8 */
++Lret_type6:
++ lbz r3,3(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT16 */
++Lret_type7:
++ lhz r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT16 */
++Lret_type8:
++ lha r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT32 */
++Lret_type9: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT32 */
++Lret_type10: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT64 */
++Lret_type11:
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_SINT64 */
++Lret_type12: // same as Lret_type11
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_STRUCT */
++Lret_type13:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* End 16-byte aligned cases */
++/* case FFI_TYPE_POINTER */
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ // fall through
++
++/* case done */
++Lfinish:
++ addi r1,r1,SF_ROUND(176) // Restore stack pointer.
++ lg r0,SF_RETURN(r1) // Restore return address.
++ mtlr r0 // Restore link register.
++ blr
++
++/* END(ffi_closure_ASM) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++
++#endif // __ppc__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+new file mode 100644
+index 0000000..8953d5f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+@@ -0,0 +1,1776 @@
++#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
++#include
++
++#include
++#include
++#include
++#include
++#include
++
++#if 0
++#if defined(POWERPC_DARWIN)
++#include // for sys_icache_invalidate()
++#endif
++
++#else
++
++#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)
++ 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
++
++typedef union
++{
++ float f;
++ double d;
++} ffi_dblfl;
++
++/* 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;
++ long 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] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
++ else
++ avalue[i] = (void*)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(temp_ld.lb[0]));
++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
++ 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 ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+new file mode 100644
+index 0000000..7162fa1
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+@@ -0,0 +1,418 @@
++#if defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc64-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0
++ stg r0,SF_RETURN(r1) // save return address
++
++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
++ stg r3,SF_ARG1(r1)
++ stg r4,SF_ARG2(r1)
++ stg r5,SF_ARG3(r1)
++ stg r6,SF_ARG4(r1)
++ stg r7,SF_ARG5(r1)
++ stg r8,SF_ARG6(r1)
++ stg r9,SF_ARG7(r1)
++ stg r10,SF_ARG8(r1)
++
++LCFI0:
++/* 48 bytes (Linkage Area)
++ 64 bytes (outgoing parameter area, always reserved)
++ 112 bytes (14*8 for incoming FPR)
++ ? bytes (result)
++ 112 bytes (14*8 for outgoing FPR)
++ 16 bytes (2 saved registers)
++ 352 + ? total bytes
++*/
++
++ std r31,-8(r1) // Save registers we use.
++ std r30,-16(r1)
++ mr r30,r1 // Save the old SP.
++ mr r31,r11 // Save the ffi_closure around ffi64_data_size.
++
++ // Calculate the space we need.
++ stdu r1,-SF_MINSIZE(r1)
++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ bl Lffi64_data_size$stub
++ ld r1,0(r1)
++
++ addi r3,r3,352 // Add our overhead.
++ neg r3,r3
++ li r0,-32 // Align to 32 bytes.
++ and r3,r3,r0
++ stdux r1,r1,r3 // Grow the stack.
++
++ mr r11,r31 // Copy the ffi_closure back.
++
++LCFI1:
++ // We want to build up an area for the parameters passed
++ // in registers. (both floating point and integer)
++
++/* 320 bytes (callee stack frame aligned to 32)
++ 48 bytes (caller linkage area)
++ 368 (start of caller parameter area aligned to 8)
++*/
++
++ // Save FPRs 1 - 14. (aligned to 8)
++ stfd f1,112(r1)
++ stfd f2,120(r1)
++ stfd f3,128(r1)
++ stfd f4,136(r1)
++ stfd f5,144(r1)
++ stfd f6,152(r1)
++ stfd f7,160(r1)
++ stfd f8,168(r1)
++ stfd f9,176(r1)
++ stfd f10,184(r1)
++ stfd f11,192(r1)
++ stfd f12,200(r1)
++ stfd f13,208(r1)
++ stfd f14,216(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,224 // result storage
++ addi r5,r30,SF_ARG1 // saved GPRs
++ addi r6,r1,112 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ // Look the proper starting point in table
++ // by using return type as an offset.
++ addi r5,r1,224 // Get pointer to results area.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Now multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ // (4 instructions). For cache effectiveness we align to a 16 byte
++ // boundary first.
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++// case FFI_TYPE_VOID
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++// case FFI_TYPE_INT
++Lret_type1:
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_FLOAT
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_DOUBLE
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_LONGDOUBLE
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT8
++Lret_type5:
++ lbz r3,7(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT8
++Lret_type6:
++ lbz r3,7(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT16
++Lret_type7:
++ lhz r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT16
++Lret_type8:
++ lha r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT32
++Lret_type9: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT32
++Lret_type10: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT64
++Lret_type11:
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT64
++Lret_type12: // same as Lret_type11
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_STRUCT
++Lret_type13:
++ b Lret_struct
++ nop
++ nop
++ nop
++
++// ** End 16-byte aligned cases **
++// case FFI_TYPE_POINTER
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ b Lfinish
++
++// copy struct into registers
++Lret_struct:
++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r31) // ffi_cif->rtype*
++ ld r31,24(r31) // ffi_cif->flags
++ mr r4,r5 // copy struct* to 2nd arg
++ addi r7,r1,SF_ARG9 // GPR return area
++ addi r9,r30,-16-(14*8) // FPR return area
++ li r5,0 // struct offset ptr (NULL)
++ li r6,0 // FPR used count ptr (NULL)
++ li r8,0 // GPR return area size ptr (NULL)
++ li r10,0 // FPR return area size ptr (NULL)
++ bl Lffi64_struct_to_reg_form$stub
++
++ // Load GPRs
++ ld r3,SF_ARG9(r1)
++ ld r4,SF_ARG10(r1)
++ ld r5,SF_ARG11(r1)
++ ld r6,SF_ARG12(r1)
++ nop
++ ld r7,SF_ARG13(r1)
++ ld r8,SF_ARG14(r1)
++ ld r9,SF_ARG15(r1)
++ ld r10,SF_ARG16(r1)
++ nop
++
++ // Load FPRs
++ mtcrf 0x2,r31
++ bf 26,Lfinish
++ lfd f1,-16-(14*8)(r30)
++ lfd f2,-16-(13*8)(r30)
++ lfd f3,-16-(12*8)(r30)
++ lfd f4,-16-(11*8)(r30)
++ nop
++ lfd f5,-16-(10*8)(r30)
++ lfd f6,-16-(9*8)(r30)
++ lfd f7,-16-(8*8)(r30)
++ lfd f8,-16-(7*8)(r30)
++ nop
++ lfd f9,-16-(6*8)(r30)
++ lfd f10,-16-(5*8)(r30)
++ lfd f11,-16-(4*8)(r30)
++ lfd f12,-16-(3*8)(r30)
++ nop
++ lfd f13,-16-(2*8)(r30)
++ lfd f14,-16-(1*8)(r30)
++ // Fall through
++
++// case done
++Lfinish:
++ lg r1,0(r1) // Restore stack pointer.
++ ld r31,-8(r1) // Restore registers we used.
++ ld r30,-16(r1)
++ lg r0,SF_RETURN(r1) // Get return address.
++ mtlr r0 // Reset link register.
++ blr
++
++// END(ffi_closure_ASM)
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_reg_form$stub:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_reg_form
++
++LO$ffi64_struct_to_reg_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
++ mtctr r12
++ bctr
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_data_size$stub:
++ .indirect_symbol _ffi64_data_size
++ mflr r0
++ bcl 20,31,LO$ffi64_data_size
++
++LO$ffi64_data_size:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_reg_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ .g_long dyld_stub_binding_helper
++
++L_ffi64_data_size$lazy_ptr:
++ .indirect_symbol _ffi64_data_size
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c
+new file mode 100644
+index 0000000..44806ae
+--- /dev/null
++++ ./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
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+new file mode 100644
+index 0000000..165d469
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+@@ -0,0 +1,417 @@
++/* -----------------------------------------------------------------------
++ 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
++#include
++
++ .file "darwin64.S"
++.text
++
++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
++ void *raddr, void (*fnaddr)());
++
++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
++ for this function. This has been allocated by ffi_call. We also
++ deallocate some of the stack that has been alloca'd. */
++
++ .align 3
++ .globl _ffi_call_unix64
++
++_ffi_call_unix64:
++LUW0:
++ movq (%rsp), %r10 /* Load return address. */
++ movq %rdi, %r12 /* Save a copy of the register area. */
++ leaq (%rdi, %rsi), %rax /* Find local stack base. */
++ movq %rdx, (%rax) /* Save flags. */
++ movq %rcx, 8(%rax) /* Save raddr. */
++ movq %rbp, 16(%rax) /* Save old frame pointer. */
++ movq %r10, 24(%rax) /* Relocate return address. */
++ movq %rax, %rbp /* Finalize local stack frame. */
++LUW1:
++ /* movq %rdi, %r10 // Save a copy of the register area. */
++ movq %r12, %r10
++ movq %r8, %r11 /* Save a copy of the target fn. */
++ movl %r9d, %eax /* Set number of SSE registers. */
++
++ /* Load up all argument registers. */
++ movq (%r10), %rdi
++ movq 8(%r10), %rsi
++ movq 16(%r10), %rdx
++ movq 24(%r10), %rcx
++ movq 32(%r10), %r8
++ movq 40(%r10), %r9
++ testl %eax, %eax
++ jnz Lload_sse
++Lret_from_load_sse:
++
++ /* Deallocate the reg arg area. */
++ leaq 176(%r10), %rsp
++
++ /* Call the user function. */
++ call *%r11
++
++ /* Deallocate stack arg area; local stack frame in redzone. */
++ leaq 24(%rbp), %rsp
++
++ movq 0(%rbp), %rcx /* Reload flags. */
++ movq 8(%rbp), %rdi /* Reload raddr. */
++ movq 16(%rbp), %rbp /* Reload old frame pointer. */
++LUW2:
++
++ /* The first byte of the flags contains the FFI_TYPE. */
++ movzbl %cl, %r10d
++ leaq Lstore_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lstore_table:
++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lst_void:
++ ret
++ .align 3
++Lst_uint8:
++ movzbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_sint8:
++ movsbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint16:
++ movzwq %ax, %rax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint16:
++ movswq %ax, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint32:
++ movl %eax, %eax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint32:
++ cltq
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_int64:
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_float:
++ movss %xmm0, (%rdi)
++ ret
++ .align 3
++Lst_double:
++ movsd %xmm0, (%rdi)
++ ret
++Lst_ldouble:
++ fstpt (%rdi)
++ ret
++ .align 3
++Lst_struct:
++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */
++
++ /* We have to locate the values now, and since we don't want to
++ write too much data into the user's return value, we spill the
++ value to a 16 byte scratch area first. Bits 8, 9, and 10
++ control where the values are located. Only one of the three
++ bits will be set; see ffi_prep_cif_machdep for the pattern. */
++ movd %xmm0, %r10
++ movd %xmm1, %r11
++ testl $0x100, %ecx
++ cmovnz %rax, %rdx
++ cmovnz %r10, %rax
++ testl $0x200, %ecx
++ cmovnz %r10, %rdx
++ testl $0x400, %ecx
++ cmovnz %r10, %rax
++ cmovnz %r11, %rdx
++ movq %rax, (%rsi)
++ movq %rdx, 8(%rsi)
++
++ /* Bits 12-31 contain the true size of the structure. Copy from
++ the scratch area to the true destination. */
++ shrl $12, %ecx
++ rep movsb
++ ret
++
++ /* Many times we can avoid loading any SSE registers at all.
++ It's not worth an indirect jump to load the exact set of
++ SSE registers needed; zero or all is a good compromise. */
++ .align 3
++LUW3:
++Lload_sse:
++ movdqa 48(%r10), %xmm0
++ movdqa 64(%r10), %xmm1
++ movdqa 80(%r10), %xmm2
++ movdqa 96(%r10), %xmm3
++ movdqa 112(%r10), %xmm4
++ movdqa 128(%r10), %xmm5
++ movdqa 144(%r10), %xmm6
++ movdqa 160(%r10), %xmm7
++ jmp Lret_from_load_sse
++
++LUW4:
++ .align 3
++ .globl _ffi_closure_unix64
++
++_ffi_closure_unix64:
++LUW5:
++ /* The carry flag is set by the trampoline iff SSE registers
++ are used. Don't clobber it before the branch instruction. */
++ leaq -200(%rsp), %rsp
++LUW6:
++ movq %rdi, (%rsp)
++ movq %rsi, 8(%rsp)
++ movq %rdx, 16(%rsp)
++ movq %rcx, 24(%rsp)
++ movq %r8, 32(%rsp)
++ movq %r9, 40(%rsp)
++ jc Lsave_sse
++Lret_from_save_sse:
++
++ movq %r10, %rdi
++ leaq 176(%rsp), %rsi
++ movq %rsp, %rdx
++ leaq 208(%rsp), %rcx
++ call _ffi_closure_unix64_inner
++
++ /* Deallocate stack frame early; return value is now in redzone. */
++ addq $200, %rsp
++LUW7:
++
++ /* The first byte of the return value contains the FFI_TYPE. */
++ movzbl %al, %r10d
++ leaq Lload_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lload_table:
++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */
++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */
++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lld_void:
++ ret
++ .align 3
++Lld_int8:
++ movzbl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int16:
++ movzwl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int32:
++ movl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int64:
++ movq -24(%rsp), %rax
++ ret
++ .align 3
++Lld_float:
++ movss -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_double:
++ movsd -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_ldouble:
++ fldt -24(%rsp)
++ ret
++ .align 3
++Lld_struct:
++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
++ both rdx and xmm1 with the second word. For the remaining,
++ bit 8 set means xmm0 gets the second word, and bit 9 means
++ that rax gets the second word. */
++ movq -24(%rsp), %rcx
++ movq -16(%rsp), %rdx
++ movq -16(%rsp), %xmm1
++ testl $0x100, %eax
++ cmovnz %rdx, %rcx
++ movd %rcx, %xmm0
++ testl $0x200, %eax
++ movq -24(%rsp), %rax
++ cmovnz %rdx, %rax
++ ret
++
++ /* See the comment above Lload_sse; the same logic applies here. */
++ .align 3
++LUW8:
++Lsave_sse:
++ movdqa %xmm0, 48(%rsp)
++ movdqa %xmm1, 64(%rsp)
++ movdqa %xmm2, 80(%rsp)
++ movdqa %xmm3, 96(%rsp)
++ movdqa %xmm4, 112(%rsp)
++ movdqa %xmm5, 128(%rsp)
++ movdqa %xmm6, 144(%rsp)
++ movdqa %xmm7, 160(%rsp)
++ jmp Lret_from_save_sse
++
++LUW9:
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */
++ .long L$set$0
++LSCIE1:
++ .long 0x0 /* CIE Identifier Tag */
++ .byte 0x1 /* CIE Version */
++ .ascii "zR\0" /* CIE Augmentation */
++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
++ .byte 0x10 /* CIE RA Column */
++ .byte 0x1 /* uleb128 0x1; Augmentation size */
++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */
++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
++ .byte 0x7 /* uleb128 0x7 */
++ .byte 0x8 /* uleb128 0x8 */
++ .byte 0x90 /* DW_CFA_offset, column 0x10 */
++ .byte 0x1
++ .align 3
++LECIE1:
++ .globl _ffi_call_unix64.eh
++_ffi_call_unix64.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1 /* FDE CIE offset */
++ .quad LUW0-. /* FDE initial location */
++ .set L$set$2,LUW4-LUW0 /* FDE address range */
++ .quad L$set$2
++ .byte 0x0 /* Augmentation size */
++ .byte 0x4 /* DW_CFA_advance_loc4 */
++ .set L$set$3,LUW1-LUW0
++ .long L$set$3
++
++ /* New stack frame based off rbp. This is 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 ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+new file mode 100644
+index 0000000..925a841
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+@@ -0,0 +1,422 @@
++#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
++#include
++
++#ifdef PyObjC_STRICT_DEBUGGING
++ /* XXX: Debugging of stack alignment, to be removed */
++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
++#else
++#define ASSERT_STACK_ALIGNED
++#endif
++
++.text
++
++.globl _ffi_prep_args
++
++ .align 4
++.globl _ffi_call_SYSV
++
++_ffi_call_SYSV:
++LFB1:
++ pushl %ebp
++LCFI0:
++ movl %esp,%ebp
++LCFI1:
++ subl $8,%esp
++ /* Make room for all of the new args. */
++ movl 16(%ebp),%ecx
++ subl %ecx,%esp
++
++ movl %esp,%eax
++
++ /* Place all of the ffi_prep_args in position */
++ subl $8,%esp
++ pushl 12(%ebp)
++ pushl %eax
++ call *8(%ebp)
++
++ /* Return stack to previous state and call the function */
++ addl $16,%esp
++
++ call *28(%ebp)
++
++ /* Remove the space we pushed for the args */
++ movl 16(%ebp),%ecx
++ addl %ecx,%esp
++
++ /* Load %ecx with the return type code */
++ movl 20(%ebp),%ecx
++
++ /* If the return value pointer is NULL, assume no return value. */
++ cmpl $0,24(%ebp)
++ jne Lretint
++
++ /* Even if there is no space for the return value, we are
++ obliged to handle floating-point values. */
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lnoretval
++ fstp %st(0)
++
++ jmp Lepilogue
++
++Lretint:
++ cmpl $FFI_TYPE_INT,%ecx
++ jne Lretfloat
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ jmp Lepilogue
++
++Lretfloat:
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lretdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstps (%ecx)
++ jmp Lepilogue
++
++Lretdouble:
++ cmpl $FFI_TYPE_DOUBLE,%ecx
++ jne Lretlongdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpl (%ecx)
++ jmp Lepilogue
++
++Lretlongdouble:
++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx
++ jne Lretint64
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpt (%ecx)
++ jmp Lepilogue
++
++Lretint64:
++ cmpl $FFI_TYPE_SINT64,%ecx
++ jne Lretstruct1b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ movl %edx,4(%ecx)
++ jmp Lepilogue
++
++Lretstruct1b:
++ cmpl $FFI_TYPE_SINT8,%ecx
++ jne Lretstruct2b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movb %al,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct2b:
++ cmpl $FFI_TYPE_SINT16,%ecx
++ jne Lretstruct
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movw %ax,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct:
++ cmpl $FFI_TYPE_STRUCT,%ecx
++ jne Lnoretval
++ /* Nothing to do! */
++ addl $4,%esp
++ popl %ebp
++ ret
++
++Lnoretval:
++Lepilogue:
++ addl $8,%esp
++ movl %ebp,%esp
++ popl %ebp
++ ret
++LFE1:
++.ffi_call_SYSV_end:
++
++ .align 4
++FFI_HIDDEN (ffi_closure_SYSV)
++.globl _ffi_closure_SYSV
++
++_ffi_closure_SYSV:
++LFB2:
++ pushl %ebp
++LCFI2:
++ movl %esp, %ebp
++LCFI3:
++ subl $56, %esp
++ leal -40(%ebp), %edx
++ movl %edx, -12(%ebp) /* resp */
++ leal 8(%ebp), %edx
++ movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
++ leal -12(%ebp), %edx
++ movl %edx, (%esp) /* &resp */
++ movl %ebx, 8(%esp)
++LCFI7:
++ call L_ffi_closure_SYSV_inner$stub
++ movl 8(%esp), %ebx
++ movl -12(%ebp), %ecx
++ cmpl $FFI_TYPE_INT, %eax
++ je Lcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lcls_retllong
++ cmpl $FFI_TYPE_UINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_SINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_UINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_SINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_STRUCT, %eax
++ je Lcls_retstruct
++Lcls_epilogue:
++ movl %ebp, %esp
++ popl %ebp
++ ret
++Lcls_retint:
++ movl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retfloat:
++ flds (%ecx)
++ jmp Lcls_epilogue
++Lcls_retdouble:
++ fldl (%ecx)
++ jmp Lcls_epilogue
++Lcls_retldouble:
++ fldt (%ecx)
++ jmp Lcls_epilogue
++Lcls_retllong:
++ movl (%ecx), %eax
++ movl 4(%ecx), %edx
++ jmp Lcls_epilogue
++Lcls_retstruct1:
++ movsbl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct2:
++ movswl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct:
++ lea -8(%ebp),%esp
++ movl %ebp, %esp
++ popl %ebp
++ ret $4
++LFE2:
++
++#if !FFI_NO_RAW_API
++
++#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
++#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
++#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
++#define CIF_FLAGS_OFFSET 20
++
++ .align 4
++FFI_HIDDEN (ffi_closure_raw_SYSV)
++.globl _ffi_closure_raw_SYSV
++
++_ffi_closure_raw_SYSV:
++LFB3:
++ pushl %ebp
++LCFI4:
++ movl %esp, %ebp
++LCFI5:
++ pushl %esi
++LCFI6:
++ subl $36, %esp
++ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
++ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
++ movl %edx, 12(%esp) /* user_data */
++ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
++ movl %edx, 8(%esp) /* raw_args */
++ leal -24(%ebp), %edx
++ movl %edx, 4(%esp) /* &res */
++ movl %esi, (%esp) /* cif */
++ call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
++ movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
++ cmpl $FFI_TYPE_INT, %eax
++ je Lrcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lrcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lrcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lrcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lrcls_retllong
++Lrcls_epilogue:
++ addl $36, %esp
++ popl %esi
++ popl %ebp
++ ret
++Lrcls_retint:
++ movl -24(%ebp), %eax
++ jmp Lrcls_epilogue
++Lrcls_retfloat:
++ flds -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retdouble:
++ fldl -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retldouble:
++ fldt -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retllong:
++ movl -24(%ebp), %eax
++ movl -20(%ebp), %edx
++ jmp Lrcls_epilogue
++LFE3:
++#endif
++
++.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
++L_ffi_closure_SYSV_inner$stub:
++ .indirect_symbol _ffi_closure_SYSV_inner
++ hlt ; hlt ; hlt ; hlt ; hlt
++
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0
++LSCIE1:
++ .long 0x0
++ .byte 0x1
++ .ascii "zR\0"
++ .byte 0x1
++ .byte 0x7c
++ .byte 0x8
++ .byte 0x1
++ .byte 0x10
++ .byte 0xc
++ .byte 0x5
++ .byte 0x4
++ .byte 0x88
++ .byte 0x1
++ .align 2
++LECIE1:
++.globl _ffi_call_SYSV.eh
++_ffi_call_SYSV.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1
++ .long LFB1-.
++ .set L$set$2,LFE1-LFB1
++ .long L$set$2
++ .byte 0x0
++ .byte 0x4
++ .set L$set$3,LCFI0-LFB1
++ .long L$set$3
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$4,LCFI1-LCFI0
++ .long L$set$4
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE1:
++.globl _ffi_closure_SYSV.eh
++_ffi_closure_SYSV.eh:
++LSFDE2:
++ .set L$set$5,LEFDE2-LASFDE2
++ .long L$set$5
++LASFDE2:
++ .long LASFDE2-EH_frame1
++ .long LFB2-.
++ .set L$set$6,LFE2-LFB2
++ .long L$set$6
++ .byte 0x0
++ .byte 0x4
++ .set L$set$7,LCFI2-LFB2
++ .long L$set$7
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$8,LCFI3-LCFI2
++ .long L$set$8
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE2:
++
++#if !FFI_NO_RAW_API
++
++.globl _ffi_closure_raw_SYSV.eh
++_ffi_closure_raw_SYSV.eh:
++LSFDE3:
++ .set L$set$10,LEFDE3-LASFDE3
++ .long L$set$10
++LASFDE3:
++ .long LASFDE3-EH_frame1
++ .long LFB3-.
++ .set L$set$11,LFE3-LFB3
++ .long L$set$11
++ .byte 0x0
++ .byte 0x4
++ .set L$set$12,LCFI4-LFB3
++ .long L$set$12
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$13,LCFI5-LCFI4
++ .long L$set$13
++ .byte 0xd
++ .byte 0x4
++ .byte 0x4
++ .set L$set$14,LCFI6-LCFI5
++ .long L$set$14
++ .byte 0x85
++ .byte 0x3
++ .align 2
++LEFDE3:
++
++#endif
++
++#endif /* ifndef __x86_64__ */
++
++#endif /* defined __i386__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+new file mode 100644
+index 0000000..06feaf2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+@@ -0,0 +1,734 @@
++#ifdef __x86_64__
++
++/* -----------------------------------------------------------------------
++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen
++
++ 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
++#include
++
++#include
++#include
++
++#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 0
++ if (byte_offset + type->size <= 4)
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ else
++ classes[0] = X86_64_INTEGER_CLASS;
++
++ return 1;
++#else
++ {
++ int size = byte_offset + type->size;
++
++ if (size <= 4)
++ {
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ return 1;
++ }
++ else if (size <= 8)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ return 1;
++ }
++ else if (size <= 12)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else if (size <= 16)
++ {
++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else
++ FFI_ASSERT (0);
++ }
++#endif
++
++ case FFI_TYPE_FLOAT:
++ if (byte_offset == 0)
++ classes[0] = X86_64_SSESF_CLASS;
++ else
++ classes[0] = X86_64_SSE_CLASS;
++
++ return 1;
++
++ case FFI_TYPE_DOUBLE:
++ classes[0] = X86_64_SSEDF_CLASS;
++ return 1;
++
++ case FFI_TYPE_LONGDOUBLE:
++ classes[0] = X86_64_X87_CLASS;
++ classes[1] = X86_64_X87UP_CLASS;
++ return 2;
++
++ case FFI_TYPE_STRUCT:
++ {
++ ffi_type** ptr;
++ int i;
++ enum x86_64_reg_class subclasses[MAX_CLASSES];
++ const int UNITS_PER_WORD = 8;
++ int words =
++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++
++ /* If the struct is larger than 16 bytes, pass it on the stack. */
++ if (type->size > 16)
++ return 0;
++
++ for (i = 0; i < words; i++)
++ classes[i] = X86_64_NO_CLASS;
++
++ /* Merge the fields of structure. */
++ for (ptr = type->elements; *ptr != NULL; ptr++)
++ {
++ 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;
++ }
++
++ if (words > 2)
++ {
++ /* When size > 16 bytes, if the first one isn't
++ X86_64_SSE_CLASS or any other ones aren't
++ X86_64_SSEUP_CLASS, everything should be passed in
++ memory. */
++ if (classes[0] != X86_64_SSE_CLASS)
++ return 0;
++
++ for (i = 1; i < words; i++)
++ if (classes[i] != X86_64_SSEUP_CLASS)
++ return 0;
++ }
++
++
++ /* Final merger cleanup. */
++ for (i = 0; i < words; i++)
++ {
++ /* If one class is MEMORY, everything should be passed in
++ memory. */
++ if (classes[i] == X86_64_MEMORY_CLASS)
++ return 0;
++
++ /* The X86_64_SSEUP_CLASS should be always preceded by
++ X86_64_SSE_CLASS. */
++ if (classes[i] == X86_64_SSEUP_CLASS
++ && classes[i - 1] != X86_64_SSE_CLASS
++ && classes[i - 1] != X86_64_SSEUP_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++
++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
++ if (classes[i] == X86_64_X87UP_CLASS
++ && classes[i - 1] != X86_64_X87_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++ }
++
++ return words;
++ }
++
++ default:
++ FFI_ASSERT(0);
++ }
++
++ return 0; /* Never reached. */
++}
++
++/* Examine the argument and return set number of register required in each
++ class. Return zero if parameter should be passed in memory, otherwise
++ the number of registers. */
++static int
++examine_argument(
++ ffi_type* type,
++ enum x86_64_reg_class classes[MAX_CLASSES],
++ _Bool in_return,
++ int* pngpr,
++ int* pnsse)
++{
++ int n = classify_argument(type, classes, 0);
++ int ngpr = 0;
++ int nsse = 0;
++ int i;
++
++ if (n == 0)
++ return 0;
++
++ for (i = 0; i < n; ++i)
++ {
++ switch (classes[i])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ ngpr++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSESF_CLASS:
++ case X86_64_SSEDF_CLASS:
++ nsse++;
++ break;
++
++ case X86_64_NO_CLASS:
++ case X86_64_SSEUP_CLASS:
++ break;
++
++ case X86_64_X87_CLASS:
++ case X86_64_X87UP_CLASS:
++ case X86_64_COMPLEX_X87_CLASS:
++ return in_return != 0;
++
++ default:
++ abort();
++ }
++ }
++
++ *pngpr = ngpr;
++ *pnsse = nsse;
++
++ return n;
++}
++
++/* Perform machine dependent cif processing. */
++ffi_status
++ffi_prep_cif_machdep(
++ ffi_cif* cif)
++{
++ int gprcount = 0;
++ int ssecount = 0;
++ int flags = cif->rtype->type;
++ int i, avn, n, ngpr, nsse;
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ size_t bytes;
++
++ if (flags != FFI_TYPE_VOID)
++ {
++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value is passed in memory. A pointer to that
++ memory is the first argument. Allocate a register for it. */
++ gprcount++;
++
++ /* We don't have to do anything in asm for the return. */
++ flags = FFI_TYPE_VOID;
++ }
++ else if (flags == FFI_TYPE_STRUCT)
++ {
++ /* Mark which registers the result appears in. */
++ _Bool sse0 = SSE_CLASS_P(classes[0]);
++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
++
++ if (sse0 && !sse1)
++ flags |= 1 << 8;
++ else if (!sse0 && sse1)
++ flags |= 1 << 9;
++ else if (sse0 && sse1)
++ flags |= 1 << 10;
++
++ /* Mark the true size of the structure. */
++ flags |= cif->rtype->size << 12;
++ }
++ }
++
++ /* Go over all arguments and determine the way they should be passed.
++ If it's in a register and there is space for it, let that be so. If
++ not, add it's size to the stack byte count. */
++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
++ {
++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = cif->arg_types[i]->alignment;
++
++ if (align < 8)
++ align = 8;
++
++ bytes = ALIGN(bytes, align);
++ bytes += cif->arg_types[i]->size;
++ }
++ else
++ {
++ gprcount += ngpr;
++ ssecount += nsse;
++ }
++ }
++
++ if (ssecount)
++ flags |= 1 << 11;
++
++ cif->flags = flags;
++ cif->bytes = bytes;
++ cif->bytes = ALIGN(bytes,8);
++
++ return FFI_OK;
++}
++
++void
++ffi_call(
++ ffi_cif* cif,
++ void (*fn)(),
++ void* rvalue,
++ void** avalue)
++{
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ char* stack;
++ char* argp;
++ ffi_type** arg_types;
++ int gprcount, ssecount, ngpr, nsse, i, avn;
++ _Bool ret_in_memory;
++ RegisterArgs* reg_args;
++
++ /* Can't call 32-bit mode from 64-bit mode. */
++ FFI_ASSERT(cif->abi == FFI_UNIX64);
++
++ /* If the return value is a struct and we don't have a return value
++ address then we need to make one. Note the setting of flags to
++ VOID above in ffi_prep_cif_machdep. */
++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
++ && (cif->flags & 0xff) == FFI_TYPE_VOID);
++
++ if (rvalue == NULL && ret_in_memory)
++ rvalue = alloca (cif->rtype->size);
++
++ /* Allocate the space for the arguments, plus 4 words of temp space. */
++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
++ reg_args = (RegisterArgs*)stack;
++ argp = stack + sizeof(RegisterArgs);
++
++ gprcount = ssecount = 0;
++
++ /* If the return value is passed in memory, add the pointer as the
++ first integer argument. */
++ if (ret_in_memory)
++ reg_args->gpr[gprcount++] = (long) rvalue;
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ size_t size = arg_types[i]->size;
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ memcpy (argp, avalue[i], size);
++ argp += size;
++ }
++ else
++ { /* The argument is passed entirely in registers. */
++ char *a = (char *) avalue[i];
++ int j;
++
++ for (j = 0; j < n; j++, a += 8, size -= 8)
++ {
++ switch (classes[j])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ reg_args->gpr[gprcount] = 0;
++ switch (arg_types[i]->type) {
++ case FFI_TYPE_SINT8:
++ {
++ int8_t shortval = *(int8_t*)a;
++ int64_t actval = (int64_t)shortval;
++ reg_args->gpr[gprcount] = actval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ break;
++ }
++
++ case FFI_TYPE_SINT16:
++ {
++ int16_t shortval = *(int16_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_SINT32:
++ {
++ int32_t shortval = *(int32_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT8:
++ {
++ u_int8_t shortval = *(u_int8_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ reg_args->gpr[gprcount] = actval;
++ break;
++ }
++
++ case FFI_TYPE_UINT16:
++ {
++ u_int16_t shortval = *(u_int16_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT32:
++ {
++ u_int32_t shortval = *(u_int32_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ default:
++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
++ reg_args->gpr[gprcount] = *(int64_t*)a;
++ }
++ gprcount++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSEDF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT64 *) a;
++ break;
++
++ case X86_64_SSESF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT32 *) a;
++ break;
++
++ default:
++ abort();
++ }
++ }
++ }
++ }
++
++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
++ cif->flags, rvalue, fn, ssecount);
++}
++
++extern void ffi_closure_unix64(void);
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*, void*, void**, void*),
++ void* user_data)
++{
++ if (cif->abi != FFI_UNIX64)
++ return FFI_BAD_ABI;
++
++ volatile unsigned short* tramp =
++ (volatile unsigned short*)&closure->tramp[0];
++
++ tramp[0] = 0xbb49; /* mov , %r11 */
++ *(void* volatile*)&tramp[1] = ffi_closure_unix64;
++ tramp[5] = 0xba49; /* mov , %r10 */
++ *(void* volatile*)&tramp[6] = closure;
++
++ /* Set the carry bit if the function uses any sse registers.
++ This is clc or stc, together with the first byte of the jmp. */
++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
++ tramp[11] = 0xe3ff; /* jmp *%r11 */
++
++ closure->cif = cif;
++ closure->fun = fun;
++ closure->user_data = user_data;
++
++ return FFI_OK;
++}
++
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wmissing-prototypes"
++int
++ffi_closure_unix64_inner(
++ ffi_closure* closure,
++ void* rvalue,
++ RegisterArgs* reg_args,
++ char* argp)
++#pragma clang diagnostic pop
++{
++ ffi_cif* cif = closure->cif;
++ void** avalue = alloca(cif->nargs * sizeof(void *));
++ ffi_type** arg_types;
++ long i, avn;
++ int gprcount = 0;
++ int ssecount = 0;
++ int ngpr, nsse;
++ int ret;
++
++ ret = cif->rtype->type;
++
++ if (ret != FFI_TYPE_VOID)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value goes in memory. Arrange for the closure
++ return value to go directly back to the original caller. */
++ rvalue = (void *) reg_args->gpr[gprcount++];
++
++ /* We don't have to do anything in asm for the return. */
++ ret = FFI_TYPE_VOID;
++ }
++ else if (ret == FFI_TYPE_STRUCT && n == 2)
++ {
++ /* Mark which register the second word of the structure goes in. */
++ _Bool sse0 = SSE_CLASS_P (classes[0]);
++ _Bool sse1 = SSE_CLASS_P (classes[1]);
++
++ if (!sse0 && sse1)
++ ret |= 1 << 8;
++ else if (sse0 && !sse1)
++ ret |= 1 << 9;
++ }
++ }
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ avalue[i] = argp;
++ argp += arg_types[i]->size;
++ }
++
++#if !defined(X86_DARWIN)
++ /* If the argument is in a single register, or two consecutive
++ registers, then we can use that address directly. */
++ else if (n == 1 || (n == 2 &&
++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
++ {
++ // The argument is in a single register.
++ if (SSE_CLASS_P (classes[0]))
++ {
++ avalue[i] = ®_args->sse[ssecount];
++ ssecount += n;
++ }
++ else
++ {
++ avalue[i] = ®_args->gpr[gprcount];
++ gprcount += n;
++ }
++ }
++#endif
++
++ /* Otherwise, allocate space to make them consecutive. */
++ else
++ {
++ char *a = alloca (16);
++ int j;
++
++ avalue[i] = a;
++
++ for (j = 0; j < n; j++, a += 8)
++ {
++ if (SSE_CLASS_P (classes[j]))
++ memcpy (a, ®_args->sse[ssecount++], 8);
++ else
++ memcpy (a, ®_args->gpr[gprcount++], 8);
++ }
++ }
++ }
++
++ /* Invoke the closure. */
++ closure->fun (cif, rvalue, avalue, closure->user_data);
++
++ /* Tell assembly how to perform return type promotions. */
++ return ret;
++}
++
++#endif /* __x86_64__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+new file mode 100644
+index 0000000..706ea0f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+@@ -0,0 +1,438 @@
++#ifdef __i386__
++/* -----------------------------------------------------------------------
++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
++ Copyright (c) 2002 Ranjit Mathew
++ Copyright (c) 2002 Bo Thorsen
++ Copyright (c) 2002 Roger Sayle
++
++ x86 Foreign Function Interface
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#include
++#include
++
++#include
++
++/* ffi_prep_args is called by the assembly routine once stack space
++ has been allocated for the function's arguments */
++
++void ffi_prep_args(char *stack, extended_cif *ecif);
++
++void ffi_prep_args(char *stack, extended_cif *ecif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if (ecif->cif->flags == FFI_TYPE_STRUCT)
++ {
++ *(void **) argp = ecif->rvalue;
++ argp += 4;
++ }
++
++ p_argv = ecif->avalue;
++
++ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
++ i != 0;
++ i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp)
++ argp = (char *) ALIGN(argp, sizeof(int));
++
++ z = (*p_arg)->size;
++ if (z < sizeof(int))
++ {
++ z = sizeof(int);
++ switch ((*p_arg)->type)
++ {
++ case FFI_TYPE_SINT8:
++ *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT8:
++ *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT16:
++ *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT16:
++ *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT32:
++ *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT32:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_STRUCT:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ default:
++ FFI_ASSERT(0);
++ }
++ }
++ else
++ {
++ memcpy(argp, *p_argv, z);
++ }
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* Perform machine dependent cif processing */
++ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++{
++ /* Set the return type flag */
++ switch (cif->rtype->type)
++ {
++ case FFI_TYPE_VOID:
++#ifdef X86
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_SINT16:
++#endif
++
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ cif->flags = (unsigned) cif->rtype->type;
++ break;
++
++ case FFI_TYPE_UINT64:
++ cif->flags = FFI_TYPE_SINT64;
++ break;
++
++#ifndef X86
++ case FFI_TYPE_STRUCT:
++ if (cif->rtype->size == 1)
++ {
++ cif->flags = FFI_TYPE_SINT8; /* same as char size */
++ }
++ else if (cif->rtype->size == 2)
++ {
++ cif->flags = FFI_TYPE_SINT16; /* same as short size */
++ }
++ else if (cif->rtype->size == 4)
++ {
++ cif->flags = FFI_TYPE_INT; /* same as int type */
++ }
++ else if (cif->rtype->size == 8)
++ {
++ cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
++ }
++ else
++ {
++ cif->flags = FFI_TYPE_STRUCT;
++ }
++ break;
++#endif
++
++ default:
++ cif->flags = FFI_TYPE_INT;
++ break;
++ }
++
++#ifdef X86_DARWIN
++ cif->bytes = (cif->bytes + 15) & ~0xF;
++#endif
++
++ return FFI_OK;
++}
++
++extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#endif /* X86_WIN32 */
++
++void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
++{
++ extended_cif ecif;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->flags == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
++ fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++
++/** private members **/
++
++static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
++ void** args, ffi_cif* cif);
++void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
++__attribute__ ((regparm(1)));
++unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
++__attribute__ ((regparm(1)));
++void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
++__attribute__ ((regparm(1)));
++
++/* This function is jumped to by the trampoline */
++
++unsigned int FFI_HIDDEN
++ffi_closure_SYSV_inner (closure, respp, args)
++ffi_closure *closure;
++void **respp;
++void *args;
++{
++ // our various things...
++ ffi_cif *cif;
++ void **arg_area;
++
++ cif = closure->cif;
++ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
++
++ /* this call will initialize ARG_AREA, such that each
++ * element in that array points to the corresponding
++ * value on the stack; and if the function returns
++ * a structure, it will re-set RESP to point to the
++ * structure return address. */
++
++ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
++
++ (closure->fun) (cif, *respp, arg_area, closure->user_data);
++
++ return cif->flags;
++}
++
++static void
++ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
++ ffi_cif *cif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if ( cif->flags == FFI_TYPE_STRUCT ) {
++ *rvalue = *(void **) argp;
++ argp += 4;
++ }
++
++ p_argv = avalue;
++
++ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp) {
++ argp = (char *) ALIGN(argp, sizeof(int));
++ }
++
++ z = (*p_arg)->size;
++
++ /* because we're little endian, this is what it turns into. */
++
++ *p_argv = (void*) argp;
++
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
++
++#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
++({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
++unsigned int __fun = (unsigned int)(FUN); \
++unsigned int __ctx = (unsigned int)(CTX); \
++unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
++*(unsigned char*) &__tramp[0] = 0xb8; \
++*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
++*(unsigned char *) &__tramp[5] = 0xe9; \
++*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
++})
++
++
++/* the cif must already be prep'ed */
++ffi_status
++ffi_prep_closure (ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data)
++{
++ if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
++ &ffi_closure_SYSV, \
++ (void*)closure);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++/* ------- Native raw API support -------------------------------- */
++
++#if !FFI_NO_RAW_API
++
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc)
++{
++ int i;
++
++ FFI_ASSERT (cif->abi == FFI_SYSV);
++
++ // we currently don't support certain kinds of arguments for raw
++ // closures. This should be implemented by a separate assembly language
++ // routine, since it would require argument processing, something we
++ // don't do now for performance.
++
++ for (i = cif->nargs-1; i >= 0; i--)
++ {
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
++ }
++
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
++ codeloc);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++static void
++ffi_prep_args_raw(char *stack, extended_cif *ecif)
++{
++ memcpy (stack, ecif->avalue, ecif->cif->bytes);
++}
++
++/* we borrow this routine from libffi (it must be changed, though, to
++ * actually call the function passed in the first argument. as of
++ * libffi-1.20, this is not the case.)
++ */
++
++extern void
++ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void
++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++#endif /* X86_WIN32 */
++
++void
++ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
++{
++ extended_cif ecif;
++ void **avalue = (void **)fake_avalue;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->rtype->type == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++#endif
++#endif // __i386__
+diff --git ./setup.py ./setup.py
+index 46b92fe..2bf6b4b 100644
+--- ./setup.py
++++ ./setup.py
+@@ -98,8 +98,14 @@ class PyBuildExt(build_ext):
+ self.detect_modules()
+
+ # Remove modules that are present on the disabled list
+- self.extensions = [ext for ext in self.extensions
+- if ext.name not in disabled_module_list]
++ extensions = [ext for ext in self.extensions
++ if ext.name not in disabled_module_list]
++ # move ctypes to the end, it depends on other modules
++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
++ if "_ctypes" in ext_map:
++ ctypes = extensions.pop(ext_map["_ctypes"])
++ extensions.append(ctypes)
++ self.extensions = extensions
+
+ # Fix up the autodetected modules, prefixing all the source files
+ # with Modules/ and adding Python's include directory to the path.
+@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext):
+ # *** Uncomment these for TOGL extension only:
+ # -lGL -lGLU -lXext -lXmu \
+
++ def configure_ctypes_darwin(self, ext):
++ # Darwin (OS X) uses preconfigured files, in
++ # the Modules/_ctypes/libffi_osx directory.
++ srcdir = sysconfig.get_config_var('srcdir')
++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
++ '_ctypes', 'libffi_osx'))
++ sources = [os.path.join(ffi_srcdir, p)
++ for p in ['ffi.c',
++ 'x86/darwin64.S',
++ 'x86/x86-darwin.S',
++ 'x86/x86-ffi_darwin.c',
++ 'x86/x86-ffi64.c',
++ 'powerpc/ppc-darwin.S',
++ 'powerpc/ppc-darwin_closure.S',
++ 'powerpc/ppc-ffi_darwin.c',
++ 'powerpc/ppc64-darwin_closure.S',
++ ]]
++
++ # Add .S (preprocessed assembly) to C compiler source extensions.
++ self.compiler.src_extensions.append('.S')
++
++ include_dirs = [os.path.join(ffi_srcdir, 'include'),
++ os.path.join(ffi_srcdir, 'powerpc')]
++ ext.include_dirs.extend(include_dirs)
++ ext.sources.extend(sources)
++ return True
++
+ def configure_ctypes(self, ext):
+ if not self.use_system_libffi:
+- (srcdir,) = sysconfig.get_config_vars('srcdir')
++ if sys.platform == 'darwin':
++ return self.configure_ctypes_darwin(ext)
++
++ srcdir = sysconfig.get_config_var('srcdir')
+ ffi_builddir = os.path.join(self.build_temp, 'libffi')
+ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
+ '_ctypes', 'libffi'))
+@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext):
+ ffi_configfile):
+ from distutils.dir_util import mkpath
+ mkpath(ffi_builddir)
+- config_args = []
++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
++ if (('--host=' in arg) or ('--build=' in arg))]
++ if not self.verbose:
++ config_args.append("-q")
+
+ # Pass empty CFLAGS because we'll just append the resulting
+ # CFLAGS to Python's; -g or -O2 is to be avoided.
+@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext):
+ self.compiler.src_extensions.append('.S')
+
+ include_dirs = [os.path.join(ffi_builddir, 'include'),
+- ffi_builddir, ffi_srcdir]
++ ffi_builddir,
++ os.path.join(ffi_srcdir, 'src')]
+ extra_compile_args = fficonfig['ffi_cflags'].split()
+
+- ext.sources.extend(fficonfig['ffi_sources'])
++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
++ fficonfig['ffi_sources'])
+ ext.include_dirs.extend(include_dirs)
+ ext.extra_compile_args.extend(extra_compile_args)
+ return True
+@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext):
+
+ if sys.platform == 'darwin':
+ sources.append('_ctypes/darwin/dlfcn_simple.c')
++ extra_compile_args.append('-DMACOSX')
+ include_dirs.append('_ctypes/darwin')
+ # XXX Is this still needed?
+ ## extra_link_args.extend(['-read_only_relocs', 'warning'])
+@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext):
+ if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
+ return
+
+- ffi_inc = find_file('ffi.h', [], inc_dirs)
++ if sys.platform == 'darwin':
++ # OS X 10.5 comes with libffi.dylib; the include files are
++ # in /usr/include/ffi
++ inc_dirs.append('/usr/include/ffi')
++
++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
++ if not ffi_inc or ffi_inc[0] == '':
++ ffi_inc = find_file('ffi.h', [], inc_dirs)
+ if ffi_inc is not None:
+ ffi_h = ffi_inc[0] + '/ffi.h'
+ fp = open(ffi_h)
diff --git a/plugins/python-build/share/python-build/patches/2.5.2/Python-2.5.2/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.2/Python-2.5.2/004_osx_libffi.patch
new file mode 100644
index 00000000..cd500771
--- /dev/null
+++ b/plugins/python-build/share/python-build/patches/2.5.2/Python-2.5.2/004_osx_libffi.patch
@@ -0,0 +1,6881 @@
+diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE
+new file mode 100644
+index 0000000..f591795
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README
+new file mode 100644
+index 0000000..1fc2747
+--- /dev/null
++++ ./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: .
++
++
++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
++ #include
++
++ 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
++.
++
++
++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
++ .
++
++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 .
++
++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 . Further enhancements were
++made by Gordon Irlam at Cygnus Solutions .
++
++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 ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc
+new file mode 100644
+index 0000000..405d85f
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c
+new file mode 100644
+index 0000000..bf42093
+--- /dev/null
++++ ./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
++#include
++
++#include
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h
+new file mode 100644
+index 0000000..c104a5c
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/include/ffi.h
+@@ -0,0 +1,355 @@
++/* -----------------------------------------------------------------*-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
++#include
++
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# endif
++#endif
++
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++#error "char size not supported"
++#endif
++
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
++#else
++#error "short size not supported"
++#endif
++
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++#error "int size not supported"
++#endif
++
++#define ffi_type_ulong ffi_type_uint64
++#define ffi_type_slong ffi_type_sint64
++
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != 9223372036854775807
++# error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != 9223372036854775807
++#error "long size not supported"
++#endif
++
++/* The closure code assumes that this works on pointers, i.e. a size_t
++ can hold a pointer. */
++
++typedef struct _ffi_type {
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++/*@null@*/ struct _ffi_type** elements;
++} ffi_type;
++
++/* These are defined in types.c */
++extern ffi_type ffi_type_void;
++extern ffi_type ffi_type_uint8;
++extern ffi_type ffi_type_sint8;
++extern ffi_type ffi_type_uint16;
++extern ffi_type ffi_type_sint16;
++extern ffi_type ffi_type_uint32;
++extern ffi_type ffi_type_sint32;
++extern ffi_type ffi_type_uint64;
++extern ffi_type ffi_type_sint64;
++extern ffi_type ffi_type_float;
++extern ffi_type ffi_type_double;
++extern ffi_type ffi_type_longdouble;
++extern ffi_type ffi_type_pointer;
++
++typedef enum ffi_status {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
++
++typedef unsigned FFI_TYPE;
++
++typedef struct ffi_cif {
++ ffi_abi abi;
++ unsigned nargs;
++/*@dependent@*/ ffi_type** arg_types;
++/*@dependent@*/ ffi_type* rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
++
++/* ---- Definitions for the raw API -------------------------------------- */
++
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == 9223372036854775807
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
++
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
++
++void
++ffi_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_raw_size(
++ ffi_cif* cif);
++
++/* This is analogous to the raw API, except it uses Java parameter
++ packing, even on 64-bit machines. I.e. on 64-bit machines
++ longs and doubles are followed by an empty 64-bit word. */
++void
++ffi_java_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_java_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_java_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_java_raw_size(
++ ffi_cif* cif);
++
++/* ---- Definitions for closures ----------------------------------------- */
++
++#if FFI_CLOSURES
++
++typedef struct ffi_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void* user_data;
++} ffi_closure;
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void* user_data);
++
++void ffi_closure_free(void *);
++void *ffi_closure_alloc (size_t size, void **code);
++
++typedef struct ffi_raw_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++
++#if !FFI_NATIVE_RAW_API
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void* this_closure;
++#endif
++
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void* user_data;
++} ffi_raw_closure;
++
++ffi_status
++ffi_prep_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++ffi_status
++ffi_prep_java_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++#endif // FFI_CLOSURES
++
++/* ---- Public interface definition -------------------------------------- */
++
++ffi_status
++ffi_prep_cif(
++/*@out@*/ /*@partial@*/ ffi_cif* cif,
++ ffi_abi abi,
++ unsigned int nargs,
++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
++/*@dependent@*/ ffi_type** atypes);
++
++void
++ffi_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ void** avalue);
++
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
++
++#endif // #ifndef LIBFFI_ASM
++/* ---- Definitions shared with assembly code ---------------------------- */
++
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++
++#ifdef HAVE_LONG_DOUBLE
++# define FFI_TYPE_LONGDOUBLE 4
++#else
++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_POINTER
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // #ifndef LIBFFI_H
+diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h
+new file mode 100644
+index 0000000..685a358
+--- /dev/null
++++ ./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
++# 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
++#else
++# ifndef HAVE_MEMCPY
++# define memcpy(d, s, n) bcopy((s), (d), (n))
++# endif
++#endif
++
++/*#if defined(FFI_DEBUG)
++#include
++#endif*/
++
++#ifdef FFI_DEBUG
++#include
++
++/*@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 ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h
+new file mode 100644
+index 0000000..2172490
+--- /dev/null
++++ ./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 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 ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h
+new file mode 100644
+index 0000000..faaa30d
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
+new file mode 100644
+index 0000000..2318421
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
+new file mode 100644
+index 0000000..55c2b6c
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+new file mode 100644
+index 0000000..f143dbd
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+@@ -0,0 +1,365 @@
++#if defined(__ppc__) || defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist
++ Copyright (c) 2004 Free Software Foundation, Inc.
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include
++#include
++#include
++
++.text
++ .align 2
++.globl _ffi_prep_args
++
++.text
++ .align 2
++.globl _ffi_call_DARWIN
++
++.text
++ .align 2
++_ffi_call_DARWIN:
++LFB0:
++ mr r12,r8 /* We only need r12 until the call,
++ so it doesn't have to be saved. */
++
++LFB1:
++ /* Save the old stack pointer as AP. */
++ mr r8,r1
++
++LCFI0:
++#if defined(__ppc64__)
++ /* Allocate the stack space we need.
++ r4 (size of input data)
++ 48 bytes (linkage area)
++ 40 bytes (saved registers)
++ 8 bytes (extra FPR)
++ r4 + 96 bytes total
++ */
++
++ addi r4,r4,-96 // Add our overhead.
++ li r0,-32 // Align to 32 bytes.
++ and r4,r4,r0
++#endif
++ stgux r1,r1,r4 // Grow the stack.
++ mflr r9
++
++ /* Save registers we use. */
++#if defined(__ppc64__)
++ std r27,-40(r8)
++#endif
++ stg r28,MODE_CHOICE(-16,-32)(r8)
++ stg r29,MODE_CHOICE(-12,-24)(r8)
++ stg r30,MODE_CHOICE(-8,-16)(r8)
++ stg r31,MODE_CHOICE(-4,-8)(r8)
++ stg r9,SF_RETURN(r8) /* return address */
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ stg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++LCFI1:
++#if defined(__ppc64__)
++ mr r27,r3 // our extended_cif
++#endif
++ /* Save arguments over call. */
++ mr r31,r5 /* flags, */
++ mr r30,r6 /* rvalue, */
++ mr r29,r7 /* function address, */
++ mr r28,r8 /* our AP. */
++
++LCFI2:
++ /* Call ffi_prep_args. */
++ mr r4,r1
++ li r9,0
++ mtctr r12 /* r12 holds address of _ffi_prep_args. */
++ bctrl
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ lg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++ /* Now do the call.
++ Set up cr1 with bits 4-7 of the flags. */
++ mtcrf 0x40,r31
++
++ /* Load all those argument registers.
++ We have set up a nice stack frame, just load it into registers. */
++ lg r3,SF_ARG1(r1)
++ lg r4,SF_ARG2(r1)
++ lg r5,SF_ARG3(r1)
++ lg r6,SF_ARG4(r1)
++ nop
++ lg r7,SF_ARG5(r1)
++ lg r8,SF_ARG6(r1)
++ lg r9,SF_ARG7(r1)
++ lg r10,SF_ARG8(r1)
++
++ /* Load all the FP registers. */
++ bf 6,L2 /* No floats to load. */
++#if defined(__ppc64__)
++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#elif defined(__ppc__)
++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#else
++#error undefined architecture
++#endif
++
++L2:
++ mr r12,r29 // Put the target address in r12 as specified.
++ mtctr r12 // Get the address to call into CTR.
++ nop
++ nop
++ bctrl // Make the call.
++
++ // Deal with the return value.
++#if defined(__ppc64__)
++ mtcrf 0x3,r31 // flags in cr6 and cr7
++ bt 27,L(st_return_value)
++#elif defined(__ppc__)
++ mtcrf 0x1,r31 // flags in cr7
++#else
++#error undefined architecture
++#endif
++
++ bt 30,L(done_return_value)
++ bt 29,L(fp_return_value)
++ stg r3,0(r30)
++#if defined(__ppc__)
++ bf 28,L(done_return_value) // Store the second long if necessary.
++ stg r4,4(r30)
++#endif
++ // Fall through
++
++L(done_return_value):
++ lg r1,0(r1) // Restore stack pointer.
++ // Restore the registers we used.
++ lg r9,SF_RETURN(r1) // return address
++ lg r31,MODE_CHOICE(-4,-8)(r1)
++ mtlr r9
++ lg r30,MODE_CHOICE(-8,-16)(r1)
++ lg r29,MODE_CHOICE(-12,-24)(r1)
++ lg r28,MODE_CHOICE(-16,-32)(r1)
++#if defined(__ppc64__)
++ ld r27,-40(r1)
++#endif
++ blr
++
++#if defined(__ppc64__)
++L(st_return_value):
++ // Grow the stack enough to fit the registers. Leave room for 8 args
++ // to trample the 1st 8 slots in param area.
++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
++
++ // Store GPRs
++ std r3,SF_ARG9(r1)
++ std r4,SF_ARG10(r1)
++ std r5,SF_ARG11(r1)
++ std r6,SF_ARG12(r1)
++ nop
++ std r7,SF_ARG13(r1)
++ std r8,SF_ARG14(r1)
++ std r9,SF_ARG15(r1)
++ std r10,SF_ARG16(r1)
++
++ // Store FPRs
++ nop
++ bf 26,L(call_struct_to_ram_form)
++ stfd f1,SF_ARG17(r1)
++ stfd f2,SF_ARG18(r1)
++ stfd f3,SF_ARG19(r1)
++ stfd f4,SF_ARG20(r1)
++ nop
++ stfd f5,SF_ARG21(r1)
++ stfd f6,SF_ARG22(r1)
++ stfd f7,SF_ARG23(r1)
++ stfd f8,SF_ARG24(r1)
++ nop
++ stfd f9,SF_ARG25(r1)
++ stfd f10,SF_ARG26(r1)
++ stfd f11,SF_ARG27(r1)
++ stfd f12,SF_ARG28(r1)
++ nop
++ stfd f13,SF_ARG29(r1)
++
++L(call_struct_to_ram_form):
++ ld r3,0(r27) // extended_cif->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ addi r4,r1,SF_ARG9 // stored GPRs
++ addi r6,r1,SF_ARG17 // stored FPRs
++ li r5,0 // GPR size ptr (NULL)
++ li r7,0 // FPR size ptr (NULL)
++ li r8,0 // FPR count ptr (NULL)
++ li r10,0 // struct offset (NULL)
++ mr r9,r30 // return area
++ bl Lffi64_struct_to_ram_form$stub
++ lg r1,0(r1) // Restore stack pointer.
++ b L(done_return_value)
++#endif
++
++L(fp_return_value):
++ /* Do we have long double to store? */
++ bf 31,L(fd_return_value)
++ stfd f1,0(r30)
++ stfd f2,8(r30)
++ b L(done_return_value)
++
++L(fd_return_value):
++ /* Do we have double to store? */
++ bf 28,L(float_return_value)
++ stfd f1,0(r30)
++ b L(done_return_value)
++
++L(float_return_value):
++ /* We only have a float to store. */
++ stfs f1,0(r30)
++ b L(done_return_value)
++
++LFE1:
++/* END(_ffi_call_DARWIN) */
++
++/* Provide a null definition of _ffi_call_AIX. */
++.text
++ .align 2
++.globl _ffi_call_AIX
++.text
++ .align 2
++_ffi_call_AIX:
++ blr
++/* END(_ffi_call_AIX) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_call_DARWIN.eh
++_ffi_call_DARWIN.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB0-. ; FDE initial location
++ .set L$set$3,LFE1-LFB0
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x08 ; uleb128 0x08
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$5,LCFI1-LCFI0
++ .long L$set$5
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .byte 0x9f ; DW_CFA_offset, column 0x1f
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x9e ; DW_CFA_offset, column 0x1e
++ .byte 0x2 ; uleb128 0x2
++ .byte 0x9d ; DW_CFA_offset, column 0x1d
++ .byte 0x3 ; uleb128 0x3
++ .byte 0x9c ; DW_CFA_offset, column 0x1c
++ .byte 0x4 ; uleb128 0x4
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$6,LCFI2-LCFI1
++ .long L$set$6
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x1c ; uleb128 0x1c
++ .align LOG2_GPR_BYTES
++LEFDE1:
++
++#if defined(__ppc64__)
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_ram_form$stub:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_ram_form
++
++LO$ffi64_struct_to_ram_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_ram_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
++#endif // __ppc__ || __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+new file mode 100644
+index 0000000..cf4bd50
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+@@ -0,0 +1,85 @@
++/* -----------------------------------------------------------------------
++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define L(x) x
++
++#define SF_ARG9 MODE_CHOICE(56,112)
++#define SF_ARG10 MODE_CHOICE(60,120)
++#define SF_ARG11 MODE_CHOICE(64,128)
++#define SF_ARG12 MODE_CHOICE(68,136)
++#define SF_ARG13 MODE_CHOICE(72,144)
++#define SF_ARG14 MODE_CHOICE(76,152)
++#define SF_ARG15 MODE_CHOICE(80,160)
++#define SF_ARG16 MODE_CHOICE(84,168)
++#define SF_ARG17 MODE_CHOICE(88,176)
++#define SF_ARG18 MODE_CHOICE(92,184)
++#define SF_ARG19 MODE_CHOICE(96,192)
++#define SF_ARG20 MODE_CHOICE(100,200)
++#define SF_ARG21 MODE_CHOICE(104,208)
++#define SF_ARG22 MODE_CHOICE(108,216)
++#define SF_ARG23 MODE_CHOICE(112,224)
++#define SF_ARG24 MODE_CHOICE(116,232)
++#define SF_ARG25 MODE_CHOICE(120,240)
++#define SF_ARG26 MODE_CHOICE(124,248)
++#define SF_ARG27 MODE_CHOICE(128,256)
++#define SF_ARG28 MODE_CHOICE(132,264)
++#define SF_ARG29 MODE_CHOICE(136,272)
++
++#define ASM_NEEDS_REGISTERS 4
++#define NUM_GPR_ARG_REGISTERS 8
++#define NUM_FPR_ARG_REGISTERS 13
++
++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
++#define FFI_TYPE_4_BYTE(x) \
++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
++
++#if !defined(LIBFFI_ASM)
++
++enum {
++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
++ FLAG_RETURNS_FP = 1 << (31 - 29),
++ FLAG_RETURNS_64BITS = 1 << (31 - 28),
++ FLAG_RETURNS_128BITS = 1 << (31 - 31),
++
++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
++
++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
++};
++
++#if defined(__ppc64__)
++void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
++ const char*, unsigned int*, unsigned int*, char*, unsigned int*);
++void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
++ unsigned int*, char*, unsigned int*, char*, unsigned int*);
++bool ffi64_stret_needs_ptr(const ffi_type* inType,
++ unsigned short*, unsigned short*);
++#endif
++
++#endif // !defined(LIBFFI_ASM)
+\ No newline at end of file
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+new file mode 100644
+index 0000000..c3d30c2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+@@ -0,0 +1,308 @@
++#if defined(__ppc__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0 // Save return address
++ stg r0,SF_RETURN(r1)
++
++LCFI0:
++ /* 24/48 bytes (Linkage Area)
++ 32/64 bytes (outgoing parameter area, always reserved)
++ 104 bytes (13*8 from FPR)
++ 16/32 bytes (result)
++ 176/232 total bytes */
++
++ /* skip over caller save area and keep stack aligned to 16/32. */
++ stgu r1,-SF_ROUND(176)(r1)
++
++LCFI1:
++ /* We want to build up an area for the parameters passed
++ in registers. (both floating point and integer) */
++
++ /* 176/256 bytes (callee stack frame aligned to 16/32)
++ 24/48 bytes (caller linkage area)
++ 200/304 (start of caller parameter area aligned to 4/8)
++ */
++
++ /* Save GPRs 3 - 10 (aligned to 4/8)
++ in the parents outgoing area. */
++ stg r3,200(r1)
++ stg r4,204(r1)
++ stg r5,208(r1)
++ stg r6,212(r1)
++ stg r7,216(r1)
++ stg r8,220(r1)
++ stg r9,224(r1)
++ stg r10,228(r1)
++
++ /* Save FPRs 1 - 13. (aligned to 8) */
++ stfd f1,56(r1)
++ stfd f2,64(r1)
++ stfd f3,72(r1)
++ stfd f4,80(r1)
++ stfd f5,88(r1)
++ stfd f6,96(r1)
++ stfd f7,104(r1)
++ stfd f8,112(r1)
++ stfd f9,120(r1)
++ stfd f10,128(r1)
++ stfd f11,136(r1)
++ stfd f12,144(r1)
++ stfd f13,152(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,160 // result storage
++ addi r5,r1,200 // saved GPRs
++ addi r6,r1,56 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ /* Now r3 contains the return type. Use it to look up in a table
++ so we know how to deal with each type. */
++ addi r5,r1,160 // Copy result storage pointer.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ (4 instructions). For cache effectiveness we align to a 16 byte boundary
++ first. */
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++/* case FFI_TYPE_VOID */
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* case FFI_TYPE_INT */
++Lret_type1:
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_FLOAT */
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_DOUBLE */
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_LONGDOUBLE */
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT8 */
++Lret_type5:
++ lbz r3,3(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT8 */
++Lret_type6:
++ lbz r3,3(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT16 */
++Lret_type7:
++ lhz r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT16 */
++Lret_type8:
++ lha r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT32 */
++Lret_type9: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT32 */
++Lret_type10: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT64 */
++Lret_type11:
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_SINT64 */
++Lret_type12: // same as Lret_type11
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_STRUCT */
++Lret_type13:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* End 16-byte aligned cases */
++/* case FFI_TYPE_POINTER */
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ // fall through
++
++/* case done */
++Lfinish:
++ addi r1,r1,SF_ROUND(176) // Restore stack pointer.
++ lg r0,SF_RETURN(r1) // Restore return address.
++ mtlr r0 // Restore link register.
++ blr
++
++/* END(ffi_closure_ASM) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++
++#endif // __ppc__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+new file mode 100644
+index 0000000..8953d5f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+@@ -0,0 +1,1776 @@
++#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
++#include
++
++#include
++#include
++#include
++#include
++#include
++
++#if 0
++#if defined(POWERPC_DARWIN)
++#include // for sys_icache_invalidate()
++#endif
++
++#else
++
++#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)
++ 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
++
++typedef union
++{
++ float f;
++ double d;
++} ffi_dblfl;
++
++/* 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;
++ long 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] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
++ else
++ avalue[i] = (void*)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(temp_ld.lb[0]));
++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
++ 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 ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+new file mode 100644
+index 0000000..7162fa1
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+@@ -0,0 +1,418 @@
++#if defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc64-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0
++ stg r0,SF_RETURN(r1) // save return address
++
++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
++ stg r3,SF_ARG1(r1)
++ stg r4,SF_ARG2(r1)
++ stg r5,SF_ARG3(r1)
++ stg r6,SF_ARG4(r1)
++ stg r7,SF_ARG5(r1)
++ stg r8,SF_ARG6(r1)
++ stg r9,SF_ARG7(r1)
++ stg r10,SF_ARG8(r1)
++
++LCFI0:
++/* 48 bytes (Linkage Area)
++ 64 bytes (outgoing parameter area, always reserved)
++ 112 bytes (14*8 for incoming FPR)
++ ? bytes (result)
++ 112 bytes (14*8 for outgoing FPR)
++ 16 bytes (2 saved registers)
++ 352 + ? total bytes
++*/
++
++ std r31,-8(r1) // Save registers we use.
++ std r30,-16(r1)
++ mr r30,r1 // Save the old SP.
++ mr r31,r11 // Save the ffi_closure around ffi64_data_size.
++
++ // Calculate the space we need.
++ stdu r1,-SF_MINSIZE(r1)
++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ bl Lffi64_data_size$stub
++ ld r1,0(r1)
++
++ addi r3,r3,352 // Add our overhead.
++ neg r3,r3
++ li r0,-32 // Align to 32 bytes.
++ and r3,r3,r0
++ stdux r1,r1,r3 // Grow the stack.
++
++ mr r11,r31 // Copy the ffi_closure back.
++
++LCFI1:
++ // We want to build up an area for the parameters passed
++ // in registers. (both floating point and integer)
++
++/* 320 bytes (callee stack frame aligned to 32)
++ 48 bytes (caller linkage area)
++ 368 (start of caller parameter area aligned to 8)
++*/
++
++ // Save FPRs 1 - 14. (aligned to 8)
++ stfd f1,112(r1)
++ stfd f2,120(r1)
++ stfd f3,128(r1)
++ stfd f4,136(r1)
++ stfd f5,144(r1)
++ stfd f6,152(r1)
++ stfd f7,160(r1)
++ stfd f8,168(r1)
++ stfd f9,176(r1)
++ stfd f10,184(r1)
++ stfd f11,192(r1)
++ stfd f12,200(r1)
++ stfd f13,208(r1)
++ stfd f14,216(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,224 // result storage
++ addi r5,r30,SF_ARG1 // saved GPRs
++ addi r6,r1,112 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ // Look the proper starting point in table
++ // by using return type as an offset.
++ addi r5,r1,224 // Get pointer to results area.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Now multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ // (4 instructions). For cache effectiveness we align to a 16 byte
++ // boundary first.
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++// case FFI_TYPE_VOID
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++// case FFI_TYPE_INT
++Lret_type1:
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_FLOAT
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_DOUBLE
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_LONGDOUBLE
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT8
++Lret_type5:
++ lbz r3,7(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT8
++Lret_type6:
++ lbz r3,7(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT16
++Lret_type7:
++ lhz r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT16
++Lret_type8:
++ lha r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT32
++Lret_type9: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT32
++Lret_type10: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT64
++Lret_type11:
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT64
++Lret_type12: // same as Lret_type11
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_STRUCT
++Lret_type13:
++ b Lret_struct
++ nop
++ nop
++ nop
++
++// ** End 16-byte aligned cases **
++// case FFI_TYPE_POINTER
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ b Lfinish
++
++// copy struct into registers
++Lret_struct:
++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r31) // ffi_cif->rtype*
++ ld r31,24(r31) // ffi_cif->flags
++ mr r4,r5 // copy struct* to 2nd arg
++ addi r7,r1,SF_ARG9 // GPR return area
++ addi r9,r30,-16-(14*8) // FPR return area
++ li r5,0 // struct offset ptr (NULL)
++ li r6,0 // FPR used count ptr (NULL)
++ li r8,0 // GPR return area size ptr (NULL)
++ li r10,0 // FPR return area size ptr (NULL)
++ bl Lffi64_struct_to_reg_form$stub
++
++ // Load GPRs
++ ld r3,SF_ARG9(r1)
++ ld r4,SF_ARG10(r1)
++ ld r5,SF_ARG11(r1)
++ ld r6,SF_ARG12(r1)
++ nop
++ ld r7,SF_ARG13(r1)
++ ld r8,SF_ARG14(r1)
++ ld r9,SF_ARG15(r1)
++ ld r10,SF_ARG16(r1)
++ nop
++
++ // Load FPRs
++ mtcrf 0x2,r31
++ bf 26,Lfinish
++ lfd f1,-16-(14*8)(r30)
++ lfd f2,-16-(13*8)(r30)
++ lfd f3,-16-(12*8)(r30)
++ lfd f4,-16-(11*8)(r30)
++ nop
++ lfd f5,-16-(10*8)(r30)
++ lfd f6,-16-(9*8)(r30)
++ lfd f7,-16-(8*8)(r30)
++ lfd f8,-16-(7*8)(r30)
++ nop
++ lfd f9,-16-(6*8)(r30)
++ lfd f10,-16-(5*8)(r30)
++ lfd f11,-16-(4*8)(r30)
++ lfd f12,-16-(3*8)(r30)
++ nop
++ lfd f13,-16-(2*8)(r30)
++ lfd f14,-16-(1*8)(r30)
++ // Fall through
++
++// case done
++Lfinish:
++ lg r1,0(r1) // Restore stack pointer.
++ ld r31,-8(r1) // Restore registers we used.
++ ld r30,-16(r1)
++ lg r0,SF_RETURN(r1) // Get return address.
++ mtlr r0 // Reset link register.
++ blr
++
++// END(ffi_closure_ASM)
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_reg_form$stub:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_reg_form
++
++LO$ffi64_struct_to_reg_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
++ mtctr r12
++ bctr
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_data_size$stub:
++ .indirect_symbol _ffi64_data_size
++ mflr r0
++ bcl 20,31,LO$ffi64_data_size
++
++LO$ffi64_data_size:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_reg_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ .g_long dyld_stub_binding_helper
++
++L_ffi64_data_size$lazy_ptr:
++ .indirect_symbol _ffi64_data_size
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c
+new file mode 100644
+index 0000000..44806ae
+--- /dev/null
++++ ./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
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+new file mode 100644
+index 0000000..165d469
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+@@ -0,0 +1,417 @@
++/* -----------------------------------------------------------------------
++ 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
++#include
++
++ .file "darwin64.S"
++.text
++
++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
++ void *raddr, void (*fnaddr)());
++
++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
++ for this function. This has been allocated by ffi_call. We also
++ deallocate some of the stack that has been alloca'd. */
++
++ .align 3
++ .globl _ffi_call_unix64
++
++_ffi_call_unix64:
++LUW0:
++ movq (%rsp), %r10 /* Load return address. */
++ movq %rdi, %r12 /* Save a copy of the register area. */
++ leaq (%rdi, %rsi), %rax /* Find local stack base. */
++ movq %rdx, (%rax) /* Save flags. */
++ movq %rcx, 8(%rax) /* Save raddr. */
++ movq %rbp, 16(%rax) /* Save old frame pointer. */
++ movq %r10, 24(%rax) /* Relocate return address. */
++ movq %rax, %rbp /* Finalize local stack frame. */
++LUW1:
++ /* movq %rdi, %r10 // Save a copy of the register area. */
++ movq %r12, %r10
++ movq %r8, %r11 /* Save a copy of the target fn. */
++ movl %r9d, %eax /* Set number of SSE registers. */
++
++ /* Load up all argument registers. */
++ movq (%r10), %rdi
++ movq 8(%r10), %rsi
++ movq 16(%r10), %rdx
++ movq 24(%r10), %rcx
++ movq 32(%r10), %r8
++ movq 40(%r10), %r9
++ testl %eax, %eax
++ jnz Lload_sse
++Lret_from_load_sse:
++
++ /* Deallocate the reg arg area. */
++ leaq 176(%r10), %rsp
++
++ /* Call the user function. */
++ call *%r11
++
++ /* Deallocate stack arg area; local stack frame in redzone. */
++ leaq 24(%rbp), %rsp
++
++ movq 0(%rbp), %rcx /* Reload flags. */
++ movq 8(%rbp), %rdi /* Reload raddr. */
++ movq 16(%rbp), %rbp /* Reload old frame pointer. */
++LUW2:
++
++ /* The first byte of the flags contains the FFI_TYPE. */
++ movzbl %cl, %r10d
++ leaq Lstore_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lstore_table:
++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lst_void:
++ ret
++ .align 3
++Lst_uint8:
++ movzbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_sint8:
++ movsbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint16:
++ movzwq %ax, %rax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint16:
++ movswq %ax, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint32:
++ movl %eax, %eax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint32:
++ cltq
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_int64:
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_float:
++ movss %xmm0, (%rdi)
++ ret
++ .align 3
++Lst_double:
++ movsd %xmm0, (%rdi)
++ ret
++Lst_ldouble:
++ fstpt (%rdi)
++ ret
++ .align 3
++Lst_struct:
++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */
++
++ /* We have to locate the values now, and since we don't want to
++ write too much data into the user's return value, we spill the
++ value to a 16 byte scratch area first. Bits 8, 9, and 10
++ control where the values are located. Only one of the three
++ bits will be set; see ffi_prep_cif_machdep for the pattern. */
++ movd %xmm0, %r10
++ movd %xmm1, %r11
++ testl $0x100, %ecx
++ cmovnz %rax, %rdx
++ cmovnz %r10, %rax
++ testl $0x200, %ecx
++ cmovnz %r10, %rdx
++ testl $0x400, %ecx
++ cmovnz %r10, %rax
++ cmovnz %r11, %rdx
++ movq %rax, (%rsi)
++ movq %rdx, 8(%rsi)
++
++ /* Bits 12-31 contain the true size of the structure. Copy from
++ the scratch area to the true destination. */
++ shrl $12, %ecx
++ rep movsb
++ ret
++
++ /* Many times we can avoid loading any SSE registers at all.
++ It's not worth an indirect jump to load the exact set of
++ SSE registers needed; zero or all is a good compromise. */
++ .align 3
++LUW3:
++Lload_sse:
++ movdqa 48(%r10), %xmm0
++ movdqa 64(%r10), %xmm1
++ movdqa 80(%r10), %xmm2
++ movdqa 96(%r10), %xmm3
++ movdqa 112(%r10), %xmm4
++ movdqa 128(%r10), %xmm5
++ movdqa 144(%r10), %xmm6
++ movdqa 160(%r10), %xmm7
++ jmp Lret_from_load_sse
++
++LUW4:
++ .align 3
++ .globl _ffi_closure_unix64
++
++_ffi_closure_unix64:
++LUW5:
++ /* The carry flag is set by the trampoline iff SSE registers
++ are used. Don't clobber it before the branch instruction. */
++ leaq -200(%rsp), %rsp
++LUW6:
++ movq %rdi, (%rsp)
++ movq %rsi, 8(%rsp)
++ movq %rdx, 16(%rsp)
++ movq %rcx, 24(%rsp)
++ movq %r8, 32(%rsp)
++ movq %r9, 40(%rsp)
++ jc Lsave_sse
++Lret_from_save_sse:
++
++ movq %r10, %rdi
++ leaq 176(%rsp), %rsi
++ movq %rsp, %rdx
++ leaq 208(%rsp), %rcx
++ call _ffi_closure_unix64_inner
++
++ /* Deallocate stack frame early; return value is now in redzone. */
++ addq $200, %rsp
++LUW7:
++
++ /* The first byte of the return value contains the FFI_TYPE. */
++ movzbl %al, %r10d
++ leaq Lload_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lload_table:
++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */
++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */
++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lld_void:
++ ret
++ .align 3
++Lld_int8:
++ movzbl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int16:
++ movzwl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int32:
++ movl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int64:
++ movq -24(%rsp), %rax
++ ret
++ .align 3
++Lld_float:
++ movss -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_double:
++ movsd -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_ldouble:
++ fldt -24(%rsp)
++ ret
++ .align 3
++Lld_struct:
++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
++ both rdx and xmm1 with the second word. For the remaining,
++ bit 8 set means xmm0 gets the second word, and bit 9 means
++ that rax gets the second word. */
++ movq -24(%rsp), %rcx
++ movq -16(%rsp), %rdx
++ movq -16(%rsp), %xmm1
++ testl $0x100, %eax
++ cmovnz %rdx, %rcx
++ movd %rcx, %xmm0
++ testl $0x200, %eax
++ movq -24(%rsp), %rax
++ cmovnz %rdx, %rax
++ ret
++
++ /* See the comment above Lload_sse; the same logic applies here. */
++ .align 3
++LUW8:
++Lsave_sse:
++ movdqa %xmm0, 48(%rsp)
++ movdqa %xmm1, 64(%rsp)
++ movdqa %xmm2, 80(%rsp)
++ movdqa %xmm3, 96(%rsp)
++ movdqa %xmm4, 112(%rsp)
++ movdqa %xmm5, 128(%rsp)
++ movdqa %xmm6, 144(%rsp)
++ movdqa %xmm7, 160(%rsp)
++ jmp Lret_from_save_sse
++
++LUW9:
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */
++ .long L$set$0
++LSCIE1:
++ .long 0x0 /* CIE Identifier Tag */
++ .byte 0x1 /* CIE Version */
++ .ascii "zR\0" /* CIE Augmentation */
++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
++ .byte 0x10 /* CIE RA Column */
++ .byte 0x1 /* uleb128 0x1; Augmentation size */
++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */
++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
++ .byte 0x7 /* uleb128 0x7 */
++ .byte 0x8 /* uleb128 0x8 */
++ .byte 0x90 /* DW_CFA_offset, column 0x10 */
++ .byte 0x1
++ .align 3
++LECIE1:
++ .globl _ffi_call_unix64.eh
++_ffi_call_unix64.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1 /* FDE CIE offset */
++ .quad LUW0-. /* FDE initial location */
++ .set L$set$2,LUW4-LUW0 /* FDE address range */
++ .quad L$set$2
++ .byte 0x0 /* Augmentation size */
++ .byte 0x4 /* DW_CFA_advance_loc4 */
++ .set L$set$3,LUW1-LUW0
++ .long L$set$3
++
++ /* New stack frame based off rbp. This is 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 ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+new file mode 100644
+index 0000000..925a841
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+@@ -0,0 +1,422 @@
++#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
++#include
++
++#ifdef PyObjC_STRICT_DEBUGGING
++ /* XXX: Debugging of stack alignment, to be removed */
++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
++#else
++#define ASSERT_STACK_ALIGNED
++#endif
++
++.text
++
++.globl _ffi_prep_args
++
++ .align 4
++.globl _ffi_call_SYSV
++
++_ffi_call_SYSV:
++LFB1:
++ pushl %ebp
++LCFI0:
++ movl %esp,%ebp
++LCFI1:
++ subl $8,%esp
++ /* Make room for all of the new args. */
++ movl 16(%ebp),%ecx
++ subl %ecx,%esp
++
++ movl %esp,%eax
++
++ /* Place all of the ffi_prep_args in position */
++ subl $8,%esp
++ pushl 12(%ebp)
++ pushl %eax
++ call *8(%ebp)
++
++ /* Return stack to previous state and call the function */
++ addl $16,%esp
++
++ call *28(%ebp)
++
++ /* Remove the space we pushed for the args */
++ movl 16(%ebp),%ecx
++ addl %ecx,%esp
++
++ /* Load %ecx with the return type code */
++ movl 20(%ebp),%ecx
++
++ /* If the return value pointer is NULL, assume no return value. */
++ cmpl $0,24(%ebp)
++ jne Lretint
++
++ /* Even if there is no space for the return value, we are
++ obliged to handle floating-point values. */
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lnoretval
++ fstp %st(0)
++
++ jmp Lepilogue
++
++Lretint:
++ cmpl $FFI_TYPE_INT,%ecx
++ jne Lretfloat
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ jmp Lepilogue
++
++Lretfloat:
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lretdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstps (%ecx)
++ jmp Lepilogue
++
++Lretdouble:
++ cmpl $FFI_TYPE_DOUBLE,%ecx
++ jne Lretlongdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpl (%ecx)
++ jmp Lepilogue
++
++Lretlongdouble:
++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx
++ jne Lretint64
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpt (%ecx)
++ jmp Lepilogue
++
++Lretint64:
++ cmpl $FFI_TYPE_SINT64,%ecx
++ jne Lretstruct1b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ movl %edx,4(%ecx)
++ jmp Lepilogue
++
++Lretstruct1b:
++ cmpl $FFI_TYPE_SINT8,%ecx
++ jne Lretstruct2b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movb %al,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct2b:
++ cmpl $FFI_TYPE_SINT16,%ecx
++ jne Lretstruct
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movw %ax,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct:
++ cmpl $FFI_TYPE_STRUCT,%ecx
++ jne Lnoretval
++ /* Nothing to do! */
++ addl $4,%esp
++ popl %ebp
++ ret
++
++Lnoretval:
++Lepilogue:
++ addl $8,%esp
++ movl %ebp,%esp
++ popl %ebp
++ ret
++LFE1:
++.ffi_call_SYSV_end:
++
++ .align 4
++FFI_HIDDEN (ffi_closure_SYSV)
++.globl _ffi_closure_SYSV
++
++_ffi_closure_SYSV:
++LFB2:
++ pushl %ebp
++LCFI2:
++ movl %esp, %ebp
++LCFI3:
++ subl $56, %esp
++ leal -40(%ebp), %edx
++ movl %edx, -12(%ebp) /* resp */
++ leal 8(%ebp), %edx
++ movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
++ leal -12(%ebp), %edx
++ movl %edx, (%esp) /* &resp */
++ movl %ebx, 8(%esp)
++LCFI7:
++ call L_ffi_closure_SYSV_inner$stub
++ movl 8(%esp), %ebx
++ movl -12(%ebp), %ecx
++ cmpl $FFI_TYPE_INT, %eax
++ je Lcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lcls_retllong
++ cmpl $FFI_TYPE_UINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_SINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_UINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_SINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_STRUCT, %eax
++ je Lcls_retstruct
++Lcls_epilogue:
++ movl %ebp, %esp
++ popl %ebp
++ ret
++Lcls_retint:
++ movl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retfloat:
++ flds (%ecx)
++ jmp Lcls_epilogue
++Lcls_retdouble:
++ fldl (%ecx)
++ jmp Lcls_epilogue
++Lcls_retldouble:
++ fldt (%ecx)
++ jmp Lcls_epilogue
++Lcls_retllong:
++ movl (%ecx), %eax
++ movl 4(%ecx), %edx
++ jmp Lcls_epilogue
++Lcls_retstruct1:
++ movsbl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct2:
++ movswl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct:
++ lea -8(%ebp),%esp
++ movl %ebp, %esp
++ popl %ebp
++ ret $4
++LFE2:
++
++#if !FFI_NO_RAW_API
++
++#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
++#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
++#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
++#define CIF_FLAGS_OFFSET 20
++
++ .align 4
++FFI_HIDDEN (ffi_closure_raw_SYSV)
++.globl _ffi_closure_raw_SYSV
++
++_ffi_closure_raw_SYSV:
++LFB3:
++ pushl %ebp
++LCFI4:
++ movl %esp, %ebp
++LCFI5:
++ pushl %esi
++LCFI6:
++ subl $36, %esp
++ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
++ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
++ movl %edx, 12(%esp) /* user_data */
++ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
++ movl %edx, 8(%esp) /* raw_args */
++ leal -24(%ebp), %edx
++ movl %edx, 4(%esp) /* &res */
++ movl %esi, (%esp) /* cif */
++ call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
++ movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
++ cmpl $FFI_TYPE_INT, %eax
++ je Lrcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lrcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lrcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lrcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lrcls_retllong
++Lrcls_epilogue:
++ addl $36, %esp
++ popl %esi
++ popl %ebp
++ ret
++Lrcls_retint:
++ movl -24(%ebp), %eax
++ jmp Lrcls_epilogue
++Lrcls_retfloat:
++ flds -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retdouble:
++ fldl -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retldouble:
++ fldt -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retllong:
++ movl -24(%ebp), %eax
++ movl -20(%ebp), %edx
++ jmp Lrcls_epilogue
++LFE3:
++#endif
++
++.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
++L_ffi_closure_SYSV_inner$stub:
++ .indirect_symbol _ffi_closure_SYSV_inner
++ hlt ; hlt ; hlt ; hlt ; hlt
++
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0
++LSCIE1:
++ .long 0x0
++ .byte 0x1
++ .ascii "zR\0"
++ .byte 0x1
++ .byte 0x7c
++ .byte 0x8
++ .byte 0x1
++ .byte 0x10
++ .byte 0xc
++ .byte 0x5
++ .byte 0x4
++ .byte 0x88
++ .byte 0x1
++ .align 2
++LECIE1:
++.globl _ffi_call_SYSV.eh
++_ffi_call_SYSV.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1
++ .long LFB1-.
++ .set L$set$2,LFE1-LFB1
++ .long L$set$2
++ .byte 0x0
++ .byte 0x4
++ .set L$set$3,LCFI0-LFB1
++ .long L$set$3
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$4,LCFI1-LCFI0
++ .long L$set$4
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE1:
++.globl _ffi_closure_SYSV.eh
++_ffi_closure_SYSV.eh:
++LSFDE2:
++ .set L$set$5,LEFDE2-LASFDE2
++ .long L$set$5
++LASFDE2:
++ .long LASFDE2-EH_frame1
++ .long LFB2-.
++ .set L$set$6,LFE2-LFB2
++ .long L$set$6
++ .byte 0x0
++ .byte 0x4
++ .set L$set$7,LCFI2-LFB2
++ .long L$set$7
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$8,LCFI3-LCFI2
++ .long L$set$8
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE2:
++
++#if !FFI_NO_RAW_API
++
++.globl _ffi_closure_raw_SYSV.eh
++_ffi_closure_raw_SYSV.eh:
++LSFDE3:
++ .set L$set$10,LEFDE3-LASFDE3
++ .long L$set$10
++LASFDE3:
++ .long LASFDE3-EH_frame1
++ .long LFB3-.
++ .set L$set$11,LFE3-LFB3
++ .long L$set$11
++ .byte 0x0
++ .byte 0x4
++ .set L$set$12,LCFI4-LFB3
++ .long L$set$12
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$13,LCFI5-LCFI4
++ .long L$set$13
++ .byte 0xd
++ .byte 0x4
++ .byte 0x4
++ .set L$set$14,LCFI6-LCFI5
++ .long L$set$14
++ .byte 0x85
++ .byte 0x3
++ .align 2
++LEFDE3:
++
++#endif
++
++#endif /* ifndef __x86_64__ */
++
++#endif /* defined __i386__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+new file mode 100644
+index 0000000..06feaf2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+@@ -0,0 +1,734 @@
++#ifdef __x86_64__
++
++/* -----------------------------------------------------------------------
++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen
++
++ 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
++#include
++
++#include
++#include
++
++#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 0
++ if (byte_offset + type->size <= 4)
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ else
++ classes[0] = X86_64_INTEGER_CLASS;
++
++ return 1;
++#else
++ {
++ int size = byte_offset + type->size;
++
++ if (size <= 4)
++ {
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ return 1;
++ }
++ else if (size <= 8)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ return 1;
++ }
++ else if (size <= 12)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else if (size <= 16)
++ {
++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else
++ FFI_ASSERT (0);
++ }
++#endif
++
++ case FFI_TYPE_FLOAT:
++ if (byte_offset == 0)
++ classes[0] = X86_64_SSESF_CLASS;
++ else
++ classes[0] = X86_64_SSE_CLASS;
++
++ return 1;
++
++ case FFI_TYPE_DOUBLE:
++ classes[0] = X86_64_SSEDF_CLASS;
++ return 1;
++
++ case FFI_TYPE_LONGDOUBLE:
++ classes[0] = X86_64_X87_CLASS;
++ classes[1] = X86_64_X87UP_CLASS;
++ return 2;
++
++ case FFI_TYPE_STRUCT:
++ {
++ ffi_type** ptr;
++ int i;
++ enum x86_64_reg_class subclasses[MAX_CLASSES];
++ const int UNITS_PER_WORD = 8;
++ int words =
++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++
++ /* If the struct is larger than 16 bytes, pass it on the stack. */
++ if (type->size > 16)
++ return 0;
++
++ for (i = 0; i < words; i++)
++ classes[i] = X86_64_NO_CLASS;
++
++ /* Merge the fields of structure. */
++ for (ptr = type->elements; *ptr != NULL; ptr++)
++ {
++ 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;
++ }
++
++ if (words > 2)
++ {
++ /* When size > 16 bytes, if the first one isn't
++ X86_64_SSE_CLASS or any other ones aren't
++ X86_64_SSEUP_CLASS, everything should be passed in
++ memory. */
++ if (classes[0] != X86_64_SSE_CLASS)
++ return 0;
++
++ for (i = 1; i < words; i++)
++ if (classes[i] != X86_64_SSEUP_CLASS)
++ return 0;
++ }
++
++
++ /* Final merger cleanup. */
++ for (i = 0; i < words; i++)
++ {
++ /* If one class is MEMORY, everything should be passed in
++ memory. */
++ if (classes[i] == X86_64_MEMORY_CLASS)
++ return 0;
++
++ /* The X86_64_SSEUP_CLASS should be always preceded by
++ X86_64_SSE_CLASS. */
++ if (classes[i] == X86_64_SSEUP_CLASS
++ && classes[i - 1] != X86_64_SSE_CLASS
++ && classes[i - 1] != X86_64_SSEUP_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++
++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
++ if (classes[i] == X86_64_X87UP_CLASS
++ && classes[i - 1] != X86_64_X87_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++ }
++
++ return words;
++ }
++
++ default:
++ FFI_ASSERT(0);
++ }
++
++ return 0; /* Never reached. */
++}
++
++/* Examine the argument and return set number of register required in each
++ class. Return zero if parameter should be passed in memory, otherwise
++ the number of registers. */
++static int
++examine_argument(
++ ffi_type* type,
++ enum x86_64_reg_class classes[MAX_CLASSES],
++ _Bool in_return,
++ int* pngpr,
++ int* pnsse)
++{
++ int n = classify_argument(type, classes, 0);
++ int ngpr = 0;
++ int nsse = 0;
++ int i;
++
++ if (n == 0)
++ return 0;
++
++ for (i = 0; i < n; ++i)
++ {
++ switch (classes[i])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ ngpr++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSESF_CLASS:
++ case X86_64_SSEDF_CLASS:
++ nsse++;
++ break;
++
++ case X86_64_NO_CLASS:
++ case X86_64_SSEUP_CLASS:
++ break;
++
++ case X86_64_X87_CLASS:
++ case X86_64_X87UP_CLASS:
++ case X86_64_COMPLEX_X87_CLASS:
++ return in_return != 0;
++
++ default:
++ abort();
++ }
++ }
++
++ *pngpr = ngpr;
++ *pnsse = nsse;
++
++ return n;
++}
++
++/* Perform machine dependent cif processing. */
++ffi_status
++ffi_prep_cif_machdep(
++ ffi_cif* cif)
++{
++ int gprcount = 0;
++ int ssecount = 0;
++ int flags = cif->rtype->type;
++ int i, avn, n, ngpr, nsse;
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ size_t bytes;
++
++ if (flags != FFI_TYPE_VOID)
++ {
++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value is passed in memory. A pointer to that
++ memory is the first argument. Allocate a register for it. */
++ gprcount++;
++
++ /* We don't have to do anything in asm for the return. */
++ flags = FFI_TYPE_VOID;
++ }
++ else if (flags == FFI_TYPE_STRUCT)
++ {
++ /* Mark which registers the result appears in. */
++ _Bool sse0 = SSE_CLASS_P(classes[0]);
++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
++
++ if (sse0 && !sse1)
++ flags |= 1 << 8;
++ else if (!sse0 && sse1)
++ flags |= 1 << 9;
++ else if (sse0 && sse1)
++ flags |= 1 << 10;
++
++ /* Mark the true size of the structure. */
++ flags |= cif->rtype->size << 12;
++ }
++ }
++
++ /* Go over all arguments and determine the way they should be passed.
++ If it's in a register and there is space for it, let that be so. If
++ not, add it's size to the stack byte count. */
++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
++ {
++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = cif->arg_types[i]->alignment;
++
++ if (align < 8)
++ align = 8;
++
++ bytes = ALIGN(bytes, align);
++ bytes += cif->arg_types[i]->size;
++ }
++ else
++ {
++ gprcount += ngpr;
++ ssecount += nsse;
++ }
++ }
++
++ if (ssecount)
++ flags |= 1 << 11;
++
++ cif->flags = flags;
++ cif->bytes = bytes;
++ cif->bytes = ALIGN(bytes,8);
++
++ return FFI_OK;
++}
++
++void
++ffi_call(
++ ffi_cif* cif,
++ void (*fn)(),
++ void* rvalue,
++ void** avalue)
++{
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ char* stack;
++ char* argp;
++ ffi_type** arg_types;
++ int gprcount, ssecount, ngpr, nsse, i, avn;
++ _Bool ret_in_memory;
++ RegisterArgs* reg_args;
++
++ /* Can't call 32-bit mode from 64-bit mode. */
++ FFI_ASSERT(cif->abi == FFI_UNIX64);
++
++ /* If the return value is a struct and we don't have a return value
++ address then we need to make one. Note the setting of flags to
++ VOID above in ffi_prep_cif_machdep. */
++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
++ && (cif->flags & 0xff) == FFI_TYPE_VOID);
++
++ if (rvalue == NULL && ret_in_memory)
++ rvalue = alloca (cif->rtype->size);
++
++ /* Allocate the space for the arguments, plus 4 words of temp space. */
++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
++ reg_args = (RegisterArgs*)stack;
++ argp = stack + sizeof(RegisterArgs);
++
++ gprcount = ssecount = 0;
++
++ /* If the return value is passed in memory, add the pointer as the
++ first integer argument. */
++ if (ret_in_memory)
++ reg_args->gpr[gprcount++] = (long) rvalue;
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ size_t size = arg_types[i]->size;
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ memcpy (argp, avalue[i], size);
++ argp += size;
++ }
++ else
++ { /* The argument is passed entirely in registers. */
++ char *a = (char *) avalue[i];
++ int j;
++
++ for (j = 0; j < n; j++, a += 8, size -= 8)
++ {
++ switch (classes[j])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ reg_args->gpr[gprcount] = 0;
++ switch (arg_types[i]->type) {
++ case FFI_TYPE_SINT8:
++ {
++ int8_t shortval = *(int8_t*)a;
++ int64_t actval = (int64_t)shortval;
++ reg_args->gpr[gprcount] = actval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ break;
++ }
++
++ case FFI_TYPE_SINT16:
++ {
++ int16_t shortval = *(int16_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_SINT32:
++ {
++ int32_t shortval = *(int32_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT8:
++ {
++ u_int8_t shortval = *(u_int8_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ reg_args->gpr[gprcount] = actval;
++ break;
++ }
++
++ case FFI_TYPE_UINT16:
++ {
++ u_int16_t shortval = *(u_int16_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT32:
++ {
++ u_int32_t shortval = *(u_int32_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ default:
++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
++ reg_args->gpr[gprcount] = *(int64_t*)a;
++ }
++ gprcount++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSEDF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT64 *) a;
++ break;
++
++ case X86_64_SSESF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT32 *) a;
++ break;
++
++ default:
++ abort();
++ }
++ }
++ }
++ }
++
++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
++ cif->flags, rvalue, fn, ssecount);
++}
++
++extern void ffi_closure_unix64(void);
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*, void*, void**, void*),
++ void* user_data)
++{
++ if (cif->abi != FFI_UNIX64)
++ return FFI_BAD_ABI;
++
++ volatile unsigned short* tramp =
++ (volatile unsigned short*)&closure->tramp[0];
++
++ tramp[0] = 0xbb49; /* mov , %r11 */
++ *(void* volatile*)&tramp[1] = ffi_closure_unix64;
++ tramp[5] = 0xba49; /* mov , %r10 */
++ *(void* volatile*)&tramp[6] = closure;
++
++ /* Set the carry bit if the function uses any sse registers.
++ This is clc or stc, together with the first byte of the jmp. */
++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
++ tramp[11] = 0xe3ff; /* jmp *%r11 */
++
++ closure->cif = cif;
++ closure->fun = fun;
++ closure->user_data = user_data;
++
++ return FFI_OK;
++}
++
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wmissing-prototypes"
++int
++ffi_closure_unix64_inner(
++ ffi_closure* closure,
++ void* rvalue,
++ RegisterArgs* reg_args,
++ char* argp)
++#pragma clang diagnostic pop
++{
++ ffi_cif* cif = closure->cif;
++ void** avalue = alloca(cif->nargs * sizeof(void *));
++ ffi_type** arg_types;
++ long i, avn;
++ int gprcount = 0;
++ int ssecount = 0;
++ int ngpr, nsse;
++ int ret;
++
++ ret = cif->rtype->type;
++
++ if (ret != FFI_TYPE_VOID)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value goes in memory. Arrange for the closure
++ return value to go directly back to the original caller. */
++ rvalue = (void *) reg_args->gpr[gprcount++];
++
++ /* We don't have to do anything in asm for the return. */
++ ret = FFI_TYPE_VOID;
++ }
++ else if (ret == FFI_TYPE_STRUCT && n == 2)
++ {
++ /* Mark which register the second word of the structure goes in. */
++ _Bool sse0 = SSE_CLASS_P (classes[0]);
++ _Bool sse1 = SSE_CLASS_P (classes[1]);
++
++ if (!sse0 && sse1)
++ ret |= 1 << 8;
++ else if (sse0 && !sse1)
++ ret |= 1 << 9;
++ }
++ }
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ avalue[i] = argp;
++ argp += arg_types[i]->size;
++ }
++
++#if !defined(X86_DARWIN)
++ /* If the argument is in a single register, or two consecutive
++ registers, then we can use that address directly. */
++ else if (n == 1 || (n == 2 &&
++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
++ {
++ // The argument is in a single register.
++ if (SSE_CLASS_P (classes[0]))
++ {
++ avalue[i] = ®_args->sse[ssecount];
++ ssecount += n;
++ }
++ else
++ {
++ avalue[i] = ®_args->gpr[gprcount];
++ gprcount += n;
++ }
++ }
++#endif
++
++ /* Otherwise, allocate space to make them consecutive. */
++ else
++ {
++ char *a = alloca (16);
++ int j;
++
++ avalue[i] = a;
++
++ for (j = 0; j < n; j++, a += 8)
++ {
++ if (SSE_CLASS_P (classes[j]))
++ memcpy (a, ®_args->sse[ssecount++], 8);
++ else
++ memcpy (a, ®_args->gpr[gprcount++], 8);
++ }
++ }
++ }
++
++ /* Invoke the closure. */
++ closure->fun (cif, rvalue, avalue, closure->user_data);
++
++ /* Tell assembly how to perform return type promotions. */
++ return ret;
++}
++
++#endif /* __x86_64__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+new file mode 100644
+index 0000000..706ea0f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+@@ -0,0 +1,438 @@
++#ifdef __i386__
++/* -----------------------------------------------------------------------
++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
++ Copyright (c) 2002 Ranjit Mathew
++ Copyright (c) 2002 Bo Thorsen
++ Copyright (c) 2002 Roger Sayle
++
++ x86 Foreign Function Interface
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#include
++#include
++
++#include
++
++/* ffi_prep_args is called by the assembly routine once stack space
++ has been allocated for the function's arguments */
++
++void ffi_prep_args(char *stack, extended_cif *ecif);
++
++void ffi_prep_args(char *stack, extended_cif *ecif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if (ecif->cif->flags == FFI_TYPE_STRUCT)
++ {
++ *(void **) argp = ecif->rvalue;
++ argp += 4;
++ }
++
++ p_argv = ecif->avalue;
++
++ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
++ i != 0;
++ i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp)
++ argp = (char *) ALIGN(argp, sizeof(int));
++
++ z = (*p_arg)->size;
++ if (z < sizeof(int))
++ {
++ z = sizeof(int);
++ switch ((*p_arg)->type)
++ {
++ case FFI_TYPE_SINT8:
++ *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT8:
++ *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT16:
++ *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT16:
++ *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT32:
++ *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT32:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_STRUCT:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ default:
++ FFI_ASSERT(0);
++ }
++ }
++ else
++ {
++ memcpy(argp, *p_argv, z);
++ }
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* Perform machine dependent cif processing */
++ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++{
++ /* Set the return type flag */
++ switch (cif->rtype->type)
++ {
++ case FFI_TYPE_VOID:
++#ifdef X86
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_SINT16:
++#endif
++
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ cif->flags = (unsigned) cif->rtype->type;
++ break;
++
++ case FFI_TYPE_UINT64:
++ cif->flags = FFI_TYPE_SINT64;
++ break;
++
++#ifndef X86
++ case FFI_TYPE_STRUCT:
++ if (cif->rtype->size == 1)
++ {
++ cif->flags = FFI_TYPE_SINT8; /* same as char size */
++ }
++ else if (cif->rtype->size == 2)
++ {
++ cif->flags = FFI_TYPE_SINT16; /* same as short size */
++ }
++ else if (cif->rtype->size == 4)
++ {
++ cif->flags = FFI_TYPE_INT; /* same as int type */
++ }
++ else if (cif->rtype->size == 8)
++ {
++ cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
++ }
++ else
++ {
++ cif->flags = FFI_TYPE_STRUCT;
++ }
++ break;
++#endif
++
++ default:
++ cif->flags = FFI_TYPE_INT;
++ break;
++ }
++
++#ifdef X86_DARWIN
++ cif->bytes = (cif->bytes + 15) & ~0xF;
++#endif
++
++ return FFI_OK;
++}
++
++extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#endif /* X86_WIN32 */
++
++void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
++{
++ extended_cif ecif;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->flags == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
++ fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++
++/** private members **/
++
++static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
++ void** args, ffi_cif* cif);
++void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
++__attribute__ ((regparm(1)));
++unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
++__attribute__ ((regparm(1)));
++void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
++__attribute__ ((regparm(1)));
++
++/* This function is jumped to by the trampoline */
++
++unsigned int FFI_HIDDEN
++ffi_closure_SYSV_inner (closure, respp, args)
++ffi_closure *closure;
++void **respp;
++void *args;
++{
++ // our various things...
++ ffi_cif *cif;
++ void **arg_area;
++
++ cif = closure->cif;
++ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
++
++ /* this call will initialize ARG_AREA, such that each
++ * element in that array points to the corresponding
++ * value on the stack; and if the function returns
++ * a structure, it will re-set RESP to point to the
++ * structure return address. */
++
++ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
++
++ (closure->fun) (cif, *respp, arg_area, closure->user_data);
++
++ return cif->flags;
++}
++
++static void
++ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
++ ffi_cif *cif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if ( cif->flags == FFI_TYPE_STRUCT ) {
++ *rvalue = *(void **) argp;
++ argp += 4;
++ }
++
++ p_argv = avalue;
++
++ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp) {
++ argp = (char *) ALIGN(argp, sizeof(int));
++ }
++
++ z = (*p_arg)->size;
++
++ /* because we're little endian, this is what it turns into. */
++
++ *p_argv = (void*) argp;
++
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
++
++#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
++({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
++unsigned int __fun = (unsigned int)(FUN); \
++unsigned int __ctx = (unsigned int)(CTX); \
++unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
++*(unsigned char*) &__tramp[0] = 0xb8; \
++*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
++*(unsigned char *) &__tramp[5] = 0xe9; \
++*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
++})
++
++
++/* the cif must already be prep'ed */
++ffi_status
++ffi_prep_closure (ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data)
++{
++ if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
++ &ffi_closure_SYSV, \
++ (void*)closure);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++/* ------- Native raw API support -------------------------------- */
++
++#if !FFI_NO_RAW_API
++
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc)
++{
++ int i;
++
++ FFI_ASSERT (cif->abi == FFI_SYSV);
++
++ // we currently don't support certain kinds of arguments for raw
++ // closures. This should be implemented by a separate assembly language
++ // routine, since it would require argument processing, something we
++ // don't do now for performance.
++
++ for (i = cif->nargs-1; i >= 0; i--)
++ {
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
++ }
++
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
++ codeloc);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++static void
++ffi_prep_args_raw(char *stack, extended_cif *ecif)
++{
++ memcpy (stack, ecif->avalue, ecif->cif->bytes);
++}
++
++/* we borrow this routine from libffi (it must be changed, though, to
++ * actually call the function passed in the first argument. as of
++ * libffi-1.20, this is not the case.)
++ */
++
++extern void
++ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void
++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++#endif /* X86_WIN32 */
++
++void
++ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
++{
++ extended_cif ecif;
++ void **avalue = (void **)fake_avalue;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->rtype->type == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++#endif
++#endif // __i386__
+diff --git ./setup.py ./setup.py
+index 46b92fe..2bf6b4b 100644
+--- ./setup.py
++++ ./setup.py
+@@ -98,8 +98,14 @@ class PyBuildExt(build_ext):
+ self.detect_modules()
+
+ # Remove modules that are present on the disabled list
+- self.extensions = [ext for ext in self.extensions
+- if ext.name not in disabled_module_list]
++ extensions = [ext for ext in self.extensions
++ if ext.name not in disabled_module_list]
++ # move ctypes to the end, it depends on other modules
++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
++ if "_ctypes" in ext_map:
++ ctypes = extensions.pop(ext_map["_ctypes"])
++ extensions.append(ctypes)
++ self.extensions = extensions
+
+ # Fix up the autodetected modules, prefixing all the source files
+ # with Modules/ and adding Python's include directory to the path.
+@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext):
+ # *** Uncomment these for TOGL extension only:
+ # -lGL -lGLU -lXext -lXmu \
+
++ def configure_ctypes_darwin(self, ext):
++ # Darwin (OS X) uses preconfigured files, in
++ # the Modules/_ctypes/libffi_osx directory.
++ srcdir = sysconfig.get_config_var('srcdir')
++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
++ '_ctypes', 'libffi_osx'))
++ sources = [os.path.join(ffi_srcdir, p)
++ for p in ['ffi.c',
++ 'x86/darwin64.S',
++ 'x86/x86-darwin.S',
++ 'x86/x86-ffi_darwin.c',
++ 'x86/x86-ffi64.c',
++ 'powerpc/ppc-darwin.S',
++ 'powerpc/ppc-darwin_closure.S',
++ 'powerpc/ppc-ffi_darwin.c',
++ 'powerpc/ppc64-darwin_closure.S',
++ ]]
++
++ # Add .S (preprocessed assembly) to C compiler source extensions.
++ self.compiler.src_extensions.append('.S')
++
++ include_dirs = [os.path.join(ffi_srcdir, 'include'),
++ os.path.join(ffi_srcdir, 'powerpc')]
++ ext.include_dirs.extend(include_dirs)
++ ext.sources.extend(sources)
++ return True
++
+ def configure_ctypes(self, ext):
+ if not self.use_system_libffi:
+- (srcdir,) = sysconfig.get_config_vars('srcdir')
++ if sys.platform == 'darwin':
++ return self.configure_ctypes_darwin(ext)
++
++ srcdir = sysconfig.get_config_var('srcdir')
+ ffi_builddir = os.path.join(self.build_temp, 'libffi')
+ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
+ '_ctypes', 'libffi'))
+@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext):
+ ffi_configfile):
+ from distutils.dir_util import mkpath
+ mkpath(ffi_builddir)
+- config_args = []
++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
++ if (('--host=' in arg) or ('--build=' in arg))]
++ if not self.verbose:
++ config_args.append("-q")
+
+ # Pass empty CFLAGS because we'll just append the resulting
+ # CFLAGS to Python's; -g or -O2 is to be avoided.
+@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext):
+ self.compiler.src_extensions.append('.S')
+
+ include_dirs = [os.path.join(ffi_builddir, 'include'),
+- ffi_builddir, ffi_srcdir]
++ ffi_builddir,
++ os.path.join(ffi_srcdir, 'src')]
+ extra_compile_args = fficonfig['ffi_cflags'].split()
+
+- ext.sources.extend(fficonfig['ffi_sources'])
++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
++ fficonfig['ffi_sources'])
+ ext.include_dirs.extend(include_dirs)
+ ext.extra_compile_args.extend(extra_compile_args)
+ return True
+@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext):
+
+ if sys.platform == 'darwin':
+ sources.append('_ctypes/darwin/dlfcn_simple.c')
++ extra_compile_args.append('-DMACOSX')
+ include_dirs.append('_ctypes/darwin')
+ # XXX Is this still needed?
+ ## extra_link_args.extend(['-read_only_relocs', 'warning'])
+@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext):
+ if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
+ return
+
+- ffi_inc = find_file('ffi.h', [], inc_dirs)
++ if sys.platform == 'darwin':
++ # OS X 10.5 comes with libffi.dylib; the include files are
++ # in /usr/include/ffi
++ inc_dirs.append('/usr/include/ffi')
++
++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
++ if not ffi_inc or ffi_inc[0] == '':
++ ffi_inc = find_file('ffi.h', [], inc_dirs)
+ if ffi_inc is not None:
+ ffi_h = ffi_inc[0] + '/ffi.h'
+ fp = open(ffi_h)
diff --git a/plugins/python-build/share/python-build/patches/2.5.3/Python-2.5.3/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.3/Python-2.5.3/004_osx_libffi.patch
new file mode 100644
index 00000000..cd500771
--- /dev/null
+++ b/plugins/python-build/share/python-build/patches/2.5.3/Python-2.5.3/004_osx_libffi.patch
@@ -0,0 +1,6881 @@
+diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE
+new file mode 100644
+index 0000000..f591795
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README
+new file mode 100644
+index 0000000..1fc2747
+--- /dev/null
++++ ./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: .
++
++
++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
++ #include
++
++ 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
++.
++
++
++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
++ .
++
++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 .
++
++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 . Further enhancements were
++made by Gordon Irlam at Cygnus Solutions .
++
++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 ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc
+new file mode 100644
+index 0000000..405d85f
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c
+new file mode 100644
+index 0000000..bf42093
+--- /dev/null
++++ ./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
++#include
++
++#include
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h
+new file mode 100644
+index 0000000..c104a5c
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/include/ffi.h
+@@ -0,0 +1,355 @@
++/* -----------------------------------------------------------------*-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
++#include
++
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# endif
++#endif
++
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++#error "char size not supported"
++#endif
++
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
++#else
++#error "short size not supported"
++#endif
++
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++#error "int size not supported"
++#endif
++
++#define ffi_type_ulong ffi_type_uint64
++#define ffi_type_slong ffi_type_sint64
++
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != 9223372036854775807
++# error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != 9223372036854775807
++#error "long size not supported"
++#endif
++
++/* The closure code assumes that this works on pointers, i.e. a size_t
++ can hold a pointer. */
++
++typedef struct _ffi_type {
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++/*@null@*/ struct _ffi_type** elements;
++} ffi_type;
++
++/* These are defined in types.c */
++extern ffi_type ffi_type_void;
++extern ffi_type ffi_type_uint8;
++extern ffi_type ffi_type_sint8;
++extern ffi_type ffi_type_uint16;
++extern ffi_type ffi_type_sint16;
++extern ffi_type ffi_type_uint32;
++extern ffi_type ffi_type_sint32;
++extern ffi_type ffi_type_uint64;
++extern ffi_type ffi_type_sint64;
++extern ffi_type ffi_type_float;
++extern ffi_type ffi_type_double;
++extern ffi_type ffi_type_longdouble;
++extern ffi_type ffi_type_pointer;
++
++typedef enum ffi_status {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
++
++typedef unsigned FFI_TYPE;
++
++typedef struct ffi_cif {
++ ffi_abi abi;
++ unsigned nargs;
++/*@dependent@*/ ffi_type** arg_types;
++/*@dependent@*/ ffi_type* rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
++
++/* ---- Definitions for the raw API -------------------------------------- */
++
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == 9223372036854775807
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
++
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
++
++void
++ffi_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_raw_size(
++ ffi_cif* cif);
++
++/* This is analogous to the raw API, except it uses Java parameter
++ packing, even on 64-bit machines. I.e. on 64-bit machines
++ longs and doubles are followed by an empty 64-bit word. */
++void
++ffi_java_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_java_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_java_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_java_raw_size(
++ ffi_cif* cif);
++
++/* ---- Definitions for closures ----------------------------------------- */
++
++#if FFI_CLOSURES
++
++typedef struct ffi_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void* user_data;
++} ffi_closure;
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void* user_data);
++
++void ffi_closure_free(void *);
++void *ffi_closure_alloc (size_t size, void **code);
++
++typedef struct ffi_raw_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++
++#if !FFI_NATIVE_RAW_API
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void* this_closure;
++#endif
++
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void* user_data;
++} ffi_raw_closure;
++
++ffi_status
++ffi_prep_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++ffi_status
++ffi_prep_java_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++#endif // FFI_CLOSURES
++
++/* ---- Public interface definition -------------------------------------- */
++
++ffi_status
++ffi_prep_cif(
++/*@out@*/ /*@partial@*/ ffi_cif* cif,
++ ffi_abi abi,
++ unsigned int nargs,
++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
++/*@dependent@*/ ffi_type** atypes);
++
++void
++ffi_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ void** avalue);
++
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
++
++#endif // #ifndef LIBFFI_ASM
++/* ---- Definitions shared with assembly code ---------------------------- */
++
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++
++#ifdef HAVE_LONG_DOUBLE
++# define FFI_TYPE_LONGDOUBLE 4
++#else
++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_POINTER
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // #ifndef LIBFFI_H
+diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h
+new file mode 100644
+index 0000000..685a358
+--- /dev/null
++++ ./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
++# 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
++#else
++# ifndef HAVE_MEMCPY
++# define memcpy(d, s, n) bcopy((s), (d), (n))
++# endif
++#endif
++
++/*#if defined(FFI_DEBUG)
++#include
++#endif*/
++
++#ifdef FFI_DEBUG
++#include
++
++/*@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 ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h
+new file mode 100644
+index 0000000..2172490
+--- /dev/null
++++ ./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 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 ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h
+new file mode 100644
+index 0000000..faaa30d
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
+new file mode 100644
+index 0000000..2318421
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
+new file mode 100644
+index 0000000..55c2b6c
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+new file mode 100644
+index 0000000..f143dbd
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+@@ -0,0 +1,365 @@
++#if defined(__ppc__) || defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist
++ Copyright (c) 2004 Free Software Foundation, Inc.
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include
++#include
++#include
++
++.text
++ .align 2
++.globl _ffi_prep_args
++
++.text
++ .align 2
++.globl _ffi_call_DARWIN
++
++.text
++ .align 2
++_ffi_call_DARWIN:
++LFB0:
++ mr r12,r8 /* We only need r12 until the call,
++ so it doesn't have to be saved. */
++
++LFB1:
++ /* Save the old stack pointer as AP. */
++ mr r8,r1
++
++LCFI0:
++#if defined(__ppc64__)
++ /* Allocate the stack space we need.
++ r4 (size of input data)
++ 48 bytes (linkage area)
++ 40 bytes (saved registers)
++ 8 bytes (extra FPR)
++ r4 + 96 bytes total
++ */
++
++ addi r4,r4,-96 // Add our overhead.
++ li r0,-32 // Align to 32 bytes.
++ and r4,r4,r0
++#endif
++ stgux r1,r1,r4 // Grow the stack.
++ mflr r9
++
++ /* Save registers we use. */
++#if defined(__ppc64__)
++ std r27,-40(r8)
++#endif
++ stg r28,MODE_CHOICE(-16,-32)(r8)
++ stg r29,MODE_CHOICE(-12,-24)(r8)
++ stg r30,MODE_CHOICE(-8,-16)(r8)
++ stg r31,MODE_CHOICE(-4,-8)(r8)
++ stg r9,SF_RETURN(r8) /* return address */
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ stg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++LCFI1:
++#if defined(__ppc64__)
++ mr r27,r3 // our extended_cif
++#endif
++ /* Save arguments over call. */
++ mr r31,r5 /* flags, */
++ mr r30,r6 /* rvalue, */
++ mr r29,r7 /* function address, */
++ mr r28,r8 /* our AP. */
++
++LCFI2:
++ /* Call ffi_prep_args. */
++ mr r4,r1
++ li r9,0
++ mtctr r12 /* r12 holds address of _ffi_prep_args. */
++ bctrl
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ lg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++ /* Now do the call.
++ Set up cr1 with bits 4-7 of the flags. */
++ mtcrf 0x40,r31
++
++ /* Load all those argument registers.
++ We have set up a nice stack frame, just load it into registers. */
++ lg r3,SF_ARG1(r1)
++ lg r4,SF_ARG2(r1)
++ lg r5,SF_ARG3(r1)
++ lg r6,SF_ARG4(r1)
++ nop
++ lg r7,SF_ARG5(r1)
++ lg r8,SF_ARG6(r1)
++ lg r9,SF_ARG7(r1)
++ lg r10,SF_ARG8(r1)
++
++ /* Load all the FP registers. */
++ bf 6,L2 /* No floats to load. */
++#if defined(__ppc64__)
++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#elif defined(__ppc__)
++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#else
++#error undefined architecture
++#endif
++
++L2:
++ mr r12,r29 // Put the target address in r12 as specified.
++ mtctr r12 // Get the address to call into CTR.
++ nop
++ nop
++ bctrl // Make the call.
++
++ // Deal with the return value.
++#if defined(__ppc64__)
++ mtcrf 0x3,r31 // flags in cr6 and cr7
++ bt 27,L(st_return_value)
++#elif defined(__ppc__)
++ mtcrf 0x1,r31 // flags in cr7
++#else
++#error undefined architecture
++#endif
++
++ bt 30,L(done_return_value)
++ bt 29,L(fp_return_value)
++ stg r3,0(r30)
++#if defined(__ppc__)
++ bf 28,L(done_return_value) // Store the second long if necessary.
++ stg r4,4(r30)
++#endif
++ // Fall through
++
++L(done_return_value):
++ lg r1,0(r1) // Restore stack pointer.
++ // Restore the registers we used.
++ lg r9,SF_RETURN(r1) // return address
++ lg r31,MODE_CHOICE(-4,-8)(r1)
++ mtlr r9
++ lg r30,MODE_CHOICE(-8,-16)(r1)
++ lg r29,MODE_CHOICE(-12,-24)(r1)
++ lg r28,MODE_CHOICE(-16,-32)(r1)
++#if defined(__ppc64__)
++ ld r27,-40(r1)
++#endif
++ blr
++
++#if defined(__ppc64__)
++L(st_return_value):
++ // Grow the stack enough to fit the registers. Leave room for 8 args
++ // to trample the 1st 8 slots in param area.
++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
++
++ // Store GPRs
++ std r3,SF_ARG9(r1)
++ std r4,SF_ARG10(r1)
++ std r5,SF_ARG11(r1)
++ std r6,SF_ARG12(r1)
++ nop
++ std r7,SF_ARG13(r1)
++ std r8,SF_ARG14(r1)
++ std r9,SF_ARG15(r1)
++ std r10,SF_ARG16(r1)
++
++ // Store FPRs
++ nop
++ bf 26,L(call_struct_to_ram_form)
++ stfd f1,SF_ARG17(r1)
++ stfd f2,SF_ARG18(r1)
++ stfd f3,SF_ARG19(r1)
++ stfd f4,SF_ARG20(r1)
++ nop
++ stfd f5,SF_ARG21(r1)
++ stfd f6,SF_ARG22(r1)
++ stfd f7,SF_ARG23(r1)
++ stfd f8,SF_ARG24(r1)
++ nop
++ stfd f9,SF_ARG25(r1)
++ stfd f10,SF_ARG26(r1)
++ stfd f11,SF_ARG27(r1)
++ stfd f12,SF_ARG28(r1)
++ nop
++ stfd f13,SF_ARG29(r1)
++
++L(call_struct_to_ram_form):
++ ld r3,0(r27) // extended_cif->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ addi r4,r1,SF_ARG9 // stored GPRs
++ addi r6,r1,SF_ARG17 // stored FPRs
++ li r5,0 // GPR size ptr (NULL)
++ li r7,0 // FPR size ptr (NULL)
++ li r8,0 // FPR count ptr (NULL)
++ li r10,0 // struct offset (NULL)
++ mr r9,r30 // return area
++ bl Lffi64_struct_to_ram_form$stub
++ lg r1,0(r1) // Restore stack pointer.
++ b L(done_return_value)
++#endif
++
++L(fp_return_value):
++ /* Do we have long double to store? */
++ bf 31,L(fd_return_value)
++ stfd f1,0(r30)
++ stfd f2,8(r30)
++ b L(done_return_value)
++
++L(fd_return_value):
++ /* Do we have double to store? */
++ bf 28,L(float_return_value)
++ stfd f1,0(r30)
++ b L(done_return_value)
++
++L(float_return_value):
++ /* We only have a float to store. */
++ stfs f1,0(r30)
++ b L(done_return_value)
++
++LFE1:
++/* END(_ffi_call_DARWIN) */
++
++/* Provide a null definition of _ffi_call_AIX. */
++.text
++ .align 2
++.globl _ffi_call_AIX
++.text
++ .align 2
++_ffi_call_AIX:
++ blr
++/* END(_ffi_call_AIX) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_call_DARWIN.eh
++_ffi_call_DARWIN.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB0-. ; FDE initial location
++ .set L$set$3,LFE1-LFB0
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x08 ; uleb128 0x08
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$5,LCFI1-LCFI0
++ .long L$set$5
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .byte 0x9f ; DW_CFA_offset, column 0x1f
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x9e ; DW_CFA_offset, column 0x1e
++ .byte 0x2 ; uleb128 0x2
++ .byte 0x9d ; DW_CFA_offset, column 0x1d
++ .byte 0x3 ; uleb128 0x3
++ .byte 0x9c ; DW_CFA_offset, column 0x1c
++ .byte 0x4 ; uleb128 0x4
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$6,LCFI2-LCFI1
++ .long L$set$6
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x1c ; uleb128 0x1c
++ .align LOG2_GPR_BYTES
++LEFDE1:
++
++#if defined(__ppc64__)
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_ram_form$stub:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_ram_form
++
++LO$ffi64_struct_to_ram_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_ram_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
++#endif // __ppc__ || __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+new file mode 100644
+index 0000000..cf4bd50
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+@@ -0,0 +1,85 @@
++/* -----------------------------------------------------------------------
++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define L(x) x
++
++#define SF_ARG9 MODE_CHOICE(56,112)
++#define SF_ARG10 MODE_CHOICE(60,120)
++#define SF_ARG11 MODE_CHOICE(64,128)
++#define SF_ARG12 MODE_CHOICE(68,136)
++#define SF_ARG13 MODE_CHOICE(72,144)
++#define SF_ARG14 MODE_CHOICE(76,152)
++#define SF_ARG15 MODE_CHOICE(80,160)
++#define SF_ARG16 MODE_CHOICE(84,168)
++#define SF_ARG17 MODE_CHOICE(88,176)
++#define SF_ARG18 MODE_CHOICE(92,184)
++#define SF_ARG19 MODE_CHOICE(96,192)
++#define SF_ARG20 MODE_CHOICE(100,200)
++#define SF_ARG21 MODE_CHOICE(104,208)
++#define SF_ARG22 MODE_CHOICE(108,216)
++#define SF_ARG23 MODE_CHOICE(112,224)
++#define SF_ARG24 MODE_CHOICE(116,232)
++#define SF_ARG25 MODE_CHOICE(120,240)
++#define SF_ARG26 MODE_CHOICE(124,248)
++#define SF_ARG27 MODE_CHOICE(128,256)
++#define SF_ARG28 MODE_CHOICE(132,264)
++#define SF_ARG29 MODE_CHOICE(136,272)
++
++#define ASM_NEEDS_REGISTERS 4
++#define NUM_GPR_ARG_REGISTERS 8
++#define NUM_FPR_ARG_REGISTERS 13
++
++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
++#define FFI_TYPE_4_BYTE(x) \
++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
++
++#if !defined(LIBFFI_ASM)
++
++enum {
++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
++ FLAG_RETURNS_FP = 1 << (31 - 29),
++ FLAG_RETURNS_64BITS = 1 << (31 - 28),
++ FLAG_RETURNS_128BITS = 1 << (31 - 31),
++
++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
++
++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
++};
++
++#if defined(__ppc64__)
++void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
++ const char*, unsigned int*, unsigned int*, char*, unsigned int*);
++void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
++ unsigned int*, char*, unsigned int*, char*, unsigned int*);
++bool ffi64_stret_needs_ptr(const ffi_type* inType,
++ unsigned short*, unsigned short*);
++#endif
++
++#endif // !defined(LIBFFI_ASM)
+\ No newline at end of file
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+new file mode 100644
+index 0000000..c3d30c2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+@@ -0,0 +1,308 @@
++#if defined(__ppc__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0 // Save return address
++ stg r0,SF_RETURN(r1)
++
++LCFI0:
++ /* 24/48 bytes (Linkage Area)
++ 32/64 bytes (outgoing parameter area, always reserved)
++ 104 bytes (13*8 from FPR)
++ 16/32 bytes (result)
++ 176/232 total bytes */
++
++ /* skip over caller save area and keep stack aligned to 16/32. */
++ stgu r1,-SF_ROUND(176)(r1)
++
++LCFI1:
++ /* We want to build up an area for the parameters passed
++ in registers. (both floating point and integer) */
++
++ /* 176/256 bytes (callee stack frame aligned to 16/32)
++ 24/48 bytes (caller linkage area)
++ 200/304 (start of caller parameter area aligned to 4/8)
++ */
++
++ /* Save GPRs 3 - 10 (aligned to 4/8)
++ in the parents outgoing area. */
++ stg r3,200(r1)
++ stg r4,204(r1)
++ stg r5,208(r1)
++ stg r6,212(r1)
++ stg r7,216(r1)
++ stg r8,220(r1)
++ stg r9,224(r1)
++ stg r10,228(r1)
++
++ /* Save FPRs 1 - 13. (aligned to 8) */
++ stfd f1,56(r1)
++ stfd f2,64(r1)
++ stfd f3,72(r1)
++ stfd f4,80(r1)
++ stfd f5,88(r1)
++ stfd f6,96(r1)
++ stfd f7,104(r1)
++ stfd f8,112(r1)
++ stfd f9,120(r1)
++ stfd f10,128(r1)
++ stfd f11,136(r1)
++ stfd f12,144(r1)
++ stfd f13,152(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,160 // result storage
++ addi r5,r1,200 // saved GPRs
++ addi r6,r1,56 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ /* Now r3 contains the return type. Use it to look up in a table
++ so we know how to deal with each type. */
++ addi r5,r1,160 // Copy result storage pointer.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ (4 instructions). For cache effectiveness we align to a 16 byte boundary
++ first. */
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++/* case FFI_TYPE_VOID */
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* case FFI_TYPE_INT */
++Lret_type1:
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_FLOAT */
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_DOUBLE */
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_LONGDOUBLE */
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT8 */
++Lret_type5:
++ lbz r3,3(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT8 */
++Lret_type6:
++ lbz r3,3(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT16 */
++Lret_type7:
++ lhz r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT16 */
++Lret_type8:
++ lha r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT32 */
++Lret_type9: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT32 */
++Lret_type10: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT64 */
++Lret_type11:
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_SINT64 */
++Lret_type12: // same as Lret_type11
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_STRUCT */
++Lret_type13:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* End 16-byte aligned cases */
++/* case FFI_TYPE_POINTER */
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ // fall through
++
++/* case done */
++Lfinish:
++ addi r1,r1,SF_ROUND(176) // Restore stack pointer.
++ lg r0,SF_RETURN(r1) // Restore return address.
++ mtlr r0 // Restore link register.
++ blr
++
++/* END(ffi_closure_ASM) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++
++#endif // __ppc__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+new file mode 100644
+index 0000000..8953d5f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+@@ -0,0 +1,1776 @@
++#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
++#include
++
++#include
++#include
++#include
++#include
++#include
++
++#if 0
++#if defined(POWERPC_DARWIN)
++#include // for sys_icache_invalidate()
++#endif
++
++#else
++
++#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)
++ 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
++
++typedef union
++{
++ float f;
++ double d;
++} ffi_dblfl;
++
++/* 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;
++ long 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] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
++ else
++ avalue[i] = (void*)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(temp_ld.lb[0]));
++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
++ 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 ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+new file mode 100644
+index 0000000..7162fa1
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+@@ -0,0 +1,418 @@
++#if defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc64-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0
++ stg r0,SF_RETURN(r1) // save return address
++
++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
++ stg r3,SF_ARG1(r1)
++ stg r4,SF_ARG2(r1)
++ stg r5,SF_ARG3(r1)
++ stg r6,SF_ARG4(r1)
++ stg r7,SF_ARG5(r1)
++ stg r8,SF_ARG6(r1)
++ stg r9,SF_ARG7(r1)
++ stg r10,SF_ARG8(r1)
++
++LCFI0:
++/* 48 bytes (Linkage Area)
++ 64 bytes (outgoing parameter area, always reserved)
++ 112 bytes (14*8 for incoming FPR)
++ ? bytes (result)
++ 112 bytes (14*8 for outgoing FPR)
++ 16 bytes (2 saved registers)
++ 352 + ? total bytes
++*/
++
++ std r31,-8(r1) // Save registers we use.
++ std r30,-16(r1)
++ mr r30,r1 // Save the old SP.
++ mr r31,r11 // Save the ffi_closure around ffi64_data_size.
++
++ // Calculate the space we need.
++ stdu r1,-SF_MINSIZE(r1)
++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ bl Lffi64_data_size$stub
++ ld r1,0(r1)
++
++ addi r3,r3,352 // Add our overhead.
++ neg r3,r3
++ li r0,-32 // Align to 32 bytes.
++ and r3,r3,r0
++ stdux r1,r1,r3 // Grow the stack.
++
++ mr r11,r31 // Copy the ffi_closure back.
++
++LCFI1:
++ // We want to build up an area for the parameters passed
++ // in registers. (both floating point and integer)
++
++/* 320 bytes (callee stack frame aligned to 32)
++ 48 bytes (caller linkage area)
++ 368 (start of caller parameter area aligned to 8)
++*/
++
++ // Save FPRs 1 - 14. (aligned to 8)
++ stfd f1,112(r1)
++ stfd f2,120(r1)
++ stfd f3,128(r1)
++ stfd f4,136(r1)
++ stfd f5,144(r1)
++ stfd f6,152(r1)
++ stfd f7,160(r1)
++ stfd f8,168(r1)
++ stfd f9,176(r1)
++ stfd f10,184(r1)
++ stfd f11,192(r1)
++ stfd f12,200(r1)
++ stfd f13,208(r1)
++ stfd f14,216(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,224 // result storage
++ addi r5,r30,SF_ARG1 // saved GPRs
++ addi r6,r1,112 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ // Look the proper starting point in table
++ // by using return type as an offset.
++ addi r5,r1,224 // Get pointer to results area.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Now multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ // (4 instructions). For cache effectiveness we align to a 16 byte
++ // boundary first.
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++// case FFI_TYPE_VOID
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++// case FFI_TYPE_INT
++Lret_type1:
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_FLOAT
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_DOUBLE
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_LONGDOUBLE
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT8
++Lret_type5:
++ lbz r3,7(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT8
++Lret_type6:
++ lbz r3,7(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT16
++Lret_type7:
++ lhz r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT16
++Lret_type8:
++ lha r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT32
++Lret_type9: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT32
++Lret_type10: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT64
++Lret_type11:
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT64
++Lret_type12: // same as Lret_type11
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_STRUCT
++Lret_type13:
++ b Lret_struct
++ nop
++ nop
++ nop
++
++// ** End 16-byte aligned cases **
++// case FFI_TYPE_POINTER
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ b Lfinish
++
++// copy struct into registers
++Lret_struct:
++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r31) // ffi_cif->rtype*
++ ld r31,24(r31) // ffi_cif->flags
++ mr r4,r5 // copy struct* to 2nd arg
++ addi r7,r1,SF_ARG9 // GPR return area
++ addi r9,r30,-16-(14*8) // FPR return area
++ li r5,0 // struct offset ptr (NULL)
++ li r6,0 // FPR used count ptr (NULL)
++ li r8,0 // GPR return area size ptr (NULL)
++ li r10,0 // FPR return area size ptr (NULL)
++ bl Lffi64_struct_to_reg_form$stub
++
++ // Load GPRs
++ ld r3,SF_ARG9(r1)
++ ld r4,SF_ARG10(r1)
++ ld r5,SF_ARG11(r1)
++ ld r6,SF_ARG12(r1)
++ nop
++ ld r7,SF_ARG13(r1)
++ ld r8,SF_ARG14(r1)
++ ld r9,SF_ARG15(r1)
++ ld r10,SF_ARG16(r1)
++ nop
++
++ // Load FPRs
++ mtcrf 0x2,r31
++ bf 26,Lfinish
++ lfd f1,-16-(14*8)(r30)
++ lfd f2,-16-(13*8)(r30)
++ lfd f3,-16-(12*8)(r30)
++ lfd f4,-16-(11*8)(r30)
++ nop
++ lfd f5,-16-(10*8)(r30)
++ lfd f6,-16-(9*8)(r30)
++ lfd f7,-16-(8*8)(r30)
++ lfd f8,-16-(7*8)(r30)
++ nop
++ lfd f9,-16-(6*8)(r30)
++ lfd f10,-16-(5*8)(r30)
++ lfd f11,-16-(4*8)(r30)
++ lfd f12,-16-(3*8)(r30)
++ nop
++ lfd f13,-16-(2*8)(r30)
++ lfd f14,-16-(1*8)(r30)
++ // Fall through
++
++// case done
++Lfinish:
++ lg r1,0(r1) // Restore stack pointer.
++ ld r31,-8(r1) // Restore registers we used.
++ ld r30,-16(r1)
++ lg r0,SF_RETURN(r1) // Get return address.
++ mtlr r0 // Reset link register.
++ blr
++
++// END(ffi_closure_ASM)
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_reg_form$stub:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_reg_form
++
++LO$ffi64_struct_to_reg_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
++ mtctr r12
++ bctr
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_data_size$stub:
++ .indirect_symbol _ffi64_data_size
++ mflr r0
++ bcl 20,31,LO$ffi64_data_size
++
++LO$ffi64_data_size:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_reg_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ .g_long dyld_stub_binding_helper
++
++L_ffi64_data_size$lazy_ptr:
++ .indirect_symbol _ffi64_data_size
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c
+new file mode 100644
+index 0000000..44806ae
+--- /dev/null
++++ ./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
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+new file mode 100644
+index 0000000..165d469
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+@@ -0,0 +1,417 @@
++/* -----------------------------------------------------------------------
++ 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
++#include
++
++ .file "darwin64.S"
++.text
++
++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
++ void *raddr, void (*fnaddr)());
++
++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
++ for this function. This has been allocated by ffi_call. We also
++ deallocate some of the stack that has been alloca'd. */
++
++ .align 3
++ .globl _ffi_call_unix64
++
++_ffi_call_unix64:
++LUW0:
++ movq (%rsp), %r10 /* Load return address. */
++ movq %rdi, %r12 /* Save a copy of the register area. */
++ leaq (%rdi, %rsi), %rax /* Find local stack base. */
++ movq %rdx, (%rax) /* Save flags. */
++ movq %rcx, 8(%rax) /* Save raddr. */
++ movq %rbp, 16(%rax) /* Save old frame pointer. */
++ movq %r10, 24(%rax) /* Relocate return address. */
++ movq %rax, %rbp /* Finalize local stack frame. */
++LUW1:
++ /* movq %rdi, %r10 // Save a copy of the register area. */
++ movq %r12, %r10
++ movq %r8, %r11 /* Save a copy of the target fn. */
++ movl %r9d, %eax /* Set number of SSE registers. */
++
++ /* Load up all argument registers. */
++ movq (%r10), %rdi
++ movq 8(%r10), %rsi
++ movq 16(%r10), %rdx
++ movq 24(%r10), %rcx
++ movq 32(%r10), %r8
++ movq 40(%r10), %r9
++ testl %eax, %eax
++ jnz Lload_sse
++Lret_from_load_sse:
++
++ /* Deallocate the reg arg area. */
++ leaq 176(%r10), %rsp
++
++ /* Call the user function. */
++ call *%r11
++
++ /* Deallocate stack arg area; local stack frame in redzone. */
++ leaq 24(%rbp), %rsp
++
++ movq 0(%rbp), %rcx /* Reload flags. */
++ movq 8(%rbp), %rdi /* Reload raddr. */
++ movq 16(%rbp), %rbp /* Reload old frame pointer. */
++LUW2:
++
++ /* The first byte of the flags contains the FFI_TYPE. */
++ movzbl %cl, %r10d
++ leaq Lstore_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lstore_table:
++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lst_void:
++ ret
++ .align 3
++Lst_uint8:
++ movzbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_sint8:
++ movsbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint16:
++ movzwq %ax, %rax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint16:
++ movswq %ax, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint32:
++ movl %eax, %eax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint32:
++ cltq
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_int64:
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_float:
++ movss %xmm0, (%rdi)
++ ret
++ .align 3
++Lst_double:
++ movsd %xmm0, (%rdi)
++ ret
++Lst_ldouble:
++ fstpt (%rdi)
++ ret
++ .align 3
++Lst_struct:
++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */
++
++ /* We have to locate the values now, and since we don't want to
++ write too much data into the user's return value, we spill the
++ value to a 16 byte scratch area first. Bits 8, 9, and 10
++ control where the values are located. Only one of the three
++ bits will be set; see ffi_prep_cif_machdep for the pattern. */
++ movd %xmm0, %r10
++ movd %xmm1, %r11
++ testl $0x100, %ecx
++ cmovnz %rax, %rdx
++ cmovnz %r10, %rax
++ testl $0x200, %ecx
++ cmovnz %r10, %rdx
++ testl $0x400, %ecx
++ cmovnz %r10, %rax
++ cmovnz %r11, %rdx
++ movq %rax, (%rsi)
++ movq %rdx, 8(%rsi)
++
++ /* Bits 12-31 contain the true size of the structure. Copy from
++ the scratch area to the true destination. */
++ shrl $12, %ecx
++ rep movsb
++ ret
++
++ /* Many times we can avoid loading any SSE registers at all.
++ It's not worth an indirect jump to load the exact set of
++ SSE registers needed; zero or all is a good compromise. */
++ .align 3
++LUW3:
++Lload_sse:
++ movdqa 48(%r10), %xmm0
++ movdqa 64(%r10), %xmm1
++ movdqa 80(%r10), %xmm2
++ movdqa 96(%r10), %xmm3
++ movdqa 112(%r10), %xmm4
++ movdqa 128(%r10), %xmm5
++ movdqa 144(%r10), %xmm6
++ movdqa 160(%r10), %xmm7
++ jmp Lret_from_load_sse
++
++LUW4:
++ .align 3
++ .globl _ffi_closure_unix64
++
++_ffi_closure_unix64:
++LUW5:
++ /* The carry flag is set by the trampoline iff SSE registers
++ are used. Don't clobber it before the branch instruction. */
++ leaq -200(%rsp), %rsp
++LUW6:
++ movq %rdi, (%rsp)
++ movq %rsi, 8(%rsp)
++ movq %rdx, 16(%rsp)
++ movq %rcx, 24(%rsp)
++ movq %r8, 32(%rsp)
++ movq %r9, 40(%rsp)
++ jc Lsave_sse
++Lret_from_save_sse:
++
++ movq %r10, %rdi
++ leaq 176(%rsp), %rsi
++ movq %rsp, %rdx
++ leaq 208(%rsp), %rcx
++ call _ffi_closure_unix64_inner
++
++ /* Deallocate stack frame early; return value is now in redzone. */
++ addq $200, %rsp
++LUW7:
++
++ /* The first byte of the return value contains the FFI_TYPE. */
++ movzbl %al, %r10d
++ leaq Lload_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lload_table:
++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */
++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */
++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lld_void:
++ ret
++ .align 3
++Lld_int8:
++ movzbl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int16:
++ movzwl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int32:
++ movl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int64:
++ movq -24(%rsp), %rax
++ ret
++ .align 3
++Lld_float:
++ movss -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_double:
++ movsd -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_ldouble:
++ fldt -24(%rsp)
++ ret
++ .align 3
++Lld_struct:
++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
++ both rdx and xmm1 with the second word. For the remaining,
++ bit 8 set means xmm0 gets the second word, and bit 9 means
++ that rax gets the second word. */
++ movq -24(%rsp), %rcx
++ movq -16(%rsp), %rdx
++ movq -16(%rsp), %xmm1
++ testl $0x100, %eax
++ cmovnz %rdx, %rcx
++ movd %rcx, %xmm0
++ testl $0x200, %eax
++ movq -24(%rsp), %rax
++ cmovnz %rdx, %rax
++ ret
++
++ /* See the comment above Lload_sse; the same logic applies here. */
++ .align 3
++LUW8:
++Lsave_sse:
++ movdqa %xmm0, 48(%rsp)
++ movdqa %xmm1, 64(%rsp)
++ movdqa %xmm2, 80(%rsp)
++ movdqa %xmm3, 96(%rsp)
++ movdqa %xmm4, 112(%rsp)
++ movdqa %xmm5, 128(%rsp)
++ movdqa %xmm6, 144(%rsp)
++ movdqa %xmm7, 160(%rsp)
++ jmp Lret_from_save_sse
++
++LUW9:
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */
++ .long L$set$0
++LSCIE1:
++ .long 0x0 /* CIE Identifier Tag */
++ .byte 0x1 /* CIE Version */
++ .ascii "zR\0" /* CIE Augmentation */
++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
++ .byte 0x10 /* CIE RA Column */
++ .byte 0x1 /* uleb128 0x1; Augmentation size */
++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */
++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
++ .byte 0x7 /* uleb128 0x7 */
++ .byte 0x8 /* uleb128 0x8 */
++ .byte 0x90 /* DW_CFA_offset, column 0x10 */
++ .byte 0x1
++ .align 3
++LECIE1:
++ .globl _ffi_call_unix64.eh
++_ffi_call_unix64.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1 /* FDE CIE offset */
++ .quad LUW0-. /* FDE initial location */
++ .set L$set$2,LUW4-LUW0 /* FDE address range */
++ .quad L$set$2
++ .byte 0x0 /* Augmentation size */
++ .byte 0x4 /* DW_CFA_advance_loc4 */
++ .set L$set$3,LUW1-LUW0
++ .long L$set$3
++
++ /* New stack frame based off rbp. This is 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 ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+new file mode 100644
+index 0000000..925a841
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+@@ -0,0 +1,422 @@
++#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
++#include
++
++#ifdef PyObjC_STRICT_DEBUGGING
++ /* XXX: Debugging of stack alignment, to be removed */
++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
++#else
++#define ASSERT_STACK_ALIGNED
++#endif
++
++.text
++
++.globl _ffi_prep_args
++
++ .align 4
++.globl _ffi_call_SYSV
++
++_ffi_call_SYSV:
++LFB1:
++ pushl %ebp
++LCFI0:
++ movl %esp,%ebp
++LCFI1:
++ subl $8,%esp
++ /* Make room for all of the new args. */
++ movl 16(%ebp),%ecx
++ subl %ecx,%esp
++
++ movl %esp,%eax
++
++ /* Place all of the ffi_prep_args in position */
++ subl $8,%esp
++ pushl 12(%ebp)
++ pushl %eax
++ call *8(%ebp)
++
++ /* Return stack to previous state and call the function */
++ addl $16,%esp
++
++ call *28(%ebp)
++
++ /* Remove the space we pushed for the args */
++ movl 16(%ebp),%ecx
++ addl %ecx,%esp
++
++ /* Load %ecx with the return type code */
++ movl 20(%ebp),%ecx
++
++ /* If the return value pointer is NULL, assume no return value. */
++ cmpl $0,24(%ebp)
++ jne Lretint
++
++ /* Even if there is no space for the return value, we are
++ obliged to handle floating-point values. */
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lnoretval
++ fstp %st(0)
++
++ jmp Lepilogue
++
++Lretint:
++ cmpl $FFI_TYPE_INT,%ecx
++ jne Lretfloat
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ jmp Lepilogue
++
++Lretfloat:
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lretdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstps (%ecx)
++ jmp Lepilogue
++
++Lretdouble:
++ cmpl $FFI_TYPE_DOUBLE,%ecx
++ jne Lretlongdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpl (%ecx)
++ jmp Lepilogue
++
++Lretlongdouble:
++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx
++ jne Lretint64
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpt (%ecx)
++ jmp Lepilogue
++
++Lretint64:
++ cmpl $FFI_TYPE_SINT64,%ecx
++ jne Lretstruct1b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ movl %edx,4(%ecx)
++ jmp Lepilogue
++
++Lretstruct1b:
++ cmpl $FFI_TYPE_SINT8,%ecx
++ jne Lretstruct2b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movb %al,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct2b:
++ cmpl $FFI_TYPE_SINT16,%ecx
++ jne Lretstruct
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movw %ax,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct:
++ cmpl $FFI_TYPE_STRUCT,%ecx
++ jne Lnoretval
++ /* Nothing to do! */
++ addl $4,%esp
++ popl %ebp
++ ret
++
++Lnoretval:
++Lepilogue:
++ addl $8,%esp
++ movl %ebp,%esp
++ popl %ebp
++ ret
++LFE1:
++.ffi_call_SYSV_end:
++
++ .align 4
++FFI_HIDDEN (ffi_closure_SYSV)
++.globl _ffi_closure_SYSV
++
++_ffi_closure_SYSV:
++LFB2:
++ pushl %ebp
++LCFI2:
++ movl %esp, %ebp
++LCFI3:
++ subl $56, %esp
++ leal -40(%ebp), %edx
++ movl %edx, -12(%ebp) /* resp */
++ leal 8(%ebp), %edx
++ movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
++ leal -12(%ebp), %edx
++ movl %edx, (%esp) /* &resp */
++ movl %ebx, 8(%esp)
++LCFI7:
++ call L_ffi_closure_SYSV_inner$stub
++ movl 8(%esp), %ebx
++ movl -12(%ebp), %ecx
++ cmpl $FFI_TYPE_INT, %eax
++ je Lcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lcls_retllong
++ cmpl $FFI_TYPE_UINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_SINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_UINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_SINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_STRUCT, %eax
++ je Lcls_retstruct
++Lcls_epilogue:
++ movl %ebp, %esp
++ popl %ebp
++ ret
++Lcls_retint:
++ movl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retfloat:
++ flds (%ecx)
++ jmp Lcls_epilogue
++Lcls_retdouble:
++ fldl (%ecx)
++ jmp Lcls_epilogue
++Lcls_retldouble:
++ fldt (%ecx)
++ jmp Lcls_epilogue
++Lcls_retllong:
++ movl (%ecx), %eax
++ movl 4(%ecx), %edx
++ jmp Lcls_epilogue
++Lcls_retstruct1:
++ movsbl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct2:
++ movswl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct:
++ lea -8(%ebp),%esp
++ movl %ebp, %esp
++ popl %ebp
++ ret $4
++LFE2:
++
++#if !FFI_NO_RAW_API
++
++#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
++#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
++#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
++#define CIF_FLAGS_OFFSET 20
++
++ .align 4
++FFI_HIDDEN (ffi_closure_raw_SYSV)
++.globl _ffi_closure_raw_SYSV
++
++_ffi_closure_raw_SYSV:
++LFB3:
++ pushl %ebp
++LCFI4:
++ movl %esp, %ebp
++LCFI5:
++ pushl %esi
++LCFI6:
++ subl $36, %esp
++ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
++ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
++ movl %edx, 12(%esp) /* user_data */
++ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
++ movl %edx, 8(%esp) /* raw_args */
++ leal -24(%ebp), %edx
++ movl %edx, 4(%esp) /* &res */
++ movl %esi, (%esp) /* cif */
++ call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
++ movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
++ cmpl $FFI_TYPE_INT, %eax
++ je Lrcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lrcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lrcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lrcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lrcls_retllong
++Lrcls_epilogue:
++ addl $36, %esp
++ popl %esi
++ popl %ebp
++ ret
++Lrcls_retint:
++ movl -24(%ebp), %eax
++ jmp Lrcls_epilogue
++Lrcls_retfloat:
++ flds -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retdouble:
++ fldl -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retldouble:
++ fldt -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retllong:
++ movl -24(%ebp), %eax
++ movl -20(%ebp), %edx
++ jmp Lrcls_epilogue
++LFE3:
++#endif
++
++.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
++L_ffi_closure_SYSV_inner$stub:
++ .indirect_symbol _ffi_closure_SYSV_inner
++ hlt ; hlt ; hlt ; hlt ; hlt
++
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0
++LSCIE1:
++ .long 0x0
++ .byte 0x1
++ .ascii "zR\0"
++ .byte 0x1
++ .byte 0x7c
++ .byte 0x8
++ .byte 0x1
++ .byte 0x10
++ .byte 0xc
++ .byte 0x5
++ .byte 0x4
++ .byte 0x88
++ .byte 0x1
++ .align 2
++LECIE1:
++.globl _ffi_call_SYSV.eh
++_ffi_call_SYSV.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1
++ .long LFB1-.
++ .set L$set$2,LFE1-LFB1
++ .long L$set$2
++ .byte 0x0
++ .byte 0x4
++ .set L$set$3,LCFI0-LFB1
++ .long L$set$3
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$4,LCFI1-LCFI0
++ .long L$set$4
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE1:
++.globl _ffi_closure_SYSV.eh
++_ffi_closure_SYSV.eh:
++LSFDE2:
++ .set L$set$5,LEFDE2-LASFDE2
++ .long L$set$5
++LASFDE2:
++ .long LASFDE2-EH_frame1
++ .long LFB2-.
++ .set L$set$6,LFE2-LFB2
++ .long L$set$6
++ .byte 0x0
++ .byte 0x4
++ .set L$set$7,LCFI2-LFB2
++ .long L$set$7
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$8,LCFI3-LCFI2
++ .long L$set$8
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE2:
++
++#if !FFI_NO_RAW_API
++
++.globl _ffi_closure_raw_SYSV.eh
++_ffi_closure_raw_SYSV.eh:
++LSFDE3:
++ .set L$set$10,LEFDE3-LASFDE3
++ .long L$set$10
++LASFDE3:
++ .long LASFDE3-EH_frame1
++ .long LFB3-.
++ .set L$set$11,LFE3-LFB3
++ .long L$set$11
++ .byte 0x0
++ .byte 0x4
++ .set L$set$12,LCFI4-LFB3
++ .long L$set$12
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$13,LCFI5-LCFI4
++ .long L$set$13
++ .byte 0xd
++ .byte 0x4
++ .byte 0x4
++ .set L$set$14,LCFI6-LCFI5
++ .long L$set$14
++ .byte 0x85
++ .byte 0x3
++ .align 2
++LEFDE3:
++
++#endif
++
++#endif /* ifndef __x86_64__ */
++
++#endif /* defined __i386__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+new file mode 100644
+index 0000000..06feaf2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+@@ -0,0 +1,734 @@
++#ifdef __x86_64__
++
++/* -----------------------------------------------------------------------
++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen
++
++ 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
++#include
++
++#include
++#include
++
++#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 0
++ if (byte_offset + type->size <= 4)
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ else
++ classes[0] = X86_64_INTEGER_CLASS;
++
++ return 1;
++#else
++ {
++ int size = byte_offset + type->size;
++
++ if (size <= 4)
++ {
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ return 1;
++ }
++ else if (size <= 8)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ return 1;
++ }
++ else if (size <= 12)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else if (size <= 16)
++ {
++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else
++ FFI_ASSERT (0);
++ }
++#endif
++
++ case FFI_TYPE_FLOAT:
++ if (byte_offset == 0)
++ classes[0] = X86_64_SSESF_CLASS;
++ else
++ classes[0] = X86_64_SSE_CLASS;
++
++ return 1;
++
++ case FFI_TYPE_DOUBLE:
++ classes[0] = X86_64_SSEDF_CLASS;
++ return 1;
++
++ case FFI_TYPE_LONGDOUBLE:
++ classes[0] = X86_64_X87_CLASS;
++ classes[1] = X86_64_X87UP_CLASS;
++ return 2;
++
++ case FFI_TYPE_STRUCT:
++ {
++ ffi_type** ptr;
++ int i;
++ enum x86_64_reg_class subclasses[MAX_CLASSES];
++ const int UNITS_PER_WORD = 8;
++ int words =
++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++
++ /* If the struct is larger than 16 bytes, pass it on the stack. */
++ if (type->size > 16)
++ return 0;
++
++ for (i = 0; i < words; i++)
++ classes[i] = X86_64_NO_CLASS;
++
++ /* Merge the fields of structure. */
++ for (ptr = type->elements; *ptr != NULL; ptr++)
++ {
++ 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;
++ }
++
++ if (words > 2)
++ {
++ /* When size > 16 bytes, if the first one isn't
++ X86_64_SSE_CLASS or any other ones aren't
++ X86_64_SSEUP_CLASS, everything should be passed in
++ memory. */
++ if (classes[0] != X86_64_SSE_CLASS)
++ return 0;
++
++ for (i = 1; i < words; i++)
++ if (classes[i] != X86_64_SSEUP_CLASS)
++ return 0;
++ }
++
++
++ /* Final merger cleanup. */
++ for (i = 0; i < words; i++)
++ {
++ /* If one class is MEMORY, everything should be passed in
++ memory. */
++ if (classes[i] == X86_64_MEMORY_CLASS)
++ return 0;
++
++ /* The X86_64_SSEUP_CLASS should be always preceded by
++ X86_64_SSE_CLASS. */
++ if (classes[i] == X86_64_SSEUP_CLASS
++ && classes[i - 1] != X86_64_SSE_CLASS
++ && classes[i - 1] != X86_64_SSEUP_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++
++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
++ if (classes[i] == X86_64_X87UP_CLASS
++ && classes[i - 1] != X86_64_X87_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++ }
++
++ return words;
++ }
++
++ default:
++ FFI_ASSERT(0);
++ }
++
++ return 0; /* Never reached. */
++}
++
++/* Examine the argument and return set number of register required in each
++ class. Return zero if parameter should be passed in memory, otherwise
++ the number of registers. */
++static int
++examine_argument(
++ ffi_type* type,
++ enum x86_64_reg_class classes[MAX_CLASSES],
++ _Bool in_return,
++ int* pngpr,
++ int* pnsse)
++{
++ int n = classify_argument(type, classes, 0);
++ int ngpr = 0;
++ int nsse = 0;
++ int i;
++
++ if (n == 0)
++ return 0;
++
++ for (i = 0; i < n; ++i)
++ {
++ switch (classes[i])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ ngpr++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSESF_CLASS:
++ case X86_64_SSEDF_CLASS:
++ nsse++;
++ break;
++
++ case X86_64_NO_CLASS:
++ case X86_64_SSEUP_CLASS:
++ break;
++
++ case X86_64_X87_CLASS:
++ case X86_64_X87UP_CLASS:
++ case X86_64_COMPLEX_X87_CLASS:
++ return in_return != 0;
++
++ default:
++ abort();
++ }
++ }
++
++ *pngpr = ngpr;
++ *pnsse = nsse;
++
++ return n;
++}
++
++/* Perform machine dependent cif processing. */
++ffi_status
++ffi_prep_cif_machdep(
++ ffi_cif* cif)
++{
++ int gprcount = 0;
++ int ssecount = 0;
++ int flags = cif->rtype->type;
++ int i, avn, n, ngpr, nsse;
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ size_t bytes;
++
++ if (flags != FFI_TYPE_VOID)
++ {
++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value is passed in memory. A pointer to that
++ memory is the first argument. Allocate a register for it. */
++ gprcount++;
++
++ /* We don't have to do anything in asm for the return. */
++ flags = FFI_TYPE_VOID;
++ }
++ else if (flags == FFI_TYPE_STRUCT)
++ {
++ /* Mark which registers the result appears in. */
++ _Bool sse0 = SSE_CLASS_P(classes[0]);
++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
++
++ if (sse0 && !sse1)
++ flags |= 1 << 8;
++ else if (!sse0 && sse1)
++ flags |= 1 << 9;
++ else if (sse0 && sse1)
++ flags |= 1 << 10;
++
++ /* Mark the true size of the structure. */
++ flags |= cif->rtype->size << 12;
++ }
++ }
++
++ /* Go over all arguments and determine the way they should be passed.
++ If it's in a register and there is space for it, let that be so. If
++ not, add it's size to the stack byte count. */
++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
++ {
++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = cif->arg_types[i]->alignment;
++
++ if (align < 8)
++ align = 8;
++
++ bytes = ALIGN(bytes, align);
++ bytes += cif->arg_types[i]->size;
++ }
++ else
++ {
++ gprcount += ngpr;
++ ssecount += nsse;
++ }
++ }
++
++ if (ssecount)
++ flags |= 1 << 11;
++
++ cif->flags = flags;
++ cif->bytes = bytes;
++ cif->bytes = ALIGN(bytes,8);
++
++ return FFI_OK;
++}
++
++void
++ffi_call(
++ ffi_cif* cif,
++ void (*fn)(),
++ void* rvalue,
++ void** avalue)
++{
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ char* stack;
++ char* argp;
++ ffi_type** arg_types;
++ int gprcount, ssecount, ngpr, nsse, i, avn;
++ _Bool ret_in_memory;
++ RegisterArgs* reg_args;
++
++ /* Can't call 32-bit mode from 64-bit mode. */
++ FFI_ASSERT(cif->abi == FFI_UNIX64);
++
++ /* If the return value is a struct and we don't have a return value
++ address then we need to make one. Note the setting of flags to
++ VOID above in ffi_prep_cif_machdep. */
++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
++ && (cif->flags & 0xff) == FFI_TYPE_VOID);
++
++ if (rvalue == NULL && ret_in_memory)
++ rvalue = alloca (cif->rtype->size);
++
++ /* Allocate the space for the arguments, plus 4 words of temp space. */
++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
++ reg_args = (RegisterArgs*)stack;
++ argp = stack + sizeof(RegisterArgs);
++
++ gprcount = ssecount = 0;
++
++ /* If the return value is passed in memory, add the pointer as the
++ first integer argument. */
++ if (ret_in_memory)
++ reg_args->gpr[gprcount++] = (long) rvalue;
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ size_t size = arg_types[i]->size;
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ memcpy (argp, avalue[i], size);
++ argp += size;
++ }
++ else
++ { /* The argument is passed entirely in registers. */
++ char *a = (char *) avalue[i];
++ int j;
++
++ for (j = 0; j < n; j++, a += 8, size -= 8)
++ {
++ switch (classes[j])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ reg_args->gpr[gprcount] = 0;
++ switch (arg_types[i]->type) {
++ case FFI_TYPE_SINT8:
++ {
++ int8_t shortval = *(int8_t*)a;
++ int64_t actval = (int64_t)shortval;
++ reg_args->gpr[gprcount] = actval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ break;
++ }
++
++ case FFI_TYPE_SINT16:
++ {
++ int16_t shortval = *(int16_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_SINT32:
++ {
++ int32_t shortval = *(int32_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT8:
++ {
++ u_int8_t shortval = *(u_int8_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ reg_args->gpr[gprcount] = actval;
++ break;
++ }
++
++ case FFI_TYPE_UINT16:
++ {
++ u_int16_t shortval = *(u_int16_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT32:
++ {
++ u_int32_t shortval = *(u_int32_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ default:
++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
++ reg_args->gpr[gprcount] = *(int64_t*)a;
++ }
++ gprcount++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSEDF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT64 *) a;
++ break;
++
++ case X86_64_SSESF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT32 *) a;
++ break;
++
++ default:
++ abort();
++ }
++ }
++ }
++ }
++
++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
++ cif->flags, rvalue, fn, ssecount);
++}
++
++extern void ffi_closure_unix64(void);
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*, void*, void**, void*),
++ void* user_data)
++{
++ if (cif->abi != FFI_UNIX64)
++ return FFI_BAD_ABI;
++
++ volatile unsigned short* tramp =
++ (volatile unsigned short*)&closure->tramp[0];
++
++ tramp[0] = 0xbb49; /* mov , %r11 */
++ *(void* volatile*)&tramp[1] = ffi_closure_unix64;
++ tramp[5] = 0xba49; /* mov , %r10 */
++ *(void* volatile*)&tramp[6] = closure;
++
++ /* Set the carry bit if the function uses any sse registers.
++ This is clc or stc, together with the first byte of the jmp. */
++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
++ tramp[11] = 0xe3ff; /* jmp *%r11 */
++
++ closure->cif = cif;
++ closure->fun = fun;
++ closure->user_data = user_data;
++
++ return FFI_OK;
++}
++
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wmissing-prototypes"
++int
++ffi_closure_unix64_inner(
++ ffi_closure* closure,
++ void* rvalue,
++ RegisterArgs* reg_args,
++ char* argp)
++#pragma clang diagnostic pop
++{
++ ffi_cif* cif = closure->cif;
++ void** avalue = alloca(cif->nargs * sizeof(void *));
++ ffi_type** arg_types;
++ long i, avn;
++ int gprcount = 0;
++ int ssecount = 0;
++ int ngpr, nsse;
++ int ret;
++
++ ret = cif->rtype->type;
++
++ if (ret != FFI_TYPE_VOID)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value goes in memory. Arrange for the closure
++ return value to go directly back to the original caller. */
++ rvalue = (void *) reg_args->gpr[gprcount++];
++
++ /* We don't have to do anything in asm for the return. */
++ ret = FFI_TYPE_VOID;
++ }
++ else if (ret == FFI_TYPE_STRUCT && n == 2)
++ {
++ /* Mark which register the second word of the structure goes in. */
++ _Bool sse0 = SSE_CLASS_P (classes[0]);
++ _Bool sse1 = SSE_CLASS_P (classes[1]);
++
++ if (!sse0 && sse1)
++ ret |= 1 << 8;
++ else if (sse0 && !sse1)
++ ret |= 1 << 9;
++ }
++ }
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ avalue[i] = argp;
++ argp += arg_types[i]->size;
++ }
++
++#if !defined(X86_DARWIN)
++ /* If the argument is in a single register, or two consecutive
++ registers, then we can use that address directly. */
++ else if (n == 1 || (n == 2 &&
++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
++ {
++ // The argument is in a single register.
++ if (SSE_CLASS_P (classes[0]))
++ {
++ avalue[i] = ®_args->sse[ssecount];
++ ssecount += n;
++ }
++ else
++ {
++ avalue[i] = ®_args->gpr[gprcount];
++ gprcount += n;
++ }
++ }
++#endif
++
++ /* Otherwise, allocate space to make them consecutive. */
++ else
++ {
++ char *a = alloca (16);
++ int j;
++
++ avalue[i] = a;
++
++ for (j = 0; j < n; j++, a += 8)
++ {
++ if (SSE_CLASS_P (classes[j]))
++ memcpy (a, ®_args->sse[ssecount++], 8);
++ else
++ memcpy (a, ®_args->gpr[gprcount++], 8);
++ }
++ }
++ }
++
++ /* Invoke the closure. */
++ closure->fun (cif, rvalue, avalue, closure->user_data);
++
++ /* Tell assembly how to perform return type promotions. */
++ return ret;
++}
++
++#endif /* __x86_64__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+new file mode 100644
+index 0000000..706ea0f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+@@ -0,0 +1,438 @@
++#ifdef __i386__
++/* -----------------------------------------------------------------------
++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
++ Copyright (c) 2002 Ranjit Mathew
++ Copyright (c) 2002 Bo Thorsen
++ Copyright (c) 2002 Roger Sayle
++
++ x86 Foreign Function Interface
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#include
++#include
++
++#include
++
++/* ffi_prep_args is called by the assembly routine once stack space
++ has been allocated for the function's arguments */
++
++void ffi_prep_args(char *stack, extended_cif *ecif);
++
++void ffi_prep_args(char *stack, extended_cif *ecif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if (ecif->cif->flags == FFI_TYPE_STRUCT)
++ {
++ *(void **) argp = ecif->rvalue;
++ argp += 4;
++ }
++
++ p_argv = ecif->avalue;
++
++ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
++ i != 0;
++ i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp)
++ argp = (char *) ALIGN(argp, sizeof(int));
++
++ z = (*p_arg)->size;
++ if (z < sizeof(int))
++ {
++ z = sizeof(int);
++ switch ((*p_arg)->type)
++ {
++ case FFI_TYPE_SINT8:
++ *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT8:
++ *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT16:
++ *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT16:
++ *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT32:
++ *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT32:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_STRUCT:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ default:
++ FFI_ASSERT(0);
++ }
++ }
++ else
++ {
++ memcpy(argp, *p_argv, z);
++ }
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* Perform machine dependent cif processing */
++ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++{
++ /* Set the return type flag */
++ switch (cif->rtype->type)
++ {
++ case FFI_TYPE_VOID:
++#ifdef X86
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_SINT16:
++#endif
++
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ cif->flags = (unsigned) cif->rtype->type;
++ break;
++
++ case FFI_TYPE_UINT64:
++ cif->flags = FFI_TYPE_SINT64;
++ break;
++
++#ifndef X86
++ case FFI_TYPE_STRUCT:
++ if (cif->rtype->size == 1)
++ {
++ cif->flags = FFI_TYPE_SINT8; /* same as char size */
++ }
++ else if (cif->rtype->size == 2)
++ {
++ cif->flags = FFI_TYPE_SINT16; /* same as short size */
++ }
++ else if (cif->rtype->size == 4)
++ {
++ cif->flags = FFI_TYPE_INT; /* same as int type */
++ }
++ else if (cif->rtype->size == 8)
++ {
++ cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
++ }
++ else
++ {
++ cif->flags = FFI_TYPE_STRUCT;
++ }
++ break;
++#endif
++
++ default:
++ cif->flags = FFI_TYPE_INT;
++ break;
++ }
++
++#ifdef X86_DARWIN
++ cif->bytes = (cif->bytes + 15) & ~0xF;
++#endif
++
++ return FFI_OK;
++}
++
++extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#endif /* X86_WIN32 */
++
++void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
++{
++ extended_cif ecif;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->flags == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
++ fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++
++/** private members **/
++
++static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
++ void** args, ffi_cif* cif);
++void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
++__attribute__ ((regparm(1)));
++unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
++__attribute__ ((regparm(1)));
++void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
++__attribute__ ((regparm(1)));
++
++/* This function is jumped to by the trampoline */
++
++unsigned int FFI_HIDDEN
++ffi_closure_SYSV_inner (closure, respp, args)
++ffi_closure *closure;
++void **respp;
++void *args;
++{
++ // our various things...
++ ffi_cif *cif;
++ void **arg_area;
++
++ cif = closure->cif;
++ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
++
++ /* this call will initialize ARG_AREA, such that each
++ * element in that array points to the corresponding
++ * value on the stack; and if the function returns
++ * a structure, it will re-set RESP to point to the
++ * structure return address. */
++
++ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
++
++ (closure->fun) (cif, *respp, arg_area, closure->user_data);
++
++ return cif->flags;
++}
++
++static void
++ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
++ ffi_cif *cif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if ( cif->flags == FFI_TYPE_STRUCT ) {
++ *rvalue = *(void **) argp;
++ argp += 4;
++ }
++
++ p_argv = avalue;
++
++ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp) {
++ argp = (char *) ALIGN(argp, sizeof(int));
++ }
++
++ z = (*p_arg)->size;
++
++ /* because we're little endian, this is what it turns into. */
++
++ *p_argv = (void*) argp;
++
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
++
++#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
++({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
++unsigned int __fun = (unsigned int)(FUN); \
++unsigned int __ctx = (unsigned int)(CTX); \
++unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
++*(unsigned char*) &__tramp[0] = 0xb8; \
++*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
++*(unsigned char *) &__tramp[5] = 0xe9; \
++*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
++})
++
++
++/* the cif must already be prep'ed */
++ffi_status
++ffi_prep_closure (ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data)
++{
++ if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
++ &ffi_closure_SYSV, \
++ (void*)closure);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++/* ------- Native raw API support -------------------------------- */
++
++#if !FFI_NO_RAW_API
++
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc)
++{
++ int i;
++
++ FFI_ASSERT (cif->abi == FFI_SYSV);
++
++ // we currently don't support certain kinds of arguments for raw
++ // closures. This should be implemented by a separate assembly language
++ // routine, since it would require argument processing, something we
++ // don't do now for performance.
++
++ for (i = cif->nargs-1; i >= 0; i--)
++ {
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
++ }
++
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
++ codeloc);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++static void
++ffi_prep_args_raw(char *stack, extended_cif *ecif)
++{
++ memcpy (stack, ecif->avalue, ecif->cif->bytes);
++}
++
++/* we borrow this routine from libffi (it must be changed, though, to
++ * actually call the function passed in the first argument. as of
++ * libffi-1.20, this is not the case.)
++ */
++
++extern void
++ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void
++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++#endif /* X86_WIN32 */
++
++void
++ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
++{
++ extended_cif ecif;
++ void **avalue = (void **)fake_avalue;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->rtype->type == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++#endif
++#endif // __i386__
+diff --git ./setup.py ./setup.py
+index 46b92fe..2bf6b4b 100644
+--- ./setup.py
++++ ./setup.py
+@@ -98,8 +98,14 @@ class PyBuildExt(build_ext):
+ self.detect_modules()
+
+ # Remove modules that are present on the disabled list
+- self.extensions = [ext for ext in self.extensions
+- if ext.name not in disabled_module_list]
++ extensions = [ext for ext in self.extensions
++ if ext.name not in disabled_module_list]
++ # move ctypes to the end, it depends on other modules
++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
++ if "_ctypes" in ext_map:
++ ctypes = extensions.pop(ext_map["_ctypes"])
++ extensions.append(ctypes)
++ self.extensions = extensions
+
+ # Fix up the autodetected modules, prefixing all the source files
+ # with Modules/ and adding Python's include directory to the path.
+@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext):
+ # *** Uncomment these for TOGL extension only:
+ # -lGL -lGLU -lXext -lXmu \
+
++ def configure_ctypes_darwin(self, ext):
++ # Darwin (OS X) uses preconfigured files, in
++ # the Modules/_ctypes/libffi_osx directory.
++ srcdir = sysconfig.get_config_var('srcdir')
++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
++ '_ctypes', 'libffi_osx'))
++ sources = [os.path.join(ffi_srcdir, p)
++ for p in ['ffi.c',
++ 'x86/darwin64.S',
++ 'x86/x86-darwin.S',
++ 'x86/x86-ffi_darwin.c',
++ 'x86/x86-ffi64.c',
++ 'powerpc/ppc-darwin.S',
++ 'powerpc/ppc-darwin_closure.S',
++ 'powerpc/ppc-ffi_darwin.c',
++ 'powerpc/ppc64-darwin_closure.S',
++ ]]
++
++ # Add .S (preprocessed assembly) to C compiler source extensions.
++ self.compiler.src_extensions.append('.S')
++
++ include_dirs = [os.path.join(ffi_srcdir, 'include'),
++ os.path.join(ffi_srcdir, 'powerpc')]
++ ext.include_dirs.extend(include_dirs)
++ ext.sources.extend(sources)
++ return True
++
+ def configure_ctypes(self, ext):
+ if not self.use_system_libffi:
+- (srcdir,) = sysconfig.get_config_vars('srcdir')
++ if sys.platform == 'darwin':
++ return self.configure_ctypes_darwin(ext)
++
++ srcdir = sysconfig.get_config_var('srcdir')
+ ffi_builddir = os.path.join(self.build_temp, 'libffi')
+ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
+ '_ctypes', 'libffi'))
+@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext):
+ ffi_configfile):
+ from distutils.dir_util import mkpath
+ mkpath(ffi_builddir)
+- config_args = []
++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
++ if (('--host=' in arg) or ('--build=' in arg))]
++ if not self.verbose:
++ config_args.append("-q")
+
+ # Pass empty CFLAGS because we'll just append the resulting
+ # CFLAGS to Python's; -g or -O2 is to be avoided.
+@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext):
+ self.compiler.src_extensions.append('.S')
+
+ include_dirs = [os.path.join(ffi_builddir, 'include'),
+- ffi_builddir, ffi_srcdir]
++ ffi_builddir,
++ os.path.join(ffi_srcdir, 'src')]
+ extra_compile_args = fficonfig['ffi_cflags'].split()
+
+- ext.sources.extend(fficonfig['ffi_sources'])
++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
++ fficonfig['ffi_sources'])
+ ext.include_dirs.extend(include_dirs)
+ ext.extra_compile_args.extend(extra_compile_args)
+ return True
+@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext):
+
+ if sys.platform == 'darwin':
+ sources.append('_ctypes/darwin/dlfcn_simple.c')
++ extra_compile_args.append('-DMACOSX')
+ include_dirs.append('_ctypes/darwin')
+ # XXX Is this still needed?
+ ## extra_link_args.extend(['-read_only_relocs', 'warning'])
+@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext):
+ if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
+ return
+
+- ffi_inc = find_file('ffi.h', [], inc_dirs)
++ if sys.platform == 'darwin':
++ # OS X 10.5 comes with libffi.dylib; the include files are
++ # in /usr/include/ffi
++ inc_dirs.append('/usr/include/ffi')
++
++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
++ if not ffi_inc or ffi_inc[0] == '':
++ ffi_inc = find_file('ffi.h', [], inc_dirs)
+ if ffi_inc is not None:
+ ffi_h = ffi_inc[0] + '/ffi.h'
+ fp = open(ffi_h)
diff --git a/plugins/python-build/share/python-build/patches/2.5.4/Python-2.5.4/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.4/Python-2.5.4/004_osx_libffi.patch
new file mode 100644
index 00000000..cd500771
--- /dev/null
+++ b/plugins/python-build/share/python-build/patches/2.5.4/Python-2.5.4/004_osx_libffi.patch
@@ -0,0 +1,6881 @@
+diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE
+new file mode 100644
+index 0000000..f591795
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README
+new file mode 100644
+index 0000000..1fc2747
+--- /dev/null
++++ ./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: .
++
++
++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
++ #include
++
++ 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
++.
++
++
++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
++ .
++
++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 .
++
++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 . Further enhancements were
++made by Gordon Irlam at Cygnus Solutions .
++
++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 ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc
+new file mode 100644
+index 0000000..405d85f
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c
+new file mode 100644
+index 0000000..bf42093
+--- /dev/null
++++ ./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
++#include
++
++#include
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h
+new file mode 100644
+index 0000000..c104a5c
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/include/ffi.h
+@@ -0,0 +1,355 @@
++/* -----------------------------------------------------------------*-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
++#include
++
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# endif
++#endif
++
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++#error "char size not supported"
++#endif
++
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
++#else
++#error "short size not supported"
++#endif
++
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++#error "int size not supported"
++#endif
++
++#define ffi_type_ulong ffi_type_uint64
++#define ffi_type_slong ffi_type_sint64
++
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != 9223372036854775807
++# error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != 9223372036854775807
++#error "long size not supported"
++#endif
++
++/* The closure code assumes that this works on pointers, i.e. a size_t
++ can hold a pointer. */
++
++typedef struct _ffi_type {
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++/*@null@*/ struct _ffi_type** elements;
++} ffi_type;
++
++/* These are defined in types.c */
++extern ffi_type ffi_type_void;
++extern ffi_type ffi_type_uint8;
++extern ffi_type ffi_type_sint8;
++extern ffi_type ffi_type_uint16;
++extern ffi_type ffi_type_sint16;
++extern ffi_type ffi_type_uint32;
++extern ffi_type ffi_type_sint32;
++extern ffi_type ffi_type_uint64;
++extern ffi_type ffi_type_sint64;
++extern ffi_type ffi_type_float;
++extern ffi_type ffi_type_double;
++extern ffi_type ffi_type_longdouble;
++extern ffi_type ffi_type_pointer;
++
++typedef enum ffi_status {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
++
++typedef unsigned FFI_TYPE;
++
++typedef struct ffi_cif {
++ ffi_abi abi;
++ unsigned nargs;
++/*@dependent@*/ ffi_type** arg_types;
++/*@dependent@*/ ffi_type* rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
++
++/* ---- Definitions for the raw API -------------------------------------- */
++
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == 9223372036854775807
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
++
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
++
++void
++ffi_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_raw_size(
++ ffi_cif* cif);
++
++/* This is analogous to the raw API, except it uses Java parameter
++ packing, even on 64-bit machines. I.e. on 64-bit machines
++ longs and doubles are followed by an empty 64-bit word. */
++void
++ffi_java_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_java_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_java_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_java_raw_size(
++ ffi_cif* cif);
++
++/* ---- Definitions for closures ----------------------------------------- */
++
++#if FFI_CLOSURES
++
++typedef struct ffi_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void* user_data;
++} ffi_closure;
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void* user_data);
++
++void ffi_closure_free(void *);
++void *ffi_closure_alloc (size_t size, void **code);
++
++typedef struct ffi_raw_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++
++#if !FFI_NATIVE_RAW_API
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void* this_closure;
++#endif
++
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void* user_data;
++} ffi_raw_closure;
++
++ffi_status
++ffi_prep_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++ffi_status
++ffi_prep_java_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++#endif // FFI_CLOSURES
++
++/* ---- Public interface definition -------------------------------------- */
++
++ffi_status
++ffi_prep_cif(
++/*@out@*/ /*@partial@*/ ffi_cif* cif,
++ ffi_abi abi,
++ unsigned int nargs,
++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
++/*@dependent@*/ ffi_type** atypes);
++
++void
++ffi_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ void** avalue);
++
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
++
++#endif // #ifndef LIBFFI_ASM
++/* ---- Definitions shared with assembly code ---------------------------- */
++
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++
++#ifdef HAVE_LONG_DOUBLE
++# define FFI_TYPE_LONGDOUBLE 4
++#else
++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_POINTER
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // #ifndef LIBFFI_H
+diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h
+new file mode 100644
+index 0000000..685a358
+--- /dev/null
++++ ./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
++# 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
++#else
++# ifndef HAVE_MEMCPY
++# define memcpy(d, s, n) bcopy((s), (d), (n))
++# endif
++#endif
++
++/*#if defined(FFI_DEBUG)
++#include
++#endif*/
++
++#ifdef FFI_DEBUG
++#include
++
++/*@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 ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h
+new file mode 100644
+index 0000000..2172490
+--- /dev/null
++++ ./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 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 ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h
+new file mode 100644
+index 0000000..faaa30d
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
+new file mode 100644
+index 0000000..2318421
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
+new file mode 100644
+index 0000000..55c2b6c
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+new file mode 100644
+index 0000000..f143dbd
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+@@ -0,0 +1,365 @@
++#if defined(__ppc__) || defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist
++ Copyright (c) 2004 Free Software Foundation, Inc.
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include
++#include
++#include
++
++.text
++ .align 2
++.globl _ffi_prep_args
++
++.text
++ .align 2
++.globl _ffi_call_DARWIN
++
++.text
++ .align 2
++_ffi_call_DARWIN:
++LFB0:
++ mr r12,r8 /* We only need r12 until the call,
++ so it doesn't have to be saved. */
++
++LFB1:
++ /* Save the old stack pointer as AP. */
++ mr r8,r1
++
++LCFI0:
++#if defined(__ppc64__)
++ /* Allocate the stack space we need.
++ r4 (size of input data)
++ 48 bytes (linkage area)
++ 40 bytes (saved registers)
++ 8 bytes (extra FPR)
++ r4 + 96 bytes total
++ */
++
++ addi r4,r4,-96 // Add our overhead.
++ li r0,-32 // Align to 32 bytes.
++ and r4,r4,r0
++#endif
++ stgux r1,r1,r4 // Grow the stack.
++ mflr r9
++
++ /* Save registers we use. */
++#if defined(__ppc64__)
++ std r27,-40(r8)
++#endif
++ stg r28,MODE_CHOICE(-16,-32)(r8)
++ stg r29,MODE_CHOICE(-12,-24)(r8)
++ stg r30,MODE_CHOICE(-8,-16)(r8)
++ stg r31,MODE_CHOICE(-4,-8)(r8)
++ stg r9,SF_RETURN(r8) /* return address */
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ stg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++LCFI1:
++#if defined(__ppc64__)
++ mr r27,r3 // our extended_cif
++#endif
++ /* Save arguments over call. */
++ mr r31,r5 /* flags, */
++ mr r30,r6 /* rvalue, */
++ mr r29,r7 /* function address, */
++ mr r28,r8 /* our AP. */
++
++LCFI2:
++ /* Call ffi_prep_args. */
++ mr r4,r1
++ li r9,0
++ mtctr r12 /* r12 holds address of _ffi_prep_args. */
++ bctrl
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ lg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++ /* Now do the call.
++ Set up cr1 with bits 4-7 of the flags. */
++ mtcrf 0x40,r31
++
++ /* Load all those argument registers.
++ We have set up a nice stack frame, just load it into registers. */
++ lg r3,SF_ARG1(r1)
++ lg r4,SF_ARG2(r1)
++ lg r5,SF_ARG3(r1)
++ lg r6,SF_ARG4(r1)
++ nop
++ lg r7,SF_ARG5(r1)
++ lg r8,SF_ARG6(r1)
++ lg r9,SF_ARG7(r1)
++ lg r10,SF_ARG8(r1)
++
++ /* Load all the FP registers. */
++ bf 6,L2 /* No floats to load. */
++#if defined(__ppc64__)
++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#elif defined(__ppc__)
++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#else
++#error undefined architecture
++#endif
++
++L2:
++ mr r12,r29 // Put the target address in r12 as specified.
++ mtctr r12 // Get the address to call into CTR.
++ nop
++ nop
++ bctrl // Make the call.
++
++ // Deal with the return value.
++#if defined(__ppc64__)
++ mtcrf 0x3,r31 // flags in cr6 and cr7
++ bt 27,L(st_return_value)
++#elif defined(__ppc__)
++ mtcrf 0x1,r31 // flags in cr7
++#else
++#error undefined architecture
++#endif
++
++ bt 30,L(done_return_value)
++ bt 29,L(fp_return_value)
++ stg r3,0(r30)
++#if defined(__ppc__)
++ bf 28,L(done_return_value) // Store the second long if necessary.
++ stg r4,4(r30)
++#endif
++ // Fall through
++
++L(done_return_value):
++ lg r1,0(r1) // Restore stack pointer.
++ // Restore the registers we used.
++ lg r9,SF_RETURN(r1) // return address
++ lg r31,MODE_CHOICE(-4,-8)(r1)
++ mtlr r9
++ lg r30,MODE_CHOICE(-8,-16)(r1)
++ lg r29,MODE_CHOICE(-12,-24)(r1)
++ lg r28,MODE_CHOICE(-16,-32)(r1)
++#if defined(__ppc64__)
++ ld r27,-40(r1)
++#endif
++ blr
++
++#if defined(__ppc64__)
++L(st_return_value):
++ // Grow the stack enough to fit the registers. Leave room for 8 args
++ // to trample the 1st 8 slots in param area.
++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
++
++ // Store GPRs
++ std r3,SF_ARG9(r1)
++ std r4,SF_ARG10(r1)
++ std r5,SF_ARG11(r1)
++ std r6,SF_ARG12(r1)
++ nop
++ std r7,SF_ARG13(r1)
++ std r8,SF_ARG14(r1)
++ std r9,SF_ARG15(r1)
++ std r10,SF_ARG16(r1)
++
++ // Store FPRs
++ nop
++ bf 26,L(call_struct_to_ram_form)
++ stfd f1,SF_ARG17(r1)
++ stfd f2,SF_ARG18(r1)
++ stfd f3,SF_ARG19(r1)
++ stfd f4,SF_ARG20(r1)
++ nop
++ stfd f5,SF_ARG21(r1)
++ stfd f6,SF_ARG22(r1)
++ stfd f7,SF_ARG23(r1)
++ stfd f8,SF_ARG24(r1)
++ nop
++ stfd f9,SF_ARG25(r1)
++ stfd f10,SF_ARG26(r1)
++ stfd f11,SF_ARG27(r1)
++ stfd f12,SF_ARG28(r1)
++ nop
++ stfd f13,SF_ARG29(r1)
++
++L(call_struct_to_ram_form):
++ ld r3,0(r27) // extended_cif->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ addi r4,r1,SF_ARG9 // stored GPRs
++ addi r6,r1,SF_ARG17 // stored FPRs
++ li r5,0 // GPR size ptr (NULL)
++ li r7,0 // FPR size ptr (NULL)
++ li r8,0 // FPR count ptr (NULL)
++ li r10,0 // struct offset (NULL)
++ mr r9,r30 // return area
++ bl Lffi64_struct_to_ram_form$stub
++ lg r1,0(r1) // Restore stack pointer.
++ b L(done_return_value)
++#endif
++
++L(fp_return_value):
++ /* Do we have long double to store? */
++ bf 31,L(fd_return_value)
++ stfd f1,0(r30)
++ stfd f2,8(r30)
++ b L(done_return_value)
++
++L(fd_return_value):
++ /* Do we have double to store? */
++ bf 28,L(float_return_value)
++ stfd f1,0(r30)
++ b L(done_return_value)
++
++L(float_return_value):
++ /* We only have a float to store. */
++ stfs f1,0(r30)
++ b L(done_return_value)
++
++LFE1:
++/* END(_ffi_call_DARWIN) */
++
++/* Provide a null definition of _ffi_call_AIX. */
++.text
++ .align 2
++.globl _ffi_call_AIX
++.text
++ .align 2
++_ffi_call_AIX:
++ blr
++/* END(_ffi_call_AIX) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_call_DARWIN.eh
++_ffi_call_DARWIN.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB0-. ; FDE initial location
++ .set L$set$3,LFE1-LFB0
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x08 ; uleb128 0x08
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$5,LCFI1-LCFI0
++ .long L$set$5
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .byte 0x9f ; DW_CFA_offset, column 0x1f
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x9e ; DW_CFA_offset, column 0x1e
++ .byte 0x2 ; uleb128 0x2
++ .byte 0x9d ; DW_CFA_offset, column 0x1d
++ .byte 0x3 ; uleb128 0x3
++ .byte 0x9c ; DW_CFA_offset, column 0x1c
++ .byte 0x4 ; uleb128 0x4
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$6,LCFI2-LCFI1
++ .long L$set$6
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x1c ; uleb128 0x1c
++ .align LOG2_GPR_BYTES
++LEFDE1:
++
++#if defined(__ppc64__)
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_ram_form$stub:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_ram_form
++
++LO$ffi64_struct_to_ram_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_ram_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
++#endif // __ppc__ || __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+new file mode 100644
+index 0000000..cf4bd50
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+@@ -0,0 +1,85 @@
++/* -----------------------------------------------------------------------
++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define L(x) x
++
++#define SF_ARG9 MODE_CHOICE(56,112)
++#define SF_ARG10 MODE_CHOICE(60,120)
++#define SF_ARG11 MODE_CHOICE(64,128)
++#define SF_ARG12 MODE_CHOICE(68,136)
++#define SF_ARG13 MODE_CHOICE(72,144)
++#define SF_ARG14 MODE_CHOICE(76,152)
++#define SF_ARG15 MODE_CHOICE(80,160)
++#define SF_ARG16 MODE_CHOICE(84,168)
++#define SF_ARG17 MODE_CHOICE(88,176)
++#define SF_ARG18 MODE_CHOICE(92,184)
++#define SF_ARG19 MODE_CHOICE(96,192)
++#define SF_ARG20 MODE_CHOICE(100,200)
++#define SF_ARG21 MODE_CHOICE(104,208)
++#define SF_ARG22 MODE_CHOICE(108,216)
++#define SF_ARG23 MODE_CHOICE(112,224)
++#define SF_ARG24 MODE_CHOICE(116,232)
++#define SF_ARG25 MODE_CHOICE(120,240)
++#define SF_ARG26 MODE_CHOICE(124,248)
++#define SF_ARG27 MODE_CHOICE(128,256)
++#define SF_ARG28 MODE_CHOICE(132,264)
++#define SF_ARG29 MODE_CHOICE(136,272)
++
++#define ASM_NEEDS_REGISTERS 4
++#define NUM_GPR_ARG_REGISTERS 8
++#define NUM_FPR_ARG_REGISTERS 13
++
++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
++#define FFI_TYPE_4_BYTE(x) \
++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
++
++#if !defined(LIBFFI_ASM)
++
++enum {
++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
++ FLAG_RETURNS_FP = 1 << (31 - 29),
++ FLAG_RETURNS_64BITS = 1 << (31 - 28),
++ FLAG_RETURNS_128BITS = 1 << (31 - 31),
++
++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
++
++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
++};
++
++#if defined(__ppc64__)
++void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
++ const char*, unsigned int*, unsigned int*, char*, unsigned int*);
++void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
++ unsigned int*, char*, unsigned int*, char*, unsigned int*);
++bool ffi64_stret_needs_ptr(const ffi_type* inType,
++ unsigned short*, unsigned short*);
++#endif
++
++#endif // !defined(LIBFFI_ASM)
+\ No newline at end of file
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+new file mode 100644
+index 0000000..c3d30c2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+@@ -0,0 +1,308 @@
++#if defined(__ppc__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0 // Save return address
++ stg r0,SF_RETURN(r1)
++
++LCFI0:
++ /* 24/48 bytes (Linkage Area)
++ 32/64 bytes (outgoing parameter area, always reserved)
++ 104 bytes (13*8 from FPR)
++ 16/32 bytes (result)
++ 176/232 total bytes */
++
++ /* skip over caller save area and keep stack aligned to 16/32. */
++ stgu r1,-SF_ROUND(176)(r1)
++
++LCFI1:
++ /* We want to build up an area for the parameters passed
++ in registers. (both floating point and integer) */
++
++ /* 176/256 bytes (callee stack frame aligned to 16/32)
++ 24/48 bytes (caller linkage area)
++ 200/304 (start of caller parameter area aligned to 4/8)
++ */
++
++ /* Save GPRs 3 - 10 (aligned to 4/8)
++ in the parents outgoing area. */
++ stg r3,200(r1)
++ stg r4,204(r1)
++ stg r5,208(r1)
++ stg r6,212(r1)
++ stg r7,216(r1)
++ stg r8,220(r1)
++ stg r9,224(r1)
++ stg r10,228(r1)
++
++ /* Save FPRs 1 - 13. (aligned to 8) */
++ stfd f1,56(r1)
++ stfd f2,64(r1)
++ stfd f3,72(r1)
++ stfd f4,80(r1)
++ stfd f5,88(r1)
++ stfd f6,96(r1)
++ stfd f7,104(r1)
++ stfd f8,112(r1)
++ stfd f9,120(r1)
++ stfd f10,128(r1)
++ stfd f11,136(r1)
++ stfd f12,144(r1)
++ stfd f13,152(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,160 // result storage
++ addi r5,r1,200 // saved GPRs
++ addi r6,r1,56 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ /* Now r3 contains the return type. Use it to look up in a table
++ so we know how to deal with each type. */
++ addi r5,r1,160 // Copy result storage pointer.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ (4 instructions). For cache effectiveness we align to a 16 byte boundary
++ first. */
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++/* case FFI_TYPE_VOID */
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* case FFI_TYPE_INT */
++Lret_type1:
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_FLOAT */
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_DOUBLE */
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_LONGDOUBLE */
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT8 */
++Lret_type5:
++ lbz r3,3(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT8 */
++Lret_type6:
++ lbz r3,3(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT16 */
++Lret_type7:
++ lhz r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT16 */
++Lret_type8:
++ lha r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT32 */
++Lret_type9: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT32 */
++Lret_type10: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT64 */
++Lret_type11:
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_SINT64 */
++Lret_type12: // same as Lret_type11
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_STRUCT */
++Lret_type13:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* End 16-byte aligned cases */
++/* case FFI_TYPE_POINTER */
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ // fall through
++
++/* case done */
++Lfinish:
++ addi r1,r1,SF_ROUND(176) // Restore stack pointer.
++ lg r0,SF_RETURN(r1) // Restore return address.
++ mtlr r0 // Restore link register.
++ blr
++
++/* END(ffi_closure_ASM) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++
++#endif // __ppc__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+new file mode 100644
+index 0000000..8953d5f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+@@ -0,0 +1,1776 @@
++#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
++#include
++
++#include
++#include
++#include
++#include
++#include
++
++#if 0
++#if defined(POWERPC_DARWIN)
++#include // for sys_icache_invalidate()
++#endif
++
++#else
++
++#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)
++ 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
++
++typedef union
++{
++ float f;
++ double d;
++} ffi_dblfl;
++
++/* 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;
++ long 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] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
++ else
++ avalue[i] = (void*)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(temp_ld.lb[0]));
++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
++ 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 ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+new file mode 100644
+index 0000000..7162fa1
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+@@ -0,0 +1,418 @@
++#if defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc64-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0
++ stg r0,SF_RETURN(r1) // save return address
++
++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
++ stg r3,SF_ARG1(r1)
++ stg r4,SF_ARG2(r1)
++ stg r5,SF_ARG3(r1)
++ stg r6,SF_ARG4(r1)
++ stg r7,SF_ARG5(r1)
++ stg r8,SF_ARG6(r1)
++ stg r9,SF_ARG7(r1)
++ stg r10,SF_ARG8(r1)
++
++LCFI0:
++/* 48 bytes (Linkage Area)
++ 64 bytes (outgoing parameter area, always reserved)
++ 112 bytes (14*8 for incoming FPR)
++ ? bytes (result)
++ 112 bytes (14*8 for outgoing FPR)
++ 16 bytes (2 saved registers)
++ 352 + ? total bytes
++*/
++
++ std r31,-8(r1) // Save registers we use.
++ std r30,-16(r1)
++ mr r30,r1 // Save the old SP.
++ mr r31,r11 // Save the ffi_closure around ffi64_data_size.
++
++ // Calculate the space we need.
++ stdu r1,-SF_MINSIZE(r1)
++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ bl Lffi64_data_size$stub
++ ld r1,0(r1)
++
++ addi r3,r3,352 // Add our overhead.
++ neg r3,r3
++ li r0,-32 // Align to 32 bytes.
++ and r3,r3,r0
++ stdux r1,r1,r3 // Grow the stack.
++
++ mr r11,r31 // Copy the ffi_closure back.
++
++LCFI1:
++ // We want to build up an area for the parameters passed
++ // in registers. (both floating point and integer)
++
++/* 320 bytes (callee stack frame aligned to 32)
++ 48 bytes (caller linkage area)
++ 368 (start of caller parameter area aligned to 8)
++*/
++
++ // Save FPRs 1 - 14. (aligned to 8)
++ stfd f1,112(r1)
++ stfd f2,120(r1)
++ stfd f3,128(r1)
++ stfd f4,136(r1)
++ stfd f5,144(r1)
++ stfd f6,152(r1)
++ stfd f7,160(r1)
++ stfd f8,168(r1)
++ stfd f9,176(r1)
++ stfd f10,184(r1)
++ stfd f11,192(r1)
++ stfd f12,200(r1)
++ stfd f13,208(r1)
++ stfd f14,216(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,224 // result storage
++ addi r5,r30,SF_ARG1 // saved GPRs
++ addi r6,r1,112 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ // Look the proper starting point in table
++ // by using return type as an offset.
++ addi r5,r1,224 // Get pointer to results area.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Now multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ // (4 instructions). For cache effectiveness we align to a 16 byte
++ // boundary first.
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++// case FFI_TYPE_VOID
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++// case FFI_TYPE_INT
++Lret_type1:
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_FLOAT
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_DOUBLE
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_LONGDOUBLE
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT8
++Lret_type5:
++ lbz r3,7(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT8
++Lret_type6:
++ lbz r3,7(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT16
++Lret_type7:
++ lhz r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT16
++Lret_type8:
++ lha r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT32
++Lret_type9: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT32
++Lret_type10: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT64
++Lret_type11:
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT64
++Lret_type12: // same as Lret_type11
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_STRUCT
++Lret_type13:
++ b Lret_struct
++ nop
++ nop
++ nop
++
++// ** End 16-byte aligned cases **
++// case FFI_TYPE_POINTER
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ b Lfinish
++
++// copy struct into registers
++Lret_struct:
++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r31) // ffi_cif->rtype*
++ ld r31,24(r31) // ffi_cif->flags
++ mr r4,r5 // copy struct* to 2nd arg
++ addi r7,r1,SF_ARG9 // GPR return area
++ addi r9,r30,-16-(14*8) // FPR return area
++ li r5,0 // struct offset ptr (NULL)
++ li r6,0 // FPR used count ptr (NULL)
++ li r8,0 // GPR return area size ptr (NULL)
++ li r10,0 // FPR return area size ptr (NULL)
++ bl Lffi64_struct_to_reg_form$stub
++
++ // Load GPRs
++ ld r3,SF_ARG9(r1)
++ ld r4,SF_ARG10(r1)
++ ld r5,SF_ARG11(r1)
++ ld r6,SF_ARG12(r1)
++ nop
++ ld r7,SF_ARG13(r1)
++ ld r8,SF_ARG14(r1)
++ ld r9,SF_ARG15(r1)
++ ld r10,SF_ARG16(r1)
++ nop
++
++ // Load FPRs
++ mtcrf 0x2,r31
++ bf 26,Lfinish
++ lfd f1,-16-(14*8)(r30)
++ lfd f2,-16-(13*8)(r30)
++ lfd f3,-16-(12*8)(r30)
++ lfd f4,-16-(11*8)(r30)
++ nop
++ lfd f5,-16-(10*8)(r30)
++ lfd f6,-16-(9*8)(r30)
++ lfd f7,-16-(8*8)(r30)
++ lfd f8,-16-(7*8)(r30)
++ nop
++ lfd f9,-16-(6*8)(r30)
++ lfd f10,-16-(5*8)(r30)
++ lfd f11,-16-(4*8)(r30)
++ lfd f12,-16-(3*8)(r30)
++ nop
++ lfd f13,-16-(2*8)(r30)
++ lfd f14,-16-(1*8)(r30)
++ // Fall through
++
++// case done
++Lfinish:
++ lg r1,0(r1) // Restore stack pointer.
++ ld r31,-8(r1) // Restore registers we used.
++ ld r30,-16(r1)
++ lg r0,SF_RETURN(r1) // Get return address.
++ mtlr r0 // Reset link register.
++ blr
++
++// END(ffi_closure_ASM)
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_reg_form$stub:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_reg_form
++
++LO$ffi64_struct_to_reg_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
++ mtctr r12
++ bctr
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_data_size$stub:
++ .indirect_symbol _ffi64_data_size
++ mflr r0
++ bcl 20,31,LO$ffi64_data_size
++
++LO$ffi64_data_size:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_reg_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ .g_long dyld_stub_binding_helper
++
++L_ffi64_data_size$lazy_ptr:
++ .indirect_symbol _ffi64_data_size
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c
+new file mode 100644
+index 0000000..44806ae
+--- /dev/null
++++ ./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
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+new file mode 100644
+index 0000000..165d469
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S
+@@ -0,0 +1,417 @@
++/* -----------------------------------------------------------------------
++ 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
++#include
++
++ .file "darwin64.S"
++.text
++
++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
++ void *raddr, void (*fnaddr)());
++
++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
++ for this function. This has been allocated by ffi_call. We also
++ deallocate some of the stack that has been alloca'd. */
++
++ .align 3
++ .globl _ffi_call_unix64
++
++_ffi_call_unix64:
++LUW0:
++ movq (%rsp), %r10 /* Load return address. */
++ movq %rdi, %r12 /* Save a copy of the register area. */
++ leaq (%rdi, %rsi), %rax /* Find local stack base. */
++ movq %rdx, (%rax) /* Save flags. */
++ movq %rcx, 8(%rax) /* Save raddr. */
++ movq %rbp, 16(%rax) /* Save old frame pointer. */
++ movq %r10, 24(%rax) /* Relocate return address. */
++ movq %rax, %rbp /* Finalize local stack frame. */
++LUW1:
++ /* movq %rdi, %r10 // Save a copy of the register area. */
++ movq %r12, %r10
++ movq %r8, %r11 /* Save a copy of the target fn. */
++ movl %r9d, %eax /* Set number of SSE registers. */
++
++ /* Load up all argument registers. */
++ movq (%r10), %rdi
++ movq 8(%r10), %rsi
++ movq 16(%r10), %rdx
++ movq 24(%r10), %rcx
++ movq 32(%r10), %r8
++ movq 40(%r10), %r9
++ testl %eax, %eax
++ jnz Lload_sse
++Lret_from_load_sse:
++
++ /* Deallocate the reg arg area. */
++ leaq 176(%r10), %rsp
++
++ /* Call the user function. */
++ call *%r11
++
++ /* Deallocate stack arg area; local stack frame in redzone. */
++ leaq 24(%rbp), %rsp
++
++ movq 0(%rbp), %rcx /* Reload flags. */
++ movq 8(%rbp), %rdi /* Reload raddr. */
++ movq 16(%rbp), %rbp /* Reload old frame pointer. */
++LUW2:
++
++ /* The first byte of the flags contains the FFI_TYPE. */
++ movzbl %cl, %r10d
++ leaq Lstore_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lstore_table:
++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lst_void:
++ ret
++ .align 3
++Lst_uint8:
++ movzbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_sint8:
++ movsbq %al, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint16:
++ movzwq %ax, %rax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint16:
++ movswq %ax, %rax
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_uint32:
++ movl %eax, %eax
++ movq %rax, (%rdi)
++ .align 3
++Lst_sint32:
++ cltq
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_int64:
++ movq %rax, (%rdi)
++ ret
++ .align 3
++Lst_float:
++ movss %xmm0, (%rdi)
++ ret
++ .align 3
++Lst_double:
++ movsd %xmm0, (%rdi)
++ ret
++Lst_ldouble:
++ fstpt (%rdi)
++ ret
++ .align 3
++Lst_struct:
++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */
++
++ /* We have to locate the values now, and since we don't want to
++ write too much data into the user's return value, we spill the
++ value to a 16 byte scratch area first. Bits 8, 9, and 10
++ control where the values are located. Only one of the three
++ bits will be set; see ffi_prep_cif_machdep for the pattern. */
++ movd %xmm0, %r10
++ movd %xmm1, %r11
++ testl $0x100, %ecx
++ cmovnz %rax, %rdx
++ cmovnz %r10, %rax
++ testl $0x200, %ecx
++ cmovnz %r10, %rdx
++ testl $0x400, %ecx
++ cmovnz %r10, %rax
++ cmovnz %r11, %rdx
++ movq %rax, (%rsi)
++ movq %rdx, 8(%rsi)
++
++ /* Bits 12-31 contain the true size of the structure. Copy from
++ the scratch area to the true destination. */
++ shrl $12, %ecx
++ rep movsb
++ ret
++
++ /* Many times we can avoid loading any SSE registers at all.
++ It's not worth an indirect jump to load the exact set of
++ SSE registers needed; zero or all is a good compromise. */
++ .align 3
++LUW3:
++Lload_sse:
++ movdqa 48(%r10), %xmm0
++ movdqa 64(%r10), %xmm1
++ movdqa 80(%r10), %xmm2
++ movdqa 96(%r10), %xmm3
++ movdqa 112(%r10), %xmm4
++ movdqa 128(%r10), %xmm5
++ movdqa 144(%r10), %xmm6
++ movdqa 160(%r10), %xmm7
++ jmp Lret_from_load_sse
++
++LUW4:
++ .align 3
++ .globl _ffi_closure_unix64
++
++_ffi_closure_unix64:
++LUW5:
++ /* The carry flag is set by the trampoline iff SSE registers
++ are used. Don't clobber it before the branch instruction. */
++ leaq -200(%rsp), %rsp
++LUW6:
++ movq %rdi, (%rsp)
++ movq %rsi, 8(%rsp)
++ movq %rdx, 16(%rsp)
++ movq %rcx, 24(%rsp)
++ movq %r8, 32(%rsp)
++ movq %r9, 40(%rsp)
++ jc Lsave_sse
++Lret_from_save_sse:
++
++ movq %r10, %rdi
++ leaq 176(%rsp), %rsi
++ movq %rsp, %rdx
++ leaq 208(%rsp), %rcx
++ call _ffi_closure_unix64_inner
++
++ /* Deallocate stack frame early; return value is now in redzone. */
++ addq $200, %rsp
++LUW7:
++
++ /* The first byte of the return value contains the FFI_TYPE. */
++ movzbl %al, %r10d
++ leaq Lload_table(%rip), %r11
++ movslq (%r11, %r10, 4), %r10
++ addq %r11, %r10
++ jmp *%r10
++
++Lload_table:
++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */
++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */
++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
++
++ .text
++ .align 3
++Lld_void:
++ ret
++ .align 3
++Lld_int8:
++ movzbl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int16:
++ movzwl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int32:
++ movl -24(%rsp), %eax
++ ret
++ .align 3
++Lld_int64:
++ movq -24(%rsp), %rax
++ ret
++ .align 3
++Lld_float:
++ movss -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_double:
++ movsd -24(%rsp), %xmm0
++ ret
++ .align 3
++Lld_ldouble:
++ fldt -24(%rsp)
++ ret
++ .align 3
++Lld_struct:
++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
++ both rdx and xmm1 with the second word. For the remaining,
++ bit 8 set means xmm0 gets the second word, and bit 9 means
++ that rax gets the second word. */
++ movq -24(%rsp), %rcx
++ movq -16(%rsp), %rdx
++ movq -16(%rsp), %xmm1
++ testl $0x100, %eax
++ cmovnz %rdx, %rcx
++ movd %rcx, %xmm0
++ testl $0x200, %eax
++ movq -24(%rsp), %rax
++ cmovnz %rdx, %rax
++ ret
++
++ /* See the comment above Lload_sse; the same logic applies here. */
++ .align 3
++LUW8:
++Lsave_sse:
++ movdqa %xmm0, 48(%rsp)
++ movdqa %xmm1, 64(%rsp)
++ movdqa %xmm2, 80(%rsp)
++ movdqa %xmm3, 96(%rsp)
++ movdqa %xmm4, 112(%rsp)
++ movdqa %xmm5, 128(%rsp)
++ movdqa %xmm6, 144(%rsp)
++ movdqa %xmm7, 160(%rsp)
++ jmp Lret_from_save_sse
++
++LUW9:
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */
++ .long L$set$0
++LSCIE1:
++ .long 0x0 /* CIE Identifier Tag */
++ .byte 0x1 /* CIE Version */
++ .ascii "zR\0" /* CIE Augmentation */
++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
++ .byte 0x10 /* CIE RA Column */
++ .byte 0x1 /* uleb128 0x1; Augmentation size */
++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */
++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
++ .byte 0x7 /* uleb128 0x7 */
++ .byte 0x8 /* uleb128 0x8 */
++ .byte 0x90 /* DW_CFA_offset, column 0x10 */
++ .byte 0x1
++ .align 3
++LECIE1:
++ .globl _ffi_call_unix64.eh
++_ffi_call_unix64.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1 /* FDE CIE offset */
++ .quad LUW0-. /* FDE initial location */
++ .set L$set$2,LUW4-LUW0 /* FDE address range */
++ .quad L$set$2
++ .byte 0x0 /* Augmentation size */
++ .byte 0x4 /* DW_CFA_advance_loc4 */
++ .set L$set$3,LUW1-LUW0
++ .long L$set$3
++
++ /* New stack frame based off rbp. This is 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 ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+new file mode 100644
+index 0000000..925a841
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S
+@@ -0,0 +1,422 @@
++#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
++#include
++
++#ifdef PyObjC_STRICT_DEBUGGING
++ /* XXX: Debugging of stack alignment, to be removed */
++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
++#else
++#define ASSERT_STACK_ALIGNED
++#endif
++
++.text
++
++.globl _ffi_prep_args
++
++ .align 4
++.globl _ffi_call_SYSV
++
++_ffi_call_SYSV:
++LFB1:
++ pushl %ebp
++LCFI0:
++ movl %esp,%ebp
++LCFI1:
++ subl $8,%esp
++ /* Make room for all of the new args. */
++ movl 16(%ebp),%ecx
++ subl %ecx,%esp
++
++ movl %esp,%eax
++
++ /* Place all of the ffi_prep_args in position */
++ subl $8,%esp
++ pushl 12(%ebp)
++ pushl %eax
++ call *8(%ebp)
++
++ /* Return stack to previous state and call the function */
++ addl $16,%esp
++
++ call *28(%ebp)
++
++ /* Remove the space we pushed for the args */
++ movl 16(%ebp),%ecx
++ addl %ecx,%esp
++
++ /* Load %ecx with the return type code */
++ movl 20(%ebp),%ecx
++
++ /* If the return value pointer is NULL, assume no return value. */
++ cmpl $0,24(%ebp)
++ jne Lretint
++
++ /* Even if there is no space for the return value, we are
++ obliged to handle floating-point values. */
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lnoretval
++ fstp %st(0)
++
++ jmp Lepilogue
++
++Lretint:
++ cmpl $FFI_TYPE_INT,%ecx
++ jne Lretfloat
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ jmp Lepilogue
++
++Lretfloat:
++ cmpl $FFI_TYPE_FLOAT,%ecx
++ jne Lretdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstps (%ecx)
++ jmp Lepilogue
++
++Lretdouble:
++ cmpl $FFI_TYPE_DOUBLE,%ecx
++ jne Lretlongdouble
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpl (%ecx)
++ jmp Lepilogue
++
++Lretlongdouble:
++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx
++ jne Lretint64
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ fstpt (%ecx)
++ jmp Lepilogue
++
++Lretint64:
++ cmpl $FFI_TYPE_SINT64,%ecx
++ jne Lretstruct1b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movl %eax,0(%ecx)
++ movl %edx,4(%ecx)
++ jmp Lepilogue
++
++Lretstruct1b:
++ cmpl $FFI_TYPE_SINT8,%ecx
++ jne Lretstruct2b
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movb %al,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct2b:
++ cmpl $FFI_TYPE_SINT16,%ecx
++ jne Lretstruct
++ /* Load %ecx with the pointer to storage for the return value */
++ movl 24(%ebp),%ecx
++ movw %ax,0(%ecx)
++ jmp Lepilogue
++
++Lretstruct:
++ cmpl $FFI_TYPE_STRUCT,%ecx
++ jne Lnoretval
++ /* Nothing to do! */
++ addl $4,%esp
++ popl %ebp
++ ret
++
++Lnoretval:
++Lepilogue:
++ addl $8,%esp
++ movl %ebp,%esp
++ popl %ebp
++ ret
++LFE1:
++.ffi_call_SYSV_end:
++
++ .align 4
++FFI_HIDDEN (ffi_closure_SYSV)
++.globl _ffi_closure_SYSV
++
++_ffi_closure_SYSV:
++LFB2:
++ pushl %ebp
++LCFI2:
++ movl %esp, %ebp
++LCFI3:
++ subl $56, %esp
++ leal -40(%ebp), %edx
++ movl %edx, -12(%ebp) /* resp */
++ leal 8(%ebp), %edx
++ movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
++ leal -12(%ebp), %edx
++ movl %edx, (%esp) /* &resp */
++ movl %ebx, 8(%esp)
++LCFI7:
++ call L_ffi_closure_SYSV_inner$stub
++ movl 8(%esp), %ebx
++ movl -12(%ebp), %ecx
++ cmpl $FFI_TYPE_INT, %eax
++ je Lcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lcls_retllong
++ cmpl $FFI_TYPE_UINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_SINT8, %eax
++ je Lcls_retstruct1
++ cmpl $FFI_TYPE_UINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_SINT16, %eax
++ je Lcls_retstruct2
++ cmpl $FFI_TYPE_STRUCT, %eax
++ je Lcls_retstruct
++Lcls_epilogue:
++ movl %ebp, %esp
++ popl %ebp
++ ret
++Lcls_retint:
++ movl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retfloat:
++ flds (%ecx)
++ jmp Lcls_epilogue
++Lcls_retdouble:
++ fldl (%ecx)
++ jmp Lcls_epilogue
++Lcls_retldouble:
++ fldt (%ecx)
++ jmp Lcls_epilogue
++Lcls_retllong:
++ movl (%ecx), %eax
++ movl 4(%ecx), %edx
++ jmp Lcls_epilogue
++Lcls_retstruct1:
++ movsbl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct2:
++ movswl (%ecx), %eax
++ jmp Lcls_epilogue
++Lcls_retstruct:
++ lea -8(%ebp),%esp
++ movl %ebp, %esp
++ popl %ebp
++ ret $4
++LFE2:
++
++#if !FFI_NO_RAW_API
++
++#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
++#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
++#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
++#define CIF_FLAGS_OFFSET 20
++
++ .align 4
++FFI_HIDDEN (ffi_closure_raw_SYSV)
++.globl _ffi_closure_raw_SYSV
++
++_ffi_closure_raw_SYSV:
++LFB3:
++ pushl %ebp
++LCFI4:
++ movl %esp, %ebp
++LCFI5:
++ pushl %esi
++LCFI6:
++ subl $36, %esp
++ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
++ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
++ movl %edx, 12(%esp) /* user_data */
++ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
++ movl %edx, 8(%esp) /* raw_args */
++ leal -24(%ebp), %edx
++ movl %edx, 4(%esp) /* &res */
++ movl %esi, (%esp) /* cif */
++ call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
++ movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
++ cmpl $FFI_TYPE_INT, %eax
++ je Lrcls_retint
++ cmpl $FFI_TYPE_FLOAT, %eax
++ je Lrcls_retfloat
++ cmpl $FFI_TYPE_DOUBLE, %eax
++ je Lrcls_retdouble
++ cmpl $FFI_TYPE_LONGDOUBLE, %eax
++ je Lrcls_retldouble
++ cmpl $FFI_TYPE_SINT64, %eax
++ je Lrcls_retllong
++Lrcls_epilogue:
++ addl $36, %esp
++ popl %esi
++ popl %ebp
++ ret
++Lrcls_retint:
++ movl -24(%ebp), %eax
++ jmp Lrcls_epilogue
++Lrcls_retfloat:
++ flds -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retdouble:
++ fldl -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retldouble:
++ fldt -24(%ebp)
++ jmp Lrcls_epilogue
++Lrcls_retllong:
++ movl -24(%ebp), %eax
++ movl -20(%ebp), %edx
++ jmp Lrcls_epilogue
++LFE3:
++#endif
++
++.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
++L_ffi_closure_SYSV_inner$stub:
++ .indirect_symbol _ffi_closure_SYSV_inner
++ hlt ; hlt ; hlt ; hlt ; hlt
++
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0
++LSCIE1:
++ .long 0x0
++ .byte 0x1
++ .ascii "zR\0"
++ .byte 0x1
++ .byte 0x7c
++ .byte 0x8
++ .byte 0x1
++ .byte 0x10
++ .byte 0xc
++ .byte 0x5
++ .byte 0x4
++ .byte 0x88
++ .byte 0x1
++ .align 2
++LECIE1:
++.globl _ffi_call_SYSV.eh
++_ffi_call_SYSV.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1
++LASFDE1:
++ .long LASFDE1-EH_frame1
++ .long LFB1-.
++ .set L$set$2,LFE1-LFB1
++ .long L$set$2
++ .byte 0x0
++ .byte 0x4
++ .set L$set$3,LCFI0-LFB1
++ .long L$set$3
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$4,LCFI1-LCFI0
++ .long L$set$4
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE1:
++.globl _ffi_closure_SYSV.eh
++_ffi_closure_SYSV.eh:
++LSFDE2:
++ .set L$set$5,LEFDE2-LASFDE2
++ .long L$set$5
++LASFDE2:
++ .long LASFDE2-EH_frame1
++ .long LFB2-.
++ .set L$set$6,LFE2-LFB2
++ .long L$set$6
++ .byte 0x0
++ .byte 0x4
++ .set L$set$7,LCFI2-LFB2
++ .long L$set$7
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$8,LCFI3-LCFI2
++ .long L$set$8
++ .byte 0xd
++ .byte 0x4
++ .align 2
++LEFDE2:
++
++#if !FFI_NO_RAW_API
++
++.globl _ffi_closure_raw_SYSV.eh
++_ffi_closure_raw_SYSV.eh:
++LSFDE3:
++ .set L$set$10,LEFDE3-LASFDE3
++ .long L$set$10
++LASFDE3:
++ .long LASFDE3-EH_frame1
++ .long LFB3-.
++ .set L$set$11,LFE3-LFB3
++ .long L$set$11
++ .byte 0x0
++ .byte 0x4
++ .set L$set$12,LCFI4-LFB3
++ .long L$set$12
++ .byte 0xe
++ .byte 0x8
++ .byte 0x84
++ .byte 0x2
++ .byte 0x4
++ .set L$set$13,LCFI5-LCFI4
++ .long L$set$13
++ .byte 0xd
++ .byte 0x4
++ .byte 0x4
++ .set L$set$14,LCFI6-LCFI5
++ .long L$set$14
++ .byte 0x85
++ .byte 0x3
++ .align 2
++LEFDE3:
++
++#endif
++
++#endif /* ifndef __x86_64__ */
++
++#endif /* defined __i386__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+new file mode 100644
+index 0000000..06feaf2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
+@@ -0,0 +1,734 @@
++#ifdef __x86_64__
++
++/* -----------------------------------------------------------------------
++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen
++
++ 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
++#include
++
++#include
++#include
++
++#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 0
++ if (byte_offset + type->size <= 4)
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ else
++ classes[0] = X86_64_INTEGER_CLASS;
++
++ return 1;
++#else
++ {
++ int size = byte_offset + type->size;
++
++ if (size <= 4)
++ {
++ classes[0] = X86_64_INTEGERSI_CLASS;
++ return 1;
++ }
++ else if (size <= 8)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ return 1;
++ }
++ else if (size <= 12)
++ {
++ classes[0] = X86_64_INTEGER_CLASS;
++ classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else if (size <= 16)
++ {
++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
++ return 2;
++ }
++ else
++ FFI_ASSERT (0);
++ }
++#endif
++
++ case FFI_TYPE_FLOAT:
++ if (byte_offset == 0)
++ classes[0] = X86_64_SSESF_CLASS;
++ else
++ classes[0] = X86_64_SSE_CLASS;
++
++ return 1;
++
++ case FFI_TYPE_DOUBLE:
++ classes[0] = X86_64_SSEDF_CLASS;
++ return 1;
++
++ case FFI_TYPE_LONGDOUBLE:
++ classes[0] = X86_64_X87_CLASS;
++ classes[1] = X86_64_X87UP_CLASS;
++ return 2;
++
++ case FFI_TYPE_STRUCT:
++ {
++ ffi_type** ptr;
++ int i;
++ enum x86_64_reg_class subclasses[MAX_CLASSES];
++ const int UNITS_PER_WORD = 8;
++ int words =
++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
++
++ /* If the struct is larger than 16 bytes, pass it on the stack. */
++ if (type->size > 16)
++ return 0;
++
++ for (i = 0; i < words; i++)
++ classes[i] = X86_64_NO_CLASS;
++
++ /* Merge the fields of structure. */
++ for (ptr = type->elements; *ptr != NULL; ptr++)
++ {
++ 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;
++ }
++
++ if (words > 2)
++ {
++ /* When size > 16 bytes, if the first one isn't
++ X86_64_SSE_CLASS or any other ones aren't
++ X86_64_SSEUP_CLASS, everything should be passed in
++ memory. */
++ if (classes[0] != X86_64_SSE_CLASS)
++ return 0;
++
++ for (i = 1; i < words; i++)
++ if (classes[i] != X86_64_SSEUP_CLASS)
++ return 0;
++ }
++
++
++ /* Final merger cleanup. */
++ for (i = 0; i < words; i++)
++ {
++ /* If one class is MEMORY, everything should be passed in
++ memory. */
++ if (classes[i] == X86_64_MEMORY_CLASS)
++ return 0;
++
++ /* The X86_64_SSEUP_CLASS should be always preceded by
++ X86_64_SSE_CLASS. */
++ if (classes[i] == X86_64_SSEUP_CLASS
++ && classes[i - 1] != X86_64_SSE_CLASS
++ && classes[i - 1] != X86_64_SSEUP_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++
++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
++ if (classes[i] == X86_64_X87UP_CLASS
++ && classes[i - 1] != X86_64_X87_CLASS)
++ {
++ FFI_ASSERT(i != 0);
++ classes[i] = X86_64_SSE_CLASS;
++ }
++ }
++
++ return words;
++ }
++
++ default:
++ FFI_ASSERT(0);
++ }
++
++ return 0; /* Never reached. */
++}
++
++/* Examine the argument and return set number of register required in each
++ class. Return zero if parameter should be passed in memory, otherwise
++ the number of registers. */
++static int
++examine_argument(
++ ffi_type* type,
++ enum x86_64_reg_class classes[MAX_CLASSES],
++ _Bool in_return,
++ int* pngpr,
++ int* pnsse)
++{
++ int n = classify_argument(type, classes, 0);
++ int ngpr = 0;
++ int nsse = 0;
++ int i;
++
++ if (n == 0)
++ return 0;
++
++ for (i = 0; i < n; ++i)
++ {
++ switch (classes[i])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ ngpr++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSESF_CLASS:
++ case X86_64_SSEDF_CLASS:
++ nsse++;
++ break;
++
++ case X86_64_NO_CLASS:
++ case X86_64_SSEUP_CLASS:
++ break;
++
++ case X86_64_X87_CLASS:
++ case X86_64_X87UP_CLASS:
++ case X86_64_COMPLEX_X87_CLASS:
++ return in_return != 0;
++
++ default:
++ abort();
++ }
++ }
++
++ *pngpr = ngpr;
++ *pnsse = nsse;
++
++ return n;
++}
++
++/* Perform machine dependent cif processing. */
++ffi_status
++ffi_prep_cif_machdep(
++ ffi_cif* cif)
++{
++ int gprcount = 0;
++ int ssecount = 0;
++ int flags = cif->rtype->type;
++ int i, avn, n, ngpr, nsse;
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ size_t bytes;
++
++ if (flags != FFI_TYPE_VOID)
++ {
++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value is passed in memory. A pointer to that
++ memory is the first argument. Allocate a register for it. */
++ gprcount++;
++
++ /* We don't have to do anything in asm for the return. */
++ flags = FFI_TYPE_VOID;
++ }
++ else if (flags == FFI_TYPE_STRUCT)
++ {
++ /* Mark which registers the result appears in. */
++ _Bool sse0 = SSE_CLASS_P(classes[0]);
++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
++
++ if (sse0 && !sse1)
++ flags |= 1 << 8;
++ else if (!sse0 && sse1)
++ flags |= 1 << 9;
++ else if (sse0 && sse1)
++ flags |= 1 << 10;
++
++ /* Mark the true size of the structure. */
++ flags |= cif->rtype->size << 12;
++ }
++ }
++
++ /* Go over all arguments and determine the way they should be passed.
++ If it's in a register and there is space for it, let that be so. If
++ not, add it's size to the stack byte count. */
++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
++ {
++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = cif->arg_types[i]->alignment;
++
++ if (align < 8)
++ align = 8;
++
++ bytes = ALIGN(bytes, align);
++ bytes += cif->arg_types[i]->size;
++ }
++ else
++ {
++ gprcount += ngpr;
++ ssecount += nsse;
++ }
++ }
++
++ if (ssecount)
++ flags |= 1 << 11;
++
++ cif->flags = flags;
++ cif->bytes = bytes;
++ cif->bytes = ALIGN(bytes,8);
++
++ return FFI_OK;
++}
++
++void
++ffi_call(
++ ffi_cif* cif,
++ void (*fn)(),
++ void* rvalue,
++ void** avalue)
++{
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ char* stack;
++ char* argp;
++ ffi_type** arg_types;
++ int gprcount, ssecount, ngpr, nsse, i, avn;
++ _Bool ret_in_memory;
++ RegisterArgs* reg_args;
++
++ /* Can't call 32-bit mode from 64-bit mode. */
++ FFI_ASSERT(cif->abi == FFI_UNIX64);
++
++ /* If the return value is a struct and we don't have a return value
++ address then we need to make one. Note the setting of flags to
++ VOID above in ffi_prep_cif_machdep. */
++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
++ && (cif->flags & 0xff) == FFI_TYPE_VOID);
++
++ if (rvalue == NULL && ret_in_memory)
++ rvalue = alloca (cif->rtype->size);
++
++ /* Allocate the space for the arguments, plus 4 words of temp space. */
++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
++ reg_args = (RegisterArgs*)stack;
++ argp = stack + sizeof(RegisterArgs);
++
++ gprcount = ssecount = 0;
++
++ /* If the return value is passed in memory, add the pointer as the
++ first integer argument. */
++ if (ret_in_memory)
++ reg_args->gpr[gprcount++] = (long) rvalue;
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ size_t size = arg_types[i]->size;
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ memcpy (argp, avalue[i], size);
++ argp += size;
++ }
++ else
++ { /* The argument is passed entirely in registers. */
++ char *a = (char *) avalue[i];
++ int j;
++
++ for (j = 0; j < n; j++, a += 8, size -= 8)
++ {
++ switch (classes[j])
++ {
++ case X86_64_INTEGER_CLASS:
++ case X86_64_INTEGERSI_CLASS:
++ reg_args->gpr[gprcount] = 0;
++ switch (arg_types[i]->type) {
++ case FFI_TYPE_SINT8:
++ {
++ int8_t shortval = *(int8_t*)a;
++ int64_t actval = (int64_t)shortval;
++ reg_args->gpr[gprcount] = actval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ break;
++ }
++
++ case FFI_TYPE_SINT16:
++ {
++ int16_t shortval = *(int16_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_SINT32:
++ {
++ int32_t shortval = *(int32_t*)a;
++ int64_t actval = (int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT8:
++ {
++ u_int8_t shortval = *(u_int8_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
++ reg_args->gpr[gprcount] = actval;
++ break;
++ }
++
++ case FFI_TYPE_UINT16:
++ {
++ u_int16_t shortval = *(u_int16_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ case FFI_TYPE_UINT32:
++ {
++ u_int32_t shortval = *(u_int32_t*)a;
++ u_int64_t actval = (u_int64_t)shortval;
++ memcpy (®_args->gpr[gprcount], &actval, 8);
++ break;
++ }
++
++ default:
++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
++ reg_args->gpr[gprcount] = *(int64_t*)a;
++ }
++ gprcount++;
++ break;
++
++ case X86_64_SSE_CLASS:
++ case X86_64_SSEDF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT64 *) a;
++ break;
++
++ case X86_64_SSESF_CLASS:
++ reg_args->sse[ssecount++] = *(UINT32 *) a;
++ break;
++
++ default:
++ abort();
++ }
++ }
++ }
++ }
++
++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
++ cif->flags, rvalue, fn, ssecount);
++}
++
++extern void ffi_closure_unix64(void);
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*, void*, void**, void*),
++ void* user_data)
++{
++ if (cif->abi != FFI_UNIX64)
++ return FFI_BAD_ABI;
++
++ volatile unsigned short* tramp =
++ (volatile unsigned short*)&closure->tramp[0];
++
++ tramp[0] = 0xbb49; /* mov , %r11 */
++ *(void* volatile*)&tramp[1] = ffi_closure_unix64;
++ tramp[5] = 0xba49; /* mov , %r10 */
++ *(void* volatile*)&tramp[6] = closure;
++
++ /* Set the carry bit if the function uses any sse registers.
++ This is clc or stc, together with the first byte of the jmp. */
++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
++ tramp[11] = 0xe3ff; /* jmp *%r11 */
++
++ closure->cif = cif;
++ closure->fun = fun;
++ closure->user_data = user_data;
++
++ return FFI_OK;
++}
++
++#pragma clang diagnostic push
++#pragma clang diagnostic ignored "-Wmissing-prototypes"
++int
++ffi_closure_unix64_inner(
++ ffi_closure* closure,
++ void* rvalue,
++ RegisterArgs* reg_args,
++ char* argp)
++#pragma clang diagnostic pop
++{
++ ffi_cif* cif = closure->cif;
++ void** avalue = alloca(cif->nargs * sizeof(void *));
++ ffi_type** arg_types;
++ long i, avn;
++ int gprcount = 0;
++ int ssecount = 0;
++ int ngpr, nsse;
++ int ret;
++
++ ret = cif->rtype->type;
++
++ if (ret != FFI_TYPE_VOID)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
++
++ if (n == 0)
++ {
++ /* The return value goes in memory. Arrange for the closure
++ return value to go directly back to the original caller. */
++ rvalue = (void *) reg_args->gpr[gprcount++];
++
++ /* We don't have to do anything in asm for the return. */
++ ret = FFI_TYPE_VOID;
++ }
++ else if (ret == FFI_TYPE_STRUCT && n == 2)
++ {
++ /* Mark which register the second word of the structure goes in. */
++ _Bool sse0 = SSE_CLASS_P (classes[0]);
++ _Bool sse1 = SSE_CLASS_P (classes[1]);
++
++ if (!sse0 && sse1)
++ ret |= 1 << 8;
++ else if (sse0 && !sse1)
++ ret |= 1 << 9;
++ }
++ }
++
++ avn = cif->nargs;
++ arg_types = cif->arg_types;
++
++ for (i = 0; i < avn; ++i)
++ {
++ enum x86_64_reg_class classes[MAX_CLASSES];
++ int n;
++
++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
++
++ if (n == 0
++ || gprcount + ngpr > MAX_GPR_REGS
++ || ssecount + nsse > MAX_SSE_REGS)
++ {
++ long align = arg_types[i]->alignment;
++
++ /* Stack arguments are *always* at least 8 byte aligned. */
++ if (align < 8)
++ align = 8;
++
++ /* Pass this argument in memory. */
++ argp = (void *) ALIGN (argp, align);
++ avalue[i] = argp;
++ argp += arg_types[i]->size;
++ }
++
++#if !defined(X86_DARWIN)
++ /* If the argument is in a single register, or two consecutive
++ registers, then we can use that address directly. */
++ else if (n == 1 || (n == 2 &&
++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
++ {
++ // The argument is in a single register.
++ if (SSE_CLASS_P (classes[0]))
++ {
++ avalue[i] = ®_args->sse[ssecount];
++ ssecount += n;
++ }
++ else
++ {
++ avalue[i] = ®_args->gpr[gprcount];
++ gprcount += n;
++ }
++ }
++#endif
++
++ /* Otherwise, allocate space to make them consecutive. */
++ else
++ {
++ char *a = alloca (16);
++ int j;
++
++ avalue[i] = a;
++
++ for (j = 0; j < n; j++, a += 8)
++ {
++ if (SSE_CLASS_P (classes[j]))
++ memcpy (a, ®_args->sse[ssecount++], 8);
++ else
++ memcpy (a, ®_args->gpr[gprcount++], 8);
++ }
++ }
++ }
++
++ /* Invoke the closure. */
++ closure->fun (cif, rvalue, avalue, closure->user_data);
++
++ /* Tell assembly how to perform return type promotions. */
++ return ret;
++}
++
++#endif /* __x86_64__ */
+diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+new file mode 100644
+index 0000000..706ea0f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
+@@ -0,0 +1,438 @@
++#ifdef __i386__
++/* -----------------------------------------------------------------------
++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
++ Copyright (c) 2002 Ranjit Mathew
++ Copyright (c) 2002 Bo Thorsen
++ Copyright (c) 2002 Roger Sayle
++
++ x86 Foreign Function Interface
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#include
++#include
++
++#include
++
++/* ffi_prep_args is called by the assembly routine once stack space
++ has been allocated for the function's arguments */
++
++void ffi_prep_args(char *stack, extended_cif *ecif);
++
++void ffi_prep_args(char *stack, extended_cif *ecif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if (ecif->cif->flags == FFI_TYPE_STRUCT)
++ {
++ *(void **) argp = ecif->rvalue;
++ argp += 4;
++ }
++
++ p_argv = ecif->avalue;
++
++ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
++ i != 0;
++ i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp)
++ argp = (char *) ALIGN(argp, sizeof(int));
++
++ z = (*p_arg)->size;
++ if (z < sizeof(int))
++ {
++ z = sizeof(int);
++ switch ((*p_arg)->type)
++ {
++ case FFI_TYPE_SINT8:
++ *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT8:
++ *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT16:
++ *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT16:
++ *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_SINT32:
++ *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_UINT32:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ case FFI_TYPE_STRUCT:
++ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
++ break;
++
++ default:
++ FFI_ASSERT(0);
++ }
++ }
++ else
++ {
++ memcpy(argp, *p_argv, z);
++ }
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* Perform machine dependent cif processing */
++ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++{
++ /* Set the return type flag */
++ switch (cif->rtype->type)
++ {
++ case FFI_TYPE_VOID:
++#ifdef X86
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_SINT16:
++#endif
++
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ cif->flags = (unsigned) cif->rtype->type;
++ break;
++
++ case FFI_TYPE_UINT64:
++ cif->flags = FFI_TYPE_SINT64;
++ break;
++
++#ifndef X86
++ case FFI_TYPE_STRUCT:
++ if (cif->rtype->size == 1)
++ {
++ cif->flags = FFI_TYPE_SINT8; /* same as char size */
++ }
++ else if (cif->rtype->size == 2)
++ {
++ cif->flags = FFI_TYPE_SINT16; /* same as short size */
++ }
++ else if (cif->rtype->size == 4)
++ {
++ cif->flags = FFI_TYPE_INT; /* same as int type */
++ }
++ else if (cif->rtype->size == 8)
++ {
++ cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
++ }
++ else
++ {
++ cif->flags = FFI_TYPE_STRUCT;
++ }
++ break;
++#endif
++
++ default:
++ cif->flags = FFI_TYPE_INT;
++ break;
++ }
++
++#ifdef X86_DARWIN
++ cif->bytes = (cif->bytes + 15) & ~0xF;
++#endif
++
++ return FFI_OK;
++}
++
++extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
++ unsigned, unsigned, unsigned *, void (*fn)());
++
++#endif /* X86_WIN32 */
++
++void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
++{
++ extended_cif ecif;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->flags == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
++ fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++
++/** private members **/
++
++static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
++ void** args, ffi_cif* cif);
++void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
++__attribute__ ((regparm(1)));
++unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
++__attribute__ ((regparm(1)));
++void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
++__attribute__ ((regparm(1)));
++
++/* This function is jumped to by the trampoline */
++
++unsigned int FFI_HIDDEN
++ffi_closure_SYSV_inner (closure, respp, args)
++ffi_closure *closure;
++void **respp;
++void *args;
++{
++ // our various things...
++ ffi_cif *cif;
++ void **arg_area;
++
++ cif = closure->cif;
++ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
++
++ /* this call will initialize ARG_AREA, such that each
++ * element in that array points to the corresponding
++ * value on the stack; and if the function returns
++ * a structure, it will re-set RESP to point to the
++ * structure return address. */
++
++ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
++
++ (closure->fun) (cif, *respp, arg_area, closure->user_data);
++
++ return cif->flags;
++}
++
++static void
++ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
++ ffi_cif *cif)
++{
++ register unsigned int i;
++ register void **p_argv;
++ register char *argp;
++ register ffi_type **p_arg;
++
++ argp = stack;
++
++ if ( cif->flags == FFI_TYPE_STRUCT ) {
++ *rvalue = *(void **) argp;
++ argp += 4;
++ }
++
++ p_argv = avalue;
++
++ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
++ {
++ size_t z;
++
++ /* Align if necessary */
++ if ((sizeof(int) - 1) & (unsigned) argp) {
++ argp = (char *) ALIGN(argp, sizeof(int));
++ }
++
++ z = (*p_arg)->size;
++
++ /* because we're little endian, this is what it turns into. */
++
++ *p_argv = (void*) argp;
++
++ p_argv++;
++ argp += z;
++ }
++
++ return;
++}
++
++/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
++
++#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
++({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
++unsigned int __fun = (unsigned int)(FUN); \
++unsigned int __ctx = (unsigned int)(CTX); \
++unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
++*(unsigned char*) &__tramp[0] = 0xb8; \
++*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
++*(unsigned char *) &__tramp[5] = 0xe9; \
++*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
++})
++
++
++/* the cif must already be prep'ed */
++ffi_status
++ffi_prep_closure (ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data)
++{
++ if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
++ &ffi_closure_SYSV, \
++ (void*)closure);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++/* ------- Native raw API support -------------------------------- */
++
++#if !FFI_NO_RAW_API
++
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc)
++{
++ int i;
++
++ FFI_ASSERT (cif->abi == FFI_SYSV);
++
++ // we currently don't support certain kinds of arguments for raw
++ // closures. This should be implemented by a separate assembly language
++ // routine, since it would require argument processing, something we
++ // don't do now for performance.
++
++ for (i = cif->nargs-1; i >= 0; i--)
++ {
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
++ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
++ }
++
++
++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
++ codeloc);
++
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
++
++ return FFI_OK;
++}
++
++static void
++ffi_prep_args_raw(char *stack, extended_cif *ecif)
++{
++ memcpy (stack, ecif->avalue, ecif->cif->bytes);
++}
++
++/* we borrow this routine from libffi (it must be changed, though, to
++ * actually call the function passed in the first argument. as of
++ * libffi-1.20, this is not the case.)
++ */
++
++extern void
++ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++
++#ifdef X86_WIN32
++extern void
++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
++ unsigned, unsigned *, void (*fn)());
++#endif /* X86_WIN32 */
++
++void
++ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
++{
++ extended_cif ecif;
++ void **avalue = (void **)fake_avalue;
++
++ ecif.cif = cif;
++ ecif.avalue = avalue;
++
++ /* If the return value is a struct and we don't have a return */
++ /* value address then we need to make one */
++
++ if ((rvalue == NULL) &&
++ (cif->rtype->type == FFI_TYPE_STRUCT))
++ {
++ ecif.rvalue = alloca(cif->rtype->size);
++ }
++ else
++ ecif.rvalue = rvalue;
++
++
++ switch (cif->abi)
++ {
++ case FFI_SYSV:
++ ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#ifdef X86_WIN32
++ case FFI_STDCALL:
++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
++ ecif.rvalue, fn);
++ break;
++#endif /* X86_WIN32 */
++ default:
++ FFI_ASSERT(0);
++ break;
++ }
++}
++
++#endif
++#endif // __i386__
+diff --git ./setup.py ./setup.py
+index 46b92fe..2bf6b4b 100644
+--- ./setup.py
++++ ./setup.py
+@@ -98,8 +98,14 @@ class PyBuildExt(build_ext):
+ self.detect_modules()
+
+ # Remove modules that are present on the disabled list
+- self.extensions = [ext for ext in self.extensions
+- if ext.name not in disabled_module_list]
++ extensions = [ext for ext in self.extensions
++ if ext.name not in disabled_module_list]
++ # move ctypes to the end, it depends on other modules
++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
++ if "_ctypes" in ext_map:
++ ctypes = extensions.pop(ext_map["_ctypes"])
++ extensions.append(ctypes)
++ self.extensions = extensions
+
+ # Fix up the autodetected modules, prefixing all the source files
+ # with Modules/ and adding Python's include directory to the path.
+@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext):
+ # *** Uncomment these for TOGL extension only:
+ # -lGL -lGLU -lXext -lXmu \
+
++ def configure_ctypes_darwin(self, ext):
++ # Darwin (OS X) uses preconfigured files, in
++ # the Modules/_ctypes/libffi_osx directory.
++ srcdir = sysconfig.get_config_var('srcdir')
++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
++ '_ctypes', 'libffi_osx'))
++ sources = [os.path.join(ffi_srcdir, p)
++ for p in ['ffi.c',
++ 'x86/darwin64.S',
++ 'x86/x86-darwin.S',
++ 'x86/x86-ffi_darwin.c',
++ 'x86/x86-ffi64.c',
++ 'powerpc/ppc-darwin.S',
++ 'powerpc/ppc-darwin_closure.S',
++ 'powerpc/ppc-ffi_darwin.c',
++ 'powerpc/ppc64-darwin_closure.S',
++ ]]
++
++ # Add .S (preprocessed assembly) to C compiler source extensions.
++ self.compiler.src_extensions.append('.S')
++
++ include_dirs = [os.path.join(ffi_srcdir, 'include'),
++ os.path.join(ffi_srcdir, 'powerpc')]
++ ext.include_dirs.extend(include_dirs)
++ ext.sources.extend(sources)
++ return True
++
+ def configure_ctypes(self, ext):
+ if not self.use_system_libffi:
+- (srcdir,) = sysconfig.get_config_vars('srcdir')
++ if sys.platform == 'darwin':
++ return self.configure_ctypes_darwin(ext)
++
++ srcdir = sysconfig.get_config_var('srcdir')
+ ffi_builddir = os.path.join(self.build_temp, 'libffi')
+ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
+ '_ctypes', 'libffi'))
+@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext):
+ ffi_configfile):
+ from distutils.dir_util import mkpath
+ mkpath(ffi_builddir)
+- config_args = []
++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
++ if (('--host=' in arg) or ('--build=' in arg))]
++ if not self.verbose:
++ config_args.append("-q")
+
+ # Pass empty CFLAGS because we'll just append the resulting
+ # CFLAGS to Python's; -g or -O2 is to be avoided.
+@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext):
+ self.compiler.src_extensions.append('.S')
+
+ include_dirs = [os.path.join(ffi_builddir, 'include'),
+- ffi_builddir, ffi_srcdir]
++ ffi_builddir,
++ os.path.join(ffi_srcdir, 'src')]
+ extra_compile_args = fficonfig['ffi_cflags'].split()
+
+- ext.sources.extend(fficonfig['ffi_sources'])
++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
++ fficonfig['ffi_sources'])
+ ext.include_dirs.extend(include_dirs)
+ ext.extra_compile_args.extend(extra_compile_args)
+ return True
+@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext):
+
+ if sys.platform == 'darwin':
+ sources.append('_ctypes/darwin/dlfcn_simple.c')
++ extra_compile_args.append('-DMACOSX')
+ include_dirs.append('_ctypes/darwin')
+ # XXX Is this still needed?
+ ## extra_link_args.extend(['-read_only_relocs', 'warning'])
+@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext):
+ if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
+ return
+
+- ffi_inc = find_file('ffi.h', [], inc_dirs)
++ if sys.platform == 'darwin':
++ # OS X 10.5 comes with libffi.dylib; the include files are
++ # in /usr/include/ffi
++ inc_dirs.append('/usr/include/ffi')
++
++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
++ if not ffi_inc or ffi_inc[0] == '':
++ ffi_inc = find_file('ffi.h', [], inc_dirs)
+ if ffi_inc is not None:
+ ffi_h = ffi_inc[0] + '/ffi.h'
+ fp = open(ffi_h)
diff --git a/plugins/python-build/share/python-build/patches/2.5.5/Python-2.5.5/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.5/Python-2.5.5/004_osx_libffi.patch
new file mode 100644
index 00000000..cd500771
--- /dev/null
+++ b/plugins/python-build/share/python-build/patches/2.5.5/Python-2.5.5/004_osx_libffi.patch
@@ -0,0 +1,6881 @@
+diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE
+new file mode 100644
+index 0000000..f591795
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README
+new file mode 100644
+index 0000000..1fc2747
+--- /dev/null
++++ ./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: .
++
++
++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
++ #include
++
++ 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
++.
++
++
++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
++ .
++
++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 .
++
++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 . Further enhancements were
++made by Gordon Irlam at Cygnus Solutions .
++
++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 ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc
+new file mode 100644
+index 0000000..405d85f
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c
+new file mode 100644
+index 0000000..bf42093
+--- /dev/null
++++ ./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
++#include
++
++#include
++#include
++
++/* 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 ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h
+new file mode 100644
+index 0000000..c104a5c
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/include/ffi.h
+@@ -0,0 +1,355 @@
++/* -----------------------------------------------------------------*-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
++#include
++
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# endif
++#endif
++
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++#error "char size not supported"
++#endif
++
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
++#else
++#error "short size not supported"
++#endif
++
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++#error "int size not supported"
++#endif
++
++#define ffi_type_ulong ffi_type_uint64
++#define ffi_type_slong ffi_type_sint64
++
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != 9223372036854775807
++# error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != 9223372036854775807
++#error "long size not supported"
++#endif
++
++/* The closure code assumes that this works on pointers, i.e. a size_t
++ can hold a pointer. */
++
++typedef struct _ffi_type {
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++/*@null@*/ struct _ffi_type** elements;
++} ffi_type;
++
++/* These are defined in types.c */
++extern ffi_type ffi_type_void;
++extern ffi_type ffi_type_uint8;
++extern ffi_type ffi_type_sint8;
++extern ffi_type ffi_type_uint16;
++extern ffi_type ffi_type_sint16;
++extern ffi_type ffi_type_uint32;
++extern ffi_type ffi_type_sint32;
++extern ffi_type ffi_type_uint64;
++extern ffi_type ffi_type_sint64;
++extern ffi_type ffi_type_float;
++extern ffi_type ffi_type_double;
++extern ffi_type ffi_type_longdouble;
++extern ffi_type ffi_type_pointer;
++
++typedef enum ffi_status {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
++
++typedef unsigned FFI_TYPE;
++
++typedef struct ffi_cif {
++ ffi_abi abi;
++ unsigned nargs;
++/*@dependent@*/ ffi_type** arg_types;
++/*@dependent@*/ ffi_type* rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
++
++/* ---- Definitions for the raw API -------------------------------------- */
++
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == 9223372036854775807
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
++
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
++
++void
++ffi_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_raw_size(
++ ffi_cif* cif);
++
++/* This is analogous to the raw API, except it uses Java parameter
++ packing, even on 64-bit machines. I.e. on 64-bit machines
++ longs and doubles are followed by an empty 64-bit word. */
++void
++ffi_java_raw_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ ffi_raw* avalue);
++
++void
++ffi_java_ptrarray_to_raw(
++ ffi_cif* cif,
++ void** args,
++ ffi_raw* raw);
++
++void
++ffi_java_raw_to_ptrarray(
++ ffi_cif* cif,
++ ffi_raw* raw,
++ void** args);
++
++size_t
++ffi_java_raw_size(
++ ffi_cif* cif);
++
++/* ---- Definitions for closures ----------------------------------------- */
++
++#if FFI_CLOSURES
++
++typedef struct ffi_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void* user_data;
++} ffi_closure;
++
++ffi_status
++ffi_prep_closure(
++ ffi_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void* user_data);
++
++void ffi_closure_free(void *);
++void *ffi_closure_alloc (size_t size, void **code);
++
++typedef struct ffi_raw_closure {
++ char tramp[FFI_TRAMPOLINE_SIZE];
++ ffi_cif* cif;
++
++#if !FFI_NATIVE_RAW_API
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void* this_closure;
++#endif
++
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void* user_data;
++} ffi_raw_closure;
++
++ffi_status
++ffi_prep_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++ffi_status
++ffi_prep_java_raw_closure(
++ ffi_raw_closure* closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void* user_data);
++
++#endif // FFI_CLOSURES
++
++/* ---- Public interface definition -------------------------------------- */
++
++ffi_status
++ffi_prep_cif(
++/*@out@*/ /*@partial@*/ ffi_cif* cif,
++ ffi_abi abi,
++ unsigned int nargs,
++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
++/*@dependent@*/ ffi_type** atypes);
++
++void
++ffi_call(
++/*@dependent@*/ ffi_cif* cif,
++ void (*fn)(void),
++/*@out@*/ void* rvalue,
++/*@dependent@*/ void** avalue);
++
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
++
++#endif // #ifndef LIBFFI_ASM
++/* ---- Definitions shared with assembly code ---------------------------- */
++
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++
++#ifdef HAVE_LONG_DOUBLE
++# define FFI_TYPE_LONGDOUBLE 4
++#else
++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_POINTER
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif // #ifndef LIBFFI_H
+diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h
+new file mode 100644
+index 0000000..685a358
+--- /dev/null
++++ ./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
++# 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
++#else
++# ifndef HAVE_MEMCPY
++# define memcpy(d, s, n) bcopy((s), (d), (n))
++# endif
++#endif
++
++/*#if defined(FFI_DEBUG)
++#include
++#endif*/
++
++#ifdef FFI_DEBUG
++#include
++
++/*@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 ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h
+new file mode 100644
+index 0000000..2172490
+--- /dev/null
++++ ./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 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 ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h
+new file mode 100644
+index 0000000..faaa30d
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
+new file mode 100644
+index 0000000..2318421
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
+new file mode 100644
+index 0000000..55c2b6c
+--- /dev/null
++++ ./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 ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+new file mode 100644
+index 0000000..f143dbd
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
+@@ -0,0 +1,365 @@
++#if defined(__ppc__) || defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist
++ Copyright (c) 2004 Free Software Foundation, Inc.
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include
++#include
++#include
++
++.text
++ .align 2
++.globl _ffi_prep_args
++
++.text
++ .align 2
++.globl _ffi_call_DARWIN
++
++.text
++ .align 2
++_ffi_call_DARWIN:
++LFB0:
++ mr r12,r8 /* We only need r12 until the call,
++ so it doesn't have to be saved. */
++
++LFB1:
++ /* Save the old stack pointer as AP. */
++ mr r8,r1
++
++LCFI0:
++#if defined(__ppc64__)
++ /* Allocate the stack space we need.
++ r4 (size of input data)
++ 48 bytes (linkage area)
++ 40 bytes (saved registers)
++ 8 bytes (extra FPR)
++ r4 + 96 bytes total
++ */
++
++ addi r4,r4,-96 // Add our overhead.
++ li r0,-32 // Align to 32 bytes.
++ and r4,r4,r0
++#endif
++ stgux r1,r1,r4 // Grow the stack.
++ mflr r9
++
++ /* Save registers we use. */
++#if defined(__ppc64__)
++ std r27,-40(r8)
++#endif
++ stg r28,MODE_CHOICE(-16,-32)(r8)
++ stg r29,MODE_CHOICE(-12,-24)(r8)
++ stg r30,MODE_CHOICE(-8,-16)(r8)
++ stg r31,MODE_CHOICE(-4,-8)(r8)
++ stg r9,SF_RETURN(r8) /* return address */
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ stg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++LCFI1:
++#if defined(__ppc64__)
++ mr r27,r3 // our extended_cif
++#endif
++ /* Save arguments over call. */
++ mr r31,r5 /* flags, */
++ mr r30,r6 /* rvalue, */
++ mr r29,r7 /* function address, */
++ mr r28,r8 /* our AP. */
++
++LCFI2:
++ /* Call ffi_prep_args. */
++ mr r4,r1
++ li r9,0
++ mtctr r12 /* r12 holds address of _ffi_prep_args. */
++ bctrl
++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
++ lg r2,MODE_CHOICE(20,40)(r1)
++#endif
++
++ /* Now do the call.
++ Set up cr1 with bits 4-7 of the flags. */
++ mtcrf 0x40,r31
++
++ /* Load all those argument registers.
++ We have set up a nice stack frame, just load it into registers. */
++ lg r3,SF_ARG1(r1)
++ lg r4,SF_ARG2(r1)
++ lg r5,SF_ARG3(r1)
++ lg r6,SF_ARG4(r1)
++ nop
++ lg r7,SF_ARG5(r1)
++ lg r8,SF_ARG6(r1)
++ lg r9,SF_ARG7(r1)
++ lg r10,SF_ARG8(r1)
++
++ /* Load all the FP registers. */
++ bf 6,L2 /* No floats to load. */
++#if defined(__ppc64__)
++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#elif defined(__ppc__)
++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
++ nop
++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
++ nop
++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
++ nop
++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
++#else
++#error undefined architecture
++#endif
++
++L2:
++ mr r12,r29 // Put the target address in r12 as specified.
++ mtctr r12 // Get the address to call into CTR.
++ nop
++ nop
++ bctrl // Make the call.
++
++ // Deal with the return value.
++#if defined(__ppc64__)
++ mtcrf 0x3,r31 // flags in cr6 and cr7
++ bt 27,L(st_return_value)
++#elif defined(__ppc__)
++ mtcrf 0x1,r31 // flags in cr7
++#else
++#error undefined architecture
++#endif
++
++ bt 30,L(done_return_value)
++ bt 29,L(fp_return_value)
++ stg r3,0(r30)
++#if defined(__ppc__)
++ bf 28,L(done_return_value) // Store the second long if necessary.
++ stg r4,4(r30)
++#endif
++ // Fall through
++
++L(done_return_value):
++ lg r1,0(r1) // Restore stack pointer.
++ // Restore the registers we used.
++ lg r9,SF_RETURN(r1) // return address
++ lg r31,MODE_CHOICE(-4,-8)(r1)
++ mtlr r9
++ lg r30,MODE_CHOICE(-8,-16)(r1)
++ lg r29,MODE_CHOICE(-12,-24)(r1)
++ lg r28,MODE_CHOICE(-16,-32)(r1)
++#if defined(__ppc64__)
++ ld r27,-40(r1)
++#endif
++ blr
++
++#if defined(__ppc64__)
++L(st_return_value):
++ // Grow the stack enough to fit the registers. Leave room for 8 args
++ // to trample the 1st 8 slots in param area.
++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
++
++ // Store GPRs
++ std r3,SF_ARG9(r1)
++ std r4,SF_ARG10(r1)
++ std r5,SF_ARG11(r1)
++ std r6,SF_ARG12(r1)
++ nop
++ std r7,SF_ARG13(r1)
++ std r8,SF_ARG14(r1)
++ std r9,SF_ARG15(r1)
++ std r10,SF_ARG16(r1)
++
++ // Store FPRs
++ nop
++ bf 26,L(call_struct_to_ram_form)
++ stfd f1,SF_ARG17(r1)
++ stfd f2,SF_ARG18(r1)
++ stfd f3,SF_ARG19(r1)
++ stfd f4,SF_ARG20(r1)
++ nop
++ stfd f5,SF_ARG21(r1)
++ stfd f6,SF_ARG22(r1)
++ stfd f7,SF_ARG23(r1)
++ stfd f8,SF_ARG24(r1)
++ nop
++ stfd f9,SF_ARG25(r1)
++ stfd f10,SF_ARG26(r1)
++ stfd f11,SF_ARG27(r1)
++ stfd f12,SF_ARG28(r1)
++ nop
++ stfd f13,SF_ARG29(r1)
++
++L(call_struct_to_ram_form):
++ ld r3,0(r27) // extended_cif->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ addi r4,r1,SF_ARG9 // stored GPRs
++ addi r6,r1,SF_ARG17 // stored FPRs
++ li r5,0 // GPR size ptr (NULL)
++ li r7,0 // FPR size ptr (NULL)
++ li r8,0 // FPR count ptr (NULL)
++ li r10,0 // struct offset (NULL)
++ mr r9,r30 // return area
++ bl Lffi64_struct_to_ram_form$stub
++ lg r1,0(r1) // Restore stack pointer.
++ b L(done_return_value)
++#endif
++
++L(fp_return_value):
++ /* Do we have long double to store? */
++ bf 31,L(fd_return_value)
++ stfd f1,0(r30)
++ stfd f2,8(r30)
++ b L(done_return_value)
++
++L(fd_return_value):
++ /* Do we have double to store? */
++ bf 28,L(float_return_value)
++ stfd f1,0(r30)
++ b L(done_return_value)
++
++L(float_return_value):
++ /* We only have a float to store. */
++ stfs f1,0(r30)
++ b L(done_return_value)
++
++LFE1:
++/* END(_ffi_call_DARWIN) */
++
++/* Provide a null definition of _ffi_call_AIX. */
++.text
++ .align 2
++.globl _ffi_call_AIX
++.text
++ .align 2
++_ffi_call_AIX:
++ blr
++/* END(_ffi_call_AIX) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_call_DARWIN.eh
++_ffi_call_DARWIN.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB0-. ; FDE initial location
++ .set L$set$3,LFE1-LFB0
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x08 ; uleb128 0x08
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$5,LCFI1-LCFI0
++ .long L$set$5
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .byte 0x9f ; DW_CFA_offset, column 0x1f
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x9e ; DW_CFA_offset, column 0x1e
++ .byte 0x2 ; uleb128 0x2
++ .byte 0x9d ; DW_CFA_offset, column 0x1d
++ .byte 0x3 ; uleb128 0x3
++ .byte 0x9c ; DW_CFA_offset, column 0x1c
++ .byte 0x4 ; uleb128 0x4
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$6,LCFI2-LCFI1
++ .long L$set$6
++ .byte 0xd ; DW_CFA_def_cfa_register
++ .byte 0x1c ; uleb128 0x1c
++ .align LOG2_GPR_BYTES
++LEFDE1:
++
++#if defined(__ppc64__)
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_ram_form$stub:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_ram_form
++
++LO$ffi64_struct_to_ram_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_ram_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_ram_form
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
++#endif // __ppc__ || __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+new file mode 100644
+index 0000000..cf4bd50
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
+@@ -0,0 +1,85 @@
++/* -----------------------------------------------------------------------
++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define L(x) x
++
++#define SF_ARG9 MODE_CHOICE(56,112)
++#define SF_ARG10 MODE_CHOICE(60,120)
++#define SF_ARG11 MODE_CHOICE(64,128)
++#define SF_ARG12 MODE_CHOICE(68,136)
++#define SF_ARG13 MODE_CHOICE(72,144)
++#define SF_ARG14 MODE_CHOICE(76,152)
++#define SF_ARG15 MODE_CHOICE(80,160)
++#define SF_ARG16 MODE_CHOICE(84,168)
++#define SF_ARG17 MODE_CHOICE(88,176)
++#define SF_ARG18 MODE_CHOICE(92,184)
++#define SF_ARG19 MODE_CHOICE(96,192)
++#define SF_ARG20 MODE_CHOICE(100,200)
++#define SF_ARG21 MODE_CHOICE(104,208)
++#define SF_ARG22 MODE_CHOICE(108,216)
++#define SF_ARG23 MODE_CHOICE(112,224)
++#define SF_ARG24 MODE_CHOICE(116,232)
++#define SF_ARG25 MODE_CHOICE(120,240)
++#define SF_ARG26 MODE_CHOICE(124,248)
++#define SF_ARG27 MODE_CHOICE(128,256)
++#define SF_ARG28 MODE_CHOICE(132,264)
++#define SF_ARG29 MODE_CHOICE(136,272)
++
++#define ASM_NEEDS_REGISTERS 4
++#define NUM_GPR_ARG_REGISTERS 8
++#define NUM_FPR_ARG_REGISTERS 13
++
++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
++#define FFI_TYPE_4_BYTE(x) \
++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
++
++#if !defined(LIBFFI_ASM)
++
++enum {
++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
++ FLAG_RETURNS_FP = 1 << (31 - 29),
++ FLAG_RETURNS_64BITS = 1 << (31 - 28),
++ FLAG_RETURNS_128BITS = 1 << (31 - 31),
++
++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
++
++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
++};
++
++#if defined(__ppc64__)
++void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
++ const char*, unsigned int*, unsigned int*, char*, unsigned int*);
++void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
++ unsigned int*, char*, unsigned int*, char*, unsigned int*);
++bool ffi64_stret_needs_ptr(const ffi_type* inType,
++ unsigned short*, unsigned short*);
++#endif
++
++#endif // !defined(LIBFFI_ASM)
+\ No newline at end of file
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+new file mode 100644
+index 0000000..c3d30c2
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
+@@ -0,0 +1,308 @@
++#if defined(__ppc__)
++
++/* -----------------------------------------------------------------------
++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0 // Save return address
++ stg r0,SF_RETURN(r1)
++
++LCFI0:
++ /* 24/48 bytes (Linkage Area)
++ 32/64 bytes (outgoing parameter area, always reserved)
++ 104 bytes (13*8 from FPR)
++ 16/32 bytes (result)
++ 176/232 total bytes */
++
++ /* skip over caller save area and keep stack aligned to 16/32. */
++ stgu r1,-SF_ROUND(176)(r1)
++
++LCFI1:
++ /* We want to build up an area for the parameters passed
++ in registers. (both floating point and integer) */
++
++ /* 176/256 bytes (callee stack frame aligned to 16/32)
++ 24/48 bytes (caller linkage area)
++ 200/304 (start of caller parameter area aligned to 4/8)
++ */
++
++ /* Save GPRs 3 - 10 (aligned to 4/8)
++ in the parents outgoing area. */
++ stg r3,200(r1)
++ stg r4,204(r1)
++ stg r5,208(r1)
++ stg r6,212(r1)
++ stg r7,216(r1)
++ stg r8,220(r1)
++ stg r9,224(r1)
++ stg r10,228(r1)
++
++ /* Save FPRs 1 - 13. (aligned to 8) */
++ stfd f1,56(r1)
++ stfd f2,64(r1)
++ stfd f3,72(r1)
++ stfd f4,80(r1)
++ stfd f5,88(r1)
++ stfd f6,96(r1)
++ stfd f7,104(r1)
++ stfd f8,112(r1)
++ stfd f9,120(r1)
++ stfd f10,128(r1)
++ stfd f11,136(r1)
++ stfd f12,144(r1)
++ stfd f13,152(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,160 // result storage
++ addi r5,r1,200 // saved GPRs
++ addi r6,r1,56 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ /* Now r3 contains the return type. Use it to look up in a table
++ so we know how to deal with each type. */
++ addi r5,r1,160 // Copy result storage pointer.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ (4 instructions). For cache effectiveness we align to a 16 byte boundary
++ first. */
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++/* case FFI_TYPE_VOID */
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* case FFI_TYPE_INT */
++Lret_type1:
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_FLOAT */
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_DOUBLE */
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_LONGDOUBLE */
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT8 */
++Lret_type5:
++ lbz r3,3(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT8 */
++Lret_type6:
++ lbz r3,3(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_UINT16 */
++Lret_type7:
++ lhz r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT16 */
++Lret_type8:
++ lha r3,2(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT32 */
++Lret_type9: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_SINT32 */
++Lret_type10: // same as Lret_type1
++ lwz r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++/* case FFI_TYPE_UINT64 */
++Lret_type11:
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_SINT64 */
++Lret_type12: // same as Lret_type11
++ lwz r3,0(r5)
++ lwz r4,4(r5)
++ b Lfinish
++ nop
++
++/* case FFI_TYPE_STRUCT */
++Lret_type13:
++ b Lfinish
++ nop
++ nop
++ nop
++
++/* End 16-byte aligned cases */
++/* case FFI_TYPE_POINTER */
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ // fall through
++
++/* case done */
++Lfinish:
++ addi r1,r1,SF_ROUND(176) // Restore stack pointer.
++ lg r0,SF_RETURN(r1) // Restore return address.
++ mtlr r0 // Restore link register.
++ blr
++
++/* END(ffi_closure_ASM) */
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++
++#endif // __ppc__
+diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+new file mode 100644
+index 0000000..8953d5f
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
+@@ -0,0 +1,1776 @@
++#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
++#include
++
++#include
++#include
++#include
++#include
++#include
++
++#if 0
++#if defined(POWERPC_DARWIN)
++#include // for sys_icache_invalidate()
++#endif
++
++#else
++
++#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)
++ 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
++
++typedef union
++{
++ float f;
++ double d;
++} ffi_dblfl;
++
++/* 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;
++ long 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] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
++ else
++ avalue[i] = (void*)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(temp_ld.lb[0]));
++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
++ 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 ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+new file mode 100644
+index 0000000..7162fa1
+--- /dev/null
++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
+@@ -0,0 +1,418 @@
++#if defined(__ppc64__)
++
++/* -----------------------------------------------------------------------
++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
++ Inc. based on ppc_closure.S
++
++ PowerPC Assembly glue.
++
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
++
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ OTHER DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
++
++#define LIBFFI_ASM
++
++#include
++#include // for FFI_TRAMPOLINE_SIZE
++#include
++#include
++
++ .file "ppc64-darwin_closure.S"
++.text
++ .align LOG2_GPR_BYTES
++ .globl _ffi_closure_ASM
++
++.text
++ .align LOG2_GPR_BYTES
++
++_ffi_closure_ASM:
++LFB1:
++ mflr r0
++ stg r0,SF_RETURN(r1) // save return address
++
++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
++ stg r3,SF_ARG1(r1)
++ stg r4,SF_ARG2(r1)
++ stg r5,SF_ARG3(r1)
++ stg r6,SF_ARG4(r1)
++ stg r7,SF_ARG5(r1)
++ stg r8,SF_ARG6(r1)
++ stg r9,SF_ARG7(r1)
++ stg r10,SF_ARG8(r1)
++
++LCFI0:
++/* 48 bytes (Linkage Area)
++ 64 bytes (outgoing parameter area, always reserved)
++ 112 bytes (14*8 for incoming FPR)
++ ? bytes (result)
++ 112 bytes (14*8 for outgoing FPR)
++ 16 bytes (2 saved registers)
++ 352 + ? total bytes
++*/
++
++ std r31,-8(r1) // Save registers we use.
++ std r30,-16(r1)
++ mr r30,r1 // Save the old SP.
++ mr r31,r11 // Save the ffi_closure around ffi64_data_size.
++
++ // Calculate the space we need.
++ stdu r1,-SF_MINSIZE(r1)
++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r3) // ffi_cif->rtype*
++ bl Lffi64_data_size$stub
++ ld r1,0(r1)
++
++ addi r3,r3,352 // Add our overhead.
++ neg r3,r3
++ li r0,-32 // Align to 32 bytes.
++ and r3,r3,r0
++ stdux r1,r1,r3 // Grow the stack.
++
++ mr r11,r31 // Copy the ffi_closure back.
++
++LCFI1:
++ // We want to build up an area for the parameters passed
++ // in registers. (both floating point and integer)
++
++/* 320 bytes (callee stack frame aligned to 32)
++ 48 bytes (caller linkage area)
++ 368 (start of caller parameter area aligned to 8)
++*/
++
++ // Save FPRs 1 - 14. (aligned to 8)
++ stfd f1,112(r1)
++ stfd f2,120(r1)
++ stfd f3,128(r1)
++ stfd f4,136(r1)
++ stfd f5,144(r1)
++ stfd f6,152(r1)
++ stfd f7,160(r1)
++ stfd f8,168(r1)
++ stfd f9,176(r1)
++ stfd f10,184(r1)
++ stfd f11,192(r1)
++ stfd f12,200(r1)
++ stfd f13,208(r1)
++ stfd f14,216(r1)
++
++ // Set up registers for the routine that actually does the work.
++ mr r3,r11 // context pointer from the trampoline
++ addi r4,r1,224 // result storage
++ addi r5,r30,SF_ARG1 // saved GPRs
++ addi r6,r1,112 // saved FPRs
++ bl Lffi_closure_helper_DARWIN$stub
++
++ // Look the proper starting point in table
++ // by using return type as an offset.
++ addi r5,r1,224 // Get pointer to results area.
++ bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
++ mflr r4 // Move to r4.
++ slwi r3,r3,4 // Now multiply return type by 16.
++ add r3,r3,r4 // Add contents of table to table address.
++ mtctr r3
++ bctr
++
++LFE1:
++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long
++ // (4 instructions). For cache effectiveness we align to a 16 byte
++ // boundary first.
++ .align 4
++ nop
++ nop
++ nop
++
++Lget_ret_type0_addr:
++ blrl
++
++// case FFI_TYPE_VOID
++Lret_type0:
++ b Lfinish
++ nop
++ nop
++ nop
++
++// case FFI_TYPE_INT
++Lret_type1:
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_FLOAT
++Lret_type2:
++ lfs f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_DOUBLE
++Lret_type3:
++ lfd f1,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_LONGDOUBLE
++Lret_type4:
++ lfd f1,0(r5)
++ lfd f2,8(r5)
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT8
++Lret_type5:
++ lbz r3,7(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT8
++Lret_type6:
++ lbz r3,7(r5)
++ extsb r3,r3
++ b Lfinish
++ nop
++
++// case FFI_TYPE_UINT16
++Lret_type7:
++ lhz r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT16
++Lret_type8:
++ lha r3,6(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT32
++Lret_type9: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT32
++Lret_type10: // same as Lret_type1
++ lwz r3,4(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_UINT64
++Lret_type11:
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_SINT64
++Lret_type12: // same as Lret_type11
++ ld r3,0(r5)
++ b Lfinish
++ nop
++ nop
++
++// case FFI_TYPE_STRUCT
++Lret_type13:
++ b Lret_struct
++ nop
++ nop
++ nop
++
++// ** End 16-byte aligned cases **
++// case FFI_TYPE_POINTER
++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
++// are added in future, the following code will need to be updated and
++// padded to 16 bytes.
++Lret_type14:
++ lg r3,0(r5)
++ b Lfinish
++
++// copy struct into registers
++Lret_struct:
++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
++ ld r3,16(r31) // ffi_cif->rtype*
++ ld r31,24(r31) // ffi_cif->flags
++ mr r4,r5 // copy struct* to 2nd arg
++ addi r7,r1,SF_ARG9 // GPR return area
++ addi r9,r30,-16-(14*8) // FPR return area
++ li r5,0 // struct offset ptr (NULL)
++ li r6,0 // FPR used count ptr (NULL)
++ li r8,0 // GPR return area size ptr (NULL)
++ li r10,0 // FPR return area size ptr (NULL)
++ bl Lffi64_struct_to_reg_form$stub
++
++ // Load GPRs
++ ld r3,SF_ARG9(r1)
++ ld r4,SF_ARG10(r1)
++ ld r5,SF_ARG11(r1)
++ ld r6,SF_ARG12(r1)
++ nop
++ ld r7,SF_ARG13(r1)
++ ld r8,SF_ARG14(r1)
++ ld r9,SF_ARG15(r1)
++ ld r10,SF_ARG16(r1)
++ nop
++
++ // Load FPRs
++ mtcrf 0x2,r31
++ bf 26,Lfinish
++ lfd f1,-16-(14*8)(r30)
++ lfd f2,-16-(13*8)(r30)
++ lfd f3,-16-(12*8)(r30)
++ lfd f4,-16-(11*8)(r30)
++ nop
++ lfd f5,-16-(10*8)(r30)
++ lfd f6,-16-(9*8)(r30)
++ lfd f7,-16-(8*8)(r30)
++ lfd f8,-16-(7*8)(r30)
++ nop
++ lfd f9,-16-(6*8)(r30)
++ lfd f10,-16-(5*8)(r30)
++ lfd f11,-16-(4*8)(r30)
++ lfd f12,-16-(3*8)(r30)
++ nop
++ lfd f13,-16-(2*8)(r30)
++ lfd f14,-16-(1*8)(r30)
++ // Fall through
++
++// case done
++Lfinish:
++ lg r1,0(r1) // Restore stack pointer.
++ ld r31,-8(r1) // Restore registers we used.
++ ld r30,-16(r1)
++ lg r0,SF_RETURN(r1) // Get return address.
++ mtlr r0 // Reset link register.
++ blr
++
++// END(ffi_closure_ASM)
++
++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
++EH_frame1:
++ .set L$set$0,LECIE1-LSCIE1
++ .long L$set$0 ; Length of Common Information Entry
++LSCIE1:
++ .long 0x0 ; CIE Identifier Tag
++ .byte 0x1 ; CIE Version
++ .ascii "zR\0" ; CIE Augmentation
++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
++ .byte 0x41 ; CIE RA Column
++ .byte 0x1 ; uleb128 0x1; Augmentation size
++ .byte 0x10 ; FDE Encoding (pcrel)
++ .byte 0xc ; DW_CFA_def_cfa
++ .byte 0x1 ; uleb128 0x1
++ .byte 0x0 ; uleb128 0x0
++ .align LOG2_GPR_BYTES
++LECIE1:
++.globl _ffi_closure_ASM.eh
++_ffi_closure_ASM.eh:
++LSFDE1:
++ .set L$set$1,LEFDE1-LASFDE1
++ .long L$set$1 ; FDE Length
++
++LASFDE1:
++ .long LASFDE1-EH_frame1 ; FDE CIE offset
++ .g_long LFB1-. ; FDE initial location
++ .set L$set$3,LFE1-LFB1
++ .g_long L$set$3 ; FDE address range
++ .byte 0x0 ; uleb128 0x0; Augmentation size
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$3,LCFI1-LCFI0
++ .long L$set$3
++ .byte 0xe ; DW_CFA_def_cfa_offset
++ .byte 176,1 ; uleb128 176
++ .byte 0x4 ; DW_CFA_advance_loc4
++ .set L$set$4,LCFI0-LFB1
++ .long L$set$4
++ .byte 0x11 ; DW_CFA_offset_extended_sf
++ .byte 0x41 ; uleb128 0x41
++ .byte 0x7e ; sleb128 -2
++ .align LOG2_GPR_BYTES
++
++LEFDE1:
++.data
++ .align LOG2_GPR_BYTES
++LDFCM0:
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi_closure_helper_DARWIN$stub:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ mflr r0
++ bcl 20,31,LO$ffi_closure_helper_DARWIN
++
++LO$ffi_closure_helper_DARWIN:
++ mflr r11
++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
++ mtlr r0
++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi_closure_helper_DARWIN$lazy_ptr:
++ .indirect_symbol _ffi_closure_helper_DARWIN
++ .g_long dyld_stub_binding_helper
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_struct_to_reg_form$stub:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ mflr r0
++ bcl 20,31,LO$ffi64_struct_to_reg_form
++
++LO$ffi64_struct_to_reg_form:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
++ mtctr r12
++ bctr
++
++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
++ .align LOG2_GPR_BYTES
++
++Lffi64_data_size$stub:
++ .indirect_symbol _ffi64_data_size
++ mflr r0
++ bcl 20,31,LO$ffi64_data_size
++
++LO$ffi64_data_size:
++ mflr r11
++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
++ mtlr r0
++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
++ mtctr r12
++ bctr
++
++.lazy_symbol_pointer
++L_ffi64_struct_to_reg_form$lazy_ptr:
++ .indirect_symbol _ffi64_struct_to_reg_form
++ .g_long dyld_stub_binding_helper
++
++L_ffi64_data_size$lazy_ptr:
++ .indirect_symbol _ffi64_data_size
++ .g_long dyld_stub_binding_helper
++
++#endif // __ppc64__
+diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c
+new file mode 100644
+index 0000000..44806ae
+--- /dev/null
++++ ./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