[Python-checkins] r61230 - in python/branches/libffi3-branch: Modules/_ctypes/libffi_osx Modules/_ctypes/libffi_osx/LICENSE Modules/_ctypes/libffi_osx/README Modules/_ctypes/libffi_osx/README.pyobjc Modules/_ctypes/libffi_osx/ffi.c Modules/_ctypes/libffi_osx/include Modules/_ctypes/libffi_osx/include/ffi Modules/_ctypes/libffi_osx/include/ffi.h Modules/_ctypes/libffi_osx/include/ffi_common.h Modules/_ctypes/libffi_osx/include/fficonfig.h Modules/_ctypes/libffi_osx/include/ffitarget.h Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h Modules/_ctypes/libffi_osx/include/x86-ffitarget.h Modules/_ctypes/libffi_osx/powerpc Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S Modules/_ctypes/libffi_osx/types.c Modules/_ctypes/libffi_osx/x86 Modules/_ctypes/libffi_osx/x86/darwin64.S Modules/_ctypes/libffi_osx/x86/x86-darwin.S Modules/_ctypes/libffi_osx/x86/x86-ffi64.c Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c setup.py

thomas.heller python-checkins at python.org
Tue Mar 4 14:25:43 CET 2008


Author: thomas.heller
Date: Tue Mar  4 14:25:41 2008
New Revision: 61230

Added:
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/LICENSE
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/README
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/README.pyobjc
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/ffi.c
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ffi/
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ffi.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ffi_common.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/fficonfig.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ffitarget.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/types.c
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/darwin64.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-darwin.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c
   python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
Modified:
   python/branches/libffi3-branch/setup.py
Log:
I gave up on using libffi3 files on os x.
Instead, static configuration with files from pyobjc is used.

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/LICENSE
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/LICENSE	Tue Mar  4 14:25:41 2008
@@ -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.

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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/README.pyobjc
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/README.pyobjc	Tue Mar  4 14:25:41 2008
@@ -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.

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

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

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

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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ffitarget.h
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ffitarget.h	Tue Mar  4 14:25:41 2008
@@ -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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h	Tue Mar  4 14:25:41 2008
@@ -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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/x86-ffitarget.h
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/include/x86-ffitarget.h	Tue Mar  4 14:25:41 2008
@@ -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

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

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

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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c	Tue Mar  4 14:25:41 2008
@@ -0,0 +1,1775 @@
+#if defined(__ppc__) || defined(__ppc64__)
+
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Foreign Function Interface
+
+   Darwin ABI support (c) 2001 John Hornkvist
+   AIX ABI support (c) 2002 Free Software Foundation, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include "ffi.h"
+#include "ffi_common.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "ppc-darwin.h"
+#include <architecture/ppc/mode_independent_asm.h>
+
+#if 0
+#if defined(POWERPC_DARWIN)
+#include <libkern/OSCacheControl.h>	// for sys_icache_invalidate()
+#endif
+
+#else 
+
+/* Explicit prototype instead of including a header to allow compilation
+ * on Tiger systems.
+ */
+
+#pragma weak sys_icache_invalidate
+extern void sys_icache_invalidate(void *start, size_t len);
+
+#endif
+
+extern void ffi_closure_ASM(void);
+
+// The layout of a function descriptor.  A C function pointer really
+// points to one of these.
+typedef struct aix_fd_struct {
+  void*	code_pointer;
+  void*	toc;
+} aix_fd;
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+
+   The stack layout we want looks like this:
+
+   |   Return address from ffi_call_DARWIN      |	higher addresses
+   |--------------------------------------------|
+   |   Previous backchain pointer      4/8      |	    stack pointer here
+   |--------------------------------------------|-\ <<< on entry to
+   |   Saved r28-r31                 (4/8)*4    | |	    ffi_call_DARWIN
+   |--------------------------------------------| |
+   |   Parameters      (at least 8*(4/8)=32/64) | | (176) +112 - +288
+   |--------------------------------------------| |
+   |   Space for GPR2                  4/8      | |
+   |--------------------------------------------| |	stack	|
+   |   Reserved						 (4/8)*2    | |	grows	|
+   |--------------------------------------------| |	down	V
+   |   Space for callee's LR           4/8      | |
+   |--------------------------------------------| |	lower addresses
+   |   Saved CR                        4/8      | |
+   |--------------------------------------------| |     stack pointer here
+   |   Current backchain pointer       4/8      | |     during
+   |--------------------------------------------|-/ <<< ffi_call_DARWIN
+
+	Note: ppc64 CR is saved in the low word of a long on the stack.
+*/
+
+/*@-exportheader@*/
+void
+ffi_prep_args(
+	extended_cif*	inEcif,
+	unsigned *const	stack)
+/*@=exportheader@*/
+{
+	/*	Copy the ecif to a local var so we can trample the arg.
+		BC note: test this with GP later for possible problems...	*/
+	volatile extended_cif*	ecif	= inEcif;
+
+	const unsigned bytes	= ecif->cif->bytes;
+	const unsigned flags	= ecif->cif->flags;
+
+	/*	Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode
+		and 8 in 64-bit mode.	*/
+	unsigned long *const longStack	= (unsigned long *const)stack;
+
+	/* 'stacktop' points at the previous backchain pointer.	*/
+#if defined(__ppc64__)
+	//	In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area,
+	//	saved registers, and an extra FPR.
+	unsigned long *const stacktop	=
+		(unsigned long *)(unsigned long)((char*)longStack + bytes + 96);
+#elif defined(__ppc__)
+	unsigned long *const stacktop	= longStack + (bytes / sizeof(long));
+#else
+#error undefined architecture
+#endif
+
+	/* 'fpr_base' points at the space for fpr1, and grows upwards as
+		we use FPR registers.  */
+	double*		fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) -
+		NUM_FPR_ARG_REGISTERS;
+
+#if defined(__ppc64__)
+	//	64-bit saves an extra register, and uses an extra FPR. Knock fpr_base
+	//	down a couple pegs.
+	fpr_base -= 2;
+#endif
+
+	unsigned int	fparg_count = 0;
+
+	/* 'next_arg' grows up as we put parameters in it.  */
+	unsigned long*	next_arg = longStack + 6; /* 6 reserved positions.  */
+
+	int				i;
+	double			double_tmp;
+	void**			p_argv = ecif->avalue;
+	unsigned long	gprvalue;
+	ffi_type**		ptr = ecif->cif->arg_types;
+
+	/* Check that everything starts aligned properly.  */
+	FFI_ASSERT(stack == SF_ROUND(stack));
+	FFI_ASSERT(stacktop == SF_ROUND(stacktop));
+	FFI_ASSERT(bytes == SF_ROUND(bytes));
+
+	/*	Deal with return values that are actually pass-by-reference.
+		Rule:
+		Return values are referenced by r3, so r4 is the first parameter.  */
+
+	if (flags & FLAG_RETVAL_REFERENCE)
+		*next_arg++ = (unsigned long)(char*)ecif->rvalue;
+
+	/* Now for the arguments.  */
+	for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++)
+    {
+		switch ((*ptr)->type)
+		{
+			/*	If a floating-point parameter appears before all of the general-
+				purpose registers are filled, the corresponding GPRs that match
+				the size of the floating-point parameter are shadowed for the
+				benefit of vararg and pre-ANSI functions.	*/
+			case FFI_TYPE_FLOAT:
+				double_tmp = *(float*)*p_argv;
+
+				if (fparg_count < NUM_FPR_ARG_REGISTERS)
+					*fpr_base++ = double_tmp;
+
+				*(double*)next_arg = double_tmp;
+
+				next_arg++;
+				fparg_count++;
+				FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+
+				break;
+
+			case FFI_TYPE_DOUBLE:
+				double_tmp = *(double*)*p_argv;
+
+				if (fparg_count < NUM_FPR_ARG_REGISTERS)
+					*fpr_base++ = double_tmp;
+
+				*(double*)next_arg = double_tmp;
+
+				next_arg += MODE_CHOICE(2,1);
+				fparg_count++;
+				FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+
+				break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+			case FFI_TYPE_LONGDOUBLE:
+#if defined(__ppc64__)
+				if (fparg_count < NUM_FPR_ARG_REGISTERS)
+					*(long double*)fpr_base	= *(long double*)*p_argv;
+#elif defined(__ppc__)
+				if (fparg_count < NUM_FPR_ARG_REGISTERS - 1)
+					*(long double*)fpr_base	= *(long double*)*p_argv;
+				else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1)
+					*(double*)fpr_base	= *(double*)*p_argv;
+#else
+#error undefined architecture
+#endif
+
+				*(long double*)next_arg	= *(long double*)*p_argv;
+				fparg_count += 2;
+				fpr_base += 2;
+				next_arg += MODE_CHOICE(4,2);
+				FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+
+				break;
+#endif	//	FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_SINT64:
+#if defined(__ppc64__)
+				gprvalue = *(long long*)*p_argv;
+				goto putgpr;
+#elif defined(__ppc__)
+				*(long long*)next_arg = *(long long*)*p_argv;
+				next_arg += 2;
+				break;
+#else
+#error undefined architecture
+#endif
+
+			case FFI_TYPE_POINTER:
+				gprvalue = *(unsigned long*)*p_argv;
+				goto putgpr;
+
+			case FFI_TYPE_UINT8:
+				gprvalue = *(unsigned char*)*p_argv;
+				goto putgpr;
+
+			case FFI_TYPE_SINT8:
+				gprvalue = *(signed char*)*p_argv;
+				goto putgpr;
+
+			case FFI_TYPE_UINT16:
+				gprvalue = *(unsigned short*)*p_argv;
+				goto putgpr;
+
+			case FFI_TYPE_SINT16:
+				gprvalue = *(signed short*)*p_argv;
+				goto putgpr;
+
+			case FFI_TYPE_STRUCT:
+			{
+#if defined(__ppc64__)
+				unsigned int	gprSize = 0;
+				unsigned int	fprSize = 0;
+
+				ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count,
+					(char*)next_arg, &gprSize, (char*)fpr_base, &fprSize);
+				next_arg += gprSize / sizeof(long);
+				fpr_base += fprSize / sizeof(double);
+
+#elif defined(__ppc__)
+				char*	dest_cpy = (char*)next_arg;
+
+			/*	Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+				SI 4 bytes) are aligned as if they were those modes.
+				Structures with 3 byte in size are padded upwards.  */
+				unsigned size_al = (*ptr)->size;
+
+			/*	If the first member of the struct is a double, then align
+				the struct to double-word.  */
+				if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
+					size_al = ALIGN((*ptr)->size, 8);
+
+				if (ecif->cif->abi == FFI_DARWIN)
+				{
+					if (size_al < 3)
+						dest_cpy += 4 - size_al;
+				}
+
+				memcpy((char*)dest_cpy, (char*)*p_argv, size_al);
+				next_arg += (size_al + 3) / 4;
+#else
+#error undefined architecture
+#endif
+				break;
+			}
+
+			case FFI_TYPE_INT:
+			case FFI_TYPE_UINT32:
+			case FFI_TYPE_SINT32:
+				gprvalue = *(unsigned*)*p_argv;
+
+putgpr:
+				*next_arg++ = gprvalue;
+				break;
+
+			default:
+				break;
+		}
+	}
+
+  /* Check that we didn't overrun the stack...  */
+  //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+  //FFI_ASSERT((unsigned *)fpr_base
+  //	     <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+  //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+#if defined(__ppc64__)
+
+bool
+ffi64_struct_contains_fp(
+	const ffi_type*	inType)
+{
+	bool			containsFP	= false;
+	unsigned int	i;
+
+	for (i = 0; inType->elements[i] != NULL && !containsFP; i++)
+	{
+		if (inType->elements[i]->type == FFI_TYPE_FLOAT		||
+			inType->elements[i]->type == FFI_TYPE_DOUBLE	||
+			inType->elements[i]->type == FFI_TYPE_LONGDOUBLE)
+			containsFP = true;
+		else if (inType->elements[i]->type == FFI_TYPE_STRUCT)
+			containsFP = ffi64_struct_contains_fp(inType->elements[i]);
+	}
+
+	return containsFP;
+}
+
+#endif	// defined(__ppc64__)
+
+/* Perform machine dependent cif processing.  */
+ffi_status
+ffi_prep_cif_machdep(
+	ffi_cif*	cif)
+{
+	/* All this is for the DARWIN ABI.  */
+	int				i;
+	ffi_type**		ptr;
+	int				intarg_count = 0;
+	int				fparg_count = 0;
+	unsigned int	flags = 0;
+	unsigned int	size_al = 0;
+
+	/*	All the machine-independent calculation of cif->bytes will be wrong.
+		Redo the calculation for DARWIN.  */
+
+	/*	Space for the frame pointer, callee's LR, CR, etc, and for
+		the asm's temp regs.  */
+	unsigned int	bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
+
+	/*	Return value handling.  The rules are as follows:
+		- 32-bit (or less) integer values are returned in gpr3;
+		- Structures of size <= 4 bytes also returned in gpr3;
+		- 64-bit integer values and structures between 5 and 8 bytes are
+			returned in gpr3 and gpr4;
+		- Single/double FP values are returned in fpr1;
+		- Long double FP (if not equivalent to double) values are returned in
+			fpr1 and fpr2;
+		- Larger structures values are allocated space and a pointer is passed
+			as the first argument.  */
+	switch (cif->rtype->type)
+	{
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+		case FFI_TYPE_LONGDOUBLE:
+			flags |= FLAG_RETURNS_128BITS;
+			flags |= FLAG_RETURNS_FP;
+			break;
+#endif	// FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+		case FFI_TYPE_DOUBLE:
+			flags |= FLAG_RETURNS_64BITS;
+			/* Fall through.  */
+		case FFI_TYPE_FLOAT:
+			flags |= FLAG_RETURNS_FP;
+			break;
+
+#if defined(__ppc64__)
+		case FFI_TYPE_POINTER:
+#endif
+		case FFI_TYPE_UINT64:
+		case FFI_TYPE_SINT64:
+			flags |= FLAG_RETURNS_64BITS;
+			break;
+
+		case FFI_TYPE_STRUCT:
+		{
+#if defined(__ppc64__)
+
+			if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL))
+			{
+				flags |= FLAG_RETVAL_REFERENCE;
+				flags |= FLAG_RETURNS_NOTHING;
+				intarg_count++;
+			}
+			else
+			{
+				flags |= FLAG_RETURNS_STRUCT;
+
+				if (ffi64_struct_contains_fp(cif->rtype))
+					flags |= FLAG_STRUCT_CONTAINS_FP;
+			}
+
+#elif defined(__ppc__)
+
+			flags |= FLAG_RETVAL_REFERENCE;
+			flags |= FLAG_RETURNS_NOTHING;
+			intarg_count++;
+
+#else
+#error undefined architecture
+#endif
+			break;
+		}
+
+		case FFI_TYPE_VOID:
+			flags |= FLAG_RETURNS_NOTHING;
+			break;
+
+		default:
+			/* Returns 32-bit integer, or similar.  Nothing to do here.  */
+			break;
+	}
+
+	/*	The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
+		first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
+		goes on the stack.  Structures are passed as a pointer to a copy of
+		the structure. Stuff on the stack needs to keep proper alignment.  */
+	for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+	{
+		switch ((*ptr)->type)
+		{
+			case FFI_TYPE_FLOAT:
+			case FFI_TYPE_DOUBLE:
+				fparg_count++;
+				/*	If this FP arg is going on the stack, it must be
+					8-byte-aligned.  */
+				if (fparg_count > NUM_FPR_ARG_REGISTERS
+					&& intarg_count % 2 != 0)
+					intarg_count++;
+				break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+			case FFI_TYPE_LONGDOUBLE:
+				fparg_count += 2;
+				/*	If this FP arg is going on the stack, it must be
+					8-byte-aligned.  */
+
+				if (
+#if defined(__ppc64__)
+					fparg_count > NUM_FPR_ARG_REGISTERS + 1
+#elif defined(__ppc__)
+					fparg_count > NUM_FPR_ARG_REGISTERS
+#else
+#error undefined architecture
+#endif
+					&& intarg_count % 2 != 0)
+					intarg_count++;
+
+				intarg_count += 2;
+				break;
+#endif	// FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_SINT64:
+				/*	'long long' arguments are passed as two words, but
+					either both words must fit in registers or both go
+					on the stack.  If they go on the stack, they must
+					be 8-byte-aligned.  */
+				if (intarg_count == NUM_GPR_ARG_REGISTERS - 1
+					|| (intarg_count >= NUM_GPR_ARG_REGISTERS
+					&& intarg_count % 2 != 0))
+					intarg_count++;
+
+				intarg_count += MODE_CHOICE(2,1);
+
+				break;
+
+			case FFI_TYPE_STRUCT:
+				size_al = (*ptr)->size;
+				/*	If the first member of the struct is a double, then align
+					the struct to double-word.  */
+				if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
+					size_al = ALIGN((*ptr)->size, 8);
+
+#if defined(__ppc64__)
+				// Look for FP struct members.
+				unsigned int	j;
+
+				for (j = 0; (*ptr)->elements[j] != NULL; j++)
+				{
+					if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT	||
+						(*ptr)->elements[j]->type == FFI_TYPE_DOUBLE)
+					{
+						fparg_count++;
+
+						if (fparg_count > NUM_FPR_ARG_REGISTERS)
+							intarg_count++;
+					}
+					else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE)
+					{
+						fparg_count += 2;
+
+						if (fparg_count > NUM_FPR_ARG_REGISTERS + 1)
+							intarg_count += 2;
+					}
+					else
+						intarg_count++;
+				}
+#elif defined(__ppc__)
+				intarg_count += (size_al + 3) / 4;
+#else
+#error undefined architecture
+#endif
+
+				break;
+
+			default:
+				/*	Everything else is passed as a 4/8-byte word in a GPR, either
+					the object itself or a pointer to it.  */
+				intarg_count++;
+				break;
+		}
+	}
+
+	/* Space for the FPR registers, if needed.  */
+	if (fparg_count != 0)
+	{
+		flags |= FLAG_FP_ARGUMENTS;
+#if defined(__ppc64__)
+		bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double);
+#elif defined(__ppc__)
+		bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
+#else
+#error undefined architecture
+#endif
+	}
+
+	/* Stack space.  */
+#if defined(__ppc64__)
+	if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
+		bytes += (intarg_count + fparg_count) * sizeof(long);
+#elif defined(__ppc__)
+	if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
+		bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
+#else
+#error undefined architecture
+#endif
+	else
+		bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
+
+	/* The stack space allocated needs to be a multiple of 16/32 bytes.  */
+	bytes = SF_ROUND(bytes);
+
+	cif->flags = flags;
+	cif->bytes = bytes;
+
+	return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void
+ffi_call_AIX(
+/*@out@*/	extended_cif*,
+			unsigned,
+			unsigned,
+/*@out@*/	unsigned*,
+			void (*fn)(void),
+			void (*fn2)(extended_cif*, unsigned *const));
+
+extern void
+ffi_call_DARWIN(
+/*@out@*/	extended_cif*,
+			unsigned long,
+			unsigned,
+/*@out@*/	unsigned*,
+			void (*fn)(void),
+			void (*fn2)(extended_cif*, unsigned *const));
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void
+ffi_call(
+/*@dependent@*/	ffi_cif*	cif,
+				void		(*fn)(void),
+/*@out@*/		void*		rvalue,
+/*@dependent@*/	void**		avalue)
+{
+	extended_cif ecif;
+
+	ecif.cif = cif;
+	ecif.avalue = avalue;
+
+	/*	If the return value is a struct and we don't have a return
+		value address then we need to make one.  */
+	if ((rvalue == NULL) &&
+		(cif->rtype->type == FFI_TYPE_STRUCT))
+	{
+		/*@-sysunrecog@*/
+		ecif.rvalue = alloca(cif->rtype->size);
+		/*@=sysunrecog@*/
+	}
+	else
+		ecif.rvalue = rvalue;
+
+	switch (cif->abi)
+	{
+		case FFI_AIX:
+			/*@-usedef@*/
+			ffi_call_AIX(&ecif, -cif->bytes,
+				cif->flags, ecif.rvalue, fn, ffi_prep_args);
+			/*@=usedef@*/
+			break;
+
+		case FFI_DARWIN:
+			/*@-usedef@*/
+			ffi_call_DARWIN(&ecif, -(long)cif->bytes,
+				cif->flags, ecif.rvalue, fn, ffi_prep_args);
+			/*@=usedef@*/
+			break;
+
+		default:
+			FFI_ASSERT(0);
+			break;
+    }
+}
+
+/* here I'd like to add the stack frame layout we use in darwin_closure.S
+   and aix_clsoure.S
+
+   SP previous -> +---------------------------------------+ <--- child frame
+		  | back chain to caller 4                |
+		  +---------------------------------------+ 4
+		  | saved CR 4                            |
+		  +---------------------------------------+ 8
+		  | saved LR 4                            |
+		  +---------------------------------------+ 12
+		  | reserved for compilers 4              |
+		  +---------------------------------------+ 16
+		  | reserved for binders 4                |
+		  +---------------------------------------+ 20
+		  | saved TOC pointer 4                   |
+		  +---------------------------------------+ 24
+		  | always reserved 8*4=32 (previous GPRs)|
+		  | according to the linkage convention   |
+		  | from AIX                              |
+		  +---------------------------------------+ 56
+		  | our FPR area 13*8=104                 |
+		  | f1                                    |
+		  | .                                     |
+		  | f13                                   |
+		  +---------------------------------------+ 160
+		  | result area 8                         |
+		  +---------------------------------------+ 168
+		  | alignement to the next multiple of 16 |
+SP current -->    +---------------------------------------+ 176 <- parent frame
+		  | back chain to caller 4                |
+		  +---------------------------------------+ 180
+		  | saved CR 4                            |
+		  +---------------------------------------+ 184
+		  | saved LR 4                            |
+		  +---------------------------------------+ 188
+		  | reserved for compilers 4              |
+		  +---------------------------------------+ 192
+		  | reserved for binders 4                |
+		  +---------------------------------------+ 196
+		  | saved TOC pointer 4                   |
+		  +---------------------------------------+ 200
+		  | always reserved 8*4=32  we store our  |
+		  | GPRs here                             |
+		  | r3                                    |
+		  | .                                     |
+		  | r10                                   |
+		  +---------------------------------------+ 232
+		  | overflow part                         |
+		  +---------------------------------------+ xxx
+		  | ????                                  |
+		  +---------------------------------------+ xxx
+*/
+
+#if !defined(POWERPC_DARWIN)
+
+#define MIN_LINE_SIZE 32
+
+static void
+flush_icache(
+	char*	addr)
+{
+#ifndef _AIX
+	__asm__ volatile (
+		"dcbf 0,%0\n"
+		"sync\n"
+		"icbi 0,%0\n"
+		"sync\n"
+		"isync"
+		: : "r" (addr) : "memory");
+#endif
+}
+
+static void
+flush_range(
+	char*	addr,
+	int		size)
+{
+	int i;
+
+	for (i = 0; i < size; i += MIN_LINE_SIZE)
+		flush_icache(addr + i);
+
+	flush_icache(addr + size - 1);
+}
+
+#endif	// !defined(POWERPC_DARWIN)
+
+ffi_status
+ffi_prep_closure(
+	ffi_closure*	closure,
+	ffi_cif*		cif,
+	void			(*fun)(ffi_cif*, void*, void**, void*),
+	void*			user_data)
+{
+	switch (cif->abi)
+	{
+		case FFI_DARWIN:
+		{
+			FFI_ASSERT (cif->abi == FFI_DARWIN);
+
+			unsigned int*	tramp = (unsigned int*)&closure->tramp[0];
+
+#if defined(__ppc64__)
+			tramp[0] = 0x7c0802a6;	//	mflr	r0
+			tramp[1] = 0x429f0005;	//	bcl		20,31,+0x8
+			tramp[2] = 0x7d6802a6;	//	mflr	r11
+			tramp[3] = 0x7c0803a6;	//	mtlr	r0
+			tramp[4] = 0xe98b0018;	//	ld		r12,24(r11)
+			tramp[5] = 0x7d8903a6;	//	mtctr	r12
+			tramp[6] = 0xe96b0020;	//	ld		r11,32(r11)
+			tramp[7] = 0x4e800420;	//	bctr
+			*(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM;
+			*(unsigned long*)&tramp[10] = (unsigned long)closure;
+#elif defined(__ppc__)
+			tramp[0] = 0x7c0802a6;	//	mflr	r0
+			tramp[1] = 0x429f0005;	//	bcl		20,31,+0x8
+			tramp[2] = 0x7d6802a6;	//	mflr	r11
+			tramp[3] = 0x7c0803a6;	//	mtlr	r0
+			tramp[4] = 0x818b0018;	//	lwz		r12,24(r11)
+			tramp[5] = 0x7d8903a6;	//	mtctr	r12
+			tramp[6] = 0x816b001c;	//	lwz		r11,28(r11)
+			tramp[7] = 0x4e800420;	//	bctr
+			tramp[8] = (unsigned long)ffi_closure_ASM;
+			tramp[9] = (unsigned long)closure;
+#else
+#error undefined architecture
+#endif
+
+			closure->cif = cif;
+			closure->fun = fun;
+			closure->user_data = user_data;
+
+			// Flush the icache. Only necessary on Darwin.
+#if defined(POWERPC_DARWIN)
+			if (sys_icache_invalidate) {
+				sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
+			}
+#else
+			flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE);
+#endif
+
+			break;
+		}
+
+		case FFI_AIX:
+		{
+			FFI_ASSERT (cif->abi == FFI_AIX);
+
+			ffi_aix_trampoline_struct*	tramp_aix =
+				(ffi_aix_trampoline_struct*)(closure->tramp);
+			aix_fd*	fd = (aix_fd*)(void*)ffi_closure_ASM;
+
+			tramp_aix->code_pointer = fd->code_pointer;
+			tramp_aix->toc = fd->toc;
+			tramp_aix->static_chain = closure;
+			closure->cif = cif;
+			closure->fun = fun;
+			closure->user_data = user_data;
+			break;
+		}
+
+		default:
+			return FFI_BAD_ABI;
+	}
+
+	return FFI_OK;
+}
+
+#if defined(__ppc__)
+	typedef double ldbits[2];
+
+	typedef union
+	{
+		ldbits lb;
+		long double ld;
+	} ldu;
+#endif
+
+/*	The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the
+	address of the closure. After storing the registers that could possibly
+	contain parameters to be passed into the stack frame and setting up space
+	for a return value, ffi_closure_ASM invokes the following helper function
+	to do most of the work.  */
+int
+ffi_closure_helper_DARWIN(
+	ffi_closure*	closure,
+	void*			rvalue,
+	unsigned long*	pgr,
+	ffi_dblfl*		pfr)
+{
+	/*	rvalue is the pointer to space for return value in closure assembly
+		pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
+		pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
+
+#if defined(__ppc__)
+	ldu	temp_ld;
+#endif
+
+	double				temp;
+	unsigned int		i;
+	unsigned int		nf = 0;	/* number of FPRs already used.  */
+	unsigned int		ng = 0;	/* number of GPRs already used.  */
+	ffi_cif*			cif = closure->cif;
+	unsigned int				avn = cif->nargs;
+	void**				avalue = alloca(cif->nargs * sizeof(void*));
+	ffi_type**			arg_types = cif->arg_types;
+
+	/*	Copy the caller's structure return value address so that the closure
+		returns the data directly to the caller.  */
+#if defined(__ppc64__)
+	if (cif->rtype->type == FFI_TYPE_STRUCT &&
+		ffi64_stret_needs_ptr(cif->rtype, NULL, NULL))
+#elif defined(__ppc__)
+	if (cif->rtype->type == FFI_TYPE_STRUCT)
+#else
+#error undefined architecture
+#endif
+	{
+		rvalue = (void*)*pgr;
+		pgr++;
+		ng++;
+	}
+
+	/* Grab the addresses of the arguments from the stack frame.  */
+	for (i = 0; i < avn; i++)
+	{
+		switch (arg_types[i]->type)
+		{
+			case FFI_TYPE_SINT8:
+			case FFI_TYPE_UINT8:
+				avalue[i] = (char*)pgr + MODE_CHOICE(3,7);
+				ng++;
+				pgr++;
+				break;
+
+			case FFI_TYPE_SINT16:
+			case FFI_TYPE_UINT16:
+				avalue[i] = (char*)pgr + MODE_CHOICE(2,6);
+				ng++;
+				pgr++;
+				break;
+
+#if defined(__ppc__)
+			case FFI_TYPE_POINTER:
+#endif
+			case FFI_TYPE_SINT32:
+			case FFI_TYPE_UINT32:
+				avalue[i] = (char*)pgr + MODE_CHOICE(0,4);
+				ng++;
+				pgr++;
+
+				break;
+
+			case FFI_TYPE_STRUCT:
+				if (cif->abi == FFI_DARWIN)
+				{
+#if defined(__ppc64__)
+					unsigned int	gprSize = 0;
+					unsigned int	fprSize	= 0;
+					unsigned int	savedFPRSize = fprSize;
+
+					avalue[i] = alloca(arg_types[i]->size);
+					ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr,
+						&gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL);
+ 
+					ng	+= gprSize / sizeof(long);
+					pgr	+= gprSize / sizeof(long);
+					pfr	+= (fprSize - savedFPRSize) / sizeof(double);
+
+#elif defined(__ppc__)
+					/*	Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+						SI 4 bytes) are aligned as if they were those modes.  */
+					unsigned int	size_al	= size_al = arg_types[i]->size;
+
+					/*	If the first member of the struct is a double, then align
+						the struct to double-word.  */
+					if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
+						size_al = ALIGN(arg_types[i]->size, 8);
+
+					if (size_al < 3)
+						avalue[i] = (char*)pgr + MODE_CHOICE(4,8) - size_al;
+					else
+						avalue[i] = (char*)pgr;
+
+					ng	+= (size_al + 3) / sizeof(long);
+					pgr += (size_al + 3) / sizeof(long);
+#else
+#error undefined architecture
+#endif
+				}
+
+				break;
+
+#if defined(__ppc64__)
+			case FFI_TYPE_POINTER:
+#endif
+			case FFI_TYPE_SINT64:
+			case FFI_TYPE_UINT64:
+				/* Long long ints are passed in 1 or 2 GPRs.  */
+				avalue[i] = pgr;
+				ng += MODE_CHOICE(2,1);
+				pgr += MODE_CHOICE(2,1);
+
+				break;
+
+			case FFI_TYPE_FLOAT:
+				/*	A float value consumes a GPR.
+					There are 13 64-bit floating point registers.  */
+				if (nf < NUM_FPR_ARG_REGISTERS)
+				{
+					temp = pfr->d;
+					pfr->f = (float)temp;
+					avalue[i] = pfr;
+					pfr++;
+				}
+				else
+					avalue[i] = pgr;
+
+				nf++;
+				ng++;
+				pgr++;
+				break;
+
+			case FFI_TYPE_DOUBLE:
+				/*	A double value consumes one or two GPRs.
+					There are 13 64bit floating point registers.  */
+				if (nf < NUM_FPR_ARG_REGISTERS)
+				{
+					avalue[i] = pfr;
+					pfr++;
+				}
+				else
+					avalue[i] = pgr;
+
+				nf++;
+				ng += MODE_CHOICE(2,1);
+				pgr += MODE_CHOICE(2,1);
+
+				break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+			case FFI_TYPE_LONGDOUBLE:
+#if defined(__ppc64__)
+				if (nf < NUM_FPR_ARG_REGISTERS)
+				{
+					avalue[i] = pfr;
+					pfr += 2;
+				}
+#elif defined(__ppc__)
+				/*	A long double value consumes 2/4 GPRs and 2 FPRs.
+					There are 13 64bit floating point registers.  */
+				if (nf < NUM_FPR_ARG_REGISTERS - 1)
+				{
+					avalue[i] = pfr;
+					pfr += 2;
+				}
+				/*	Here we have the situation where one part of the long double
+					is stored in fpr13 and the other part is already on the stack.
+					We use a union to pass the long double to avalue[i].  */
+				else if (nf == NUM_FPR_ARG_REGISTERS - 1)
+				{
+					memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
+					memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
+					avalue[i] = &temp_ld.ld;
+				}
+#else
+#error undefined architecture
+#endif
+				else
+					avalue[i] = pgr;
+
+				nf += 2;
+				ng += MODE_CHOICE(4,2);
+				pgr += MODE_CHOICE(4,2);
+
+				break;
+
+#endif	/*	FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE	*/
+
+			default:
+				FFI_ASSERT(0);
+				break;
+		}
+	}
+
+	(closure->fun)(cif, rvalue, avalue, closure->user_data);
+
+	/* Tell ffi_closure_ASM to perform return type promotions.  */
+	return cif->rtype->type;
+}
+
+#if defined(__ppc64__)
+
+/*	ffi64_struct_to_ram_form
+
+	Rebuild a struct's natural layout from buffers of concatenated registers.
+	Return the number of registers used.
+	inGPRs[0-7] == r3, inFPRs[0-7] == f1 ...
+*/
+void
+ffi64_struct_to_ram_form(
+	const ffi_type*	inType,
+	const char*		inGPRs,
+	unsigned int*	ioGPRMarker,
+	const char*		inFPRs,
+	unsigned int*	ioFPRMarker,
+	unsigned int*	ioFPRsUsed,
+	char*			outStruct,	// caller-allocated
+	unsigned int*	ioStructMarker)
+{
+	unsigned int	srcGMarker		= 0;
+	unsigned int	srcFMarker		= 0;
+	unsigned int	savedFMarker	= 0;
+	unsigned int	fprsUsed		= 0;
+	unsigned int	savedFPRsUsed	= 0;
+	unsigned int	destMarker		= 0;
+
+	static unsigned int	recurseCount	= 0;
+
+	if (ioGPRMarker)
+		srcGMarker	= *ioGPRMarker;
+
+	if (ioFPRMarker)
+	{
+		srcFMarker		= *ioFPRMarker;
+		savedFMarker	= srcFMarker;
+	}
+
+	if (ioFPRsUsed)
+	{
+		fprsUsed		= *ioFPRsUsed;
+		savedFPRsUsed	= fprsUsed;
+	}
+
+	if (ioStructMarker)
+		destMarker	= *ioStructMarker;
+
+	size_t			i;
+
+	switch (inType->size)
+	{
+		case 1: case 2: case 4:
+			srcGMarker += 8 - inType->size;
+			break;
+
+		default:
+			break;
+	}
+
+	for (i = 0; inType->elements[i] != NULL; i++)
+	{
+		switch (inType->elements[i]->type)
+		{
+			case FFI_TYPE_FLOAT:
+				srcFMarker = ALIGN(srcFMarker, 4);
+				srcGMarker = ALIGN(srcGMarker, 4);
+				destMarker = ALIGN(destMarker, 4);
+
+				if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+				{
+					*(float*)&outStruct[destMarker]	=
+						(float)*(double*)&inFPRs[srcFMarker];
+					srcFMarker += 8;
+					fprsUsed++;
+				}
+				else
+					*(float*)&outStruct[destMarker]	=
+						(float)*(double*)&inGPRs[srcGMarker];
+
+				srcGMarker += 4;
+				destMarker += 4;
+
+				// Skip to next GPR if next element won't fit and we're
+				// not already at a register boundary.
+				if (inType->elements[i + 1] != NULL && (destMarker % 8))
+				{
+					if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+						(!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+						(ALIGN(srcGMarker, 8) - srcGMarker) < 2) &&
+						(!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+						(ALIGN(srcGMarker, 8) - srcGMarker) < 4))
+						srcGMarker	= ALIGN(srcGMarker, 8);
+				}
+
+				break;
+
+			case FFI_TYPE_DOUBLE:
+				srcFMarker = ALIGN(srcFMarker, 8);
+				destMarker = ALIGN(destMarker, 8);
+
+				if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+				{
+					*(double*)&outStruct[destMarker]	=
+						*(double*)&inFPRs[srcFMarker];
+					srcFMarker += 8;
+					fprsUsed++;
+				}
+				else
+					*(double*)&outStruct[destMarker]	=
+						*(double*)&inGPRs[srcGMarker];
+
+				destMarker += 8;
+
+				// Skip next GPR
+				srcGMarker += 8;
+				srcGMarker = ALIGN(srcGMarker, 8);
+
+				break;
+
+			case FFI_TYPE_LONGDOUBLE:
+				destMarker = ALIGN(destMarker, 16);
+
+				if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+				{
+					srcFMarker = ALIGN(srcFMarker, 8);
+					srcGMarker = ALIGN(srcGMarker, 8);
+					*(long double*)&outStruct[destMarker]	=
+						*(long double*)&inFPRs[srcFMarker];
+					srcFMarker += 16;
+					fprsUsed += 2;
+				}
+				else
+				{
+					srcFMarker = ALIGN(srcFMarker, 16);
+					srcGMarker = ALIGN(srcGMarker, 16);
+					*(long double*)&outStruct[destMarker]	=
+						*(long double*)&inGPRs[srcGMarker];
+				}
+
+				destMarker += 16;
+
+				// Skip next 2 GPRs
+				srcGMarker += 16;
+				srcGMarker = ALIGN(srcGMarker, 8);
+
+				break;
+
+			case FFI_TYPE_UINT8:
+			case FFI_TYPE_SINT8:
+			{
+				if (inType->alignment == 1)	// chars only
+				{
+					if (inType->size == 1)
+						outStruct[destMarker++] = inGPRs[srcGMarker++];
+					else if (inType->size == 2)
+					{
+						outStruct[destMarker++] = inGPRs[srcGMarker++];
+						outStruct[destMarker++] = inGPRs[srcGMarker++];
+						i++;
+					}
+					else
+					{
+						memcpy(&outStruct[destMarker],
+							&inGPRs[srcGMarker], inType->size);
+						srcGMarker += inType->size;
+						destMarker += inType->size;
+						i += inType->size - 1;
+					}
+				}
+				else	// chars and other stuff
+				{
+					outStruct[destMarker++] = inGPRs[srcGMarker++];
+
+					// Skip to next GPR if next element won't fit and we're
+					// not already at a register boundary.
+					if (inType->elements[i + 1] != NULL && (srcGMarker % 8))
+					{
+						if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+							(!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+							(ALIGN(srcGMarker, 8) - srcGMarker) < 2) &&
+							(!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+							(ALIGN(srcGMarker, 8) - srcGMarker) < 4))
+							srcGMarker	= ALIGN(srcGMarker, inType->alignment);	// was 8
+					}
+				}
+
+				break;
+			}
+
+			case FFI_TYPE_UINT16:
+			case FFI_TYPE_SINT16:
+				srcGMarker = ALIGN(srcGMarker, 2);
+				destMarker = ALIGN(destMarker, 2);
+
+				*(short*)&outStruct[destMarker] =
+					*(short*)&inGPRs[srcGMarker];
+				srcGMarker += 2;
+				destMarker += 2;
+
+				break;
+
+			case FFI_TYPE_INT:
+			case FFI_TYPE_UINT32:
+			case FFI_TYPE_SINT32:
+				srcGMarker = ALIGN(srcGMarker, 4);
+				destMarker = ALIGN(destMarker, 4);
+
+				*(int*)&outStruct[destMarker] =
+					*(int*)&inGPRs[srcGMarker];
+				srcGMarker += 4;
+				destMarker += 4;
+
+				break;
+
+			case FFI_TYPE_POINTER:
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_SINT64:
+				srcGMarker = ALIGN(srcGMarker, 8);
+				destMarker = ALIGN(destMarker, 8);
+
+				*(long long*)&outStruct[destMarker] =
+					*(long long*)&inGPRs[srcGMarker];
+				srcGMarker += 8;
+				destMarker += 8;
+
+				break;
+
+			case FFI_TYPE_STRUCT:
+				recurseCount++;
+				ffi64_struct_to_ram_form(inType->elements[i], inGPRs,
+					&srcGMarker, inFPRs, &srcFMarker, &fprsUsed,
+					outStruct, &destMarker);
+				recurseCount--;
+				break;
+
+			default:
+				FFI_ASSERT(0);	// unknown element type
+				break;
+		}
+	}
+
+	srcGMarker = ALIGN(srcGMarker, inType->alignment);
+
+	// Take care of the special case for 16-byte structs, but not for
+	// nested structs.
+	if (recurseCount == 0 && srcGMarker == 16)
+	{
+		*(long double*)&outStruct[0] = *(long double*)&inGPRs[0];
+		srcFMarker	= savedFMarker;
+		fprsUsed	= savedFPRsUsed;
+	}
+
+	if (ioGPRMarker)
+		*ioGPRMarker = ALIGN(srcGMarker, 8);
+
+	if (ioFPRMarker)
+		*ioFPRMarker = srcFMarker;
+
+	if (ioFPRsUsed)
+		*ioFPRsUsed	= fprsUsed;
+
+	if (ioStructMarker)
+		*ioStructMarker	= ALIGN(destMarker, 8);
+}
+
+/*	ffi64_struct_to_reg_form
+
+	Copy a struct's elements into buffers that can be sliced into registers.
+	Return the sizes of the output buffers in bytes. Pass NULL buffer pointers
+	to calculate size only.
+	outGPRs[0-7] == r3, outFPRs[0-7] == f1 ...
+*/
+void
+ffi64_struct_to_reg_form(
+	const ffi_type*	inType,
+	const char*		inStruct,
+	unsigned int*	ioStructMarker,
+	unsigned int*	ioFPRsUsed,
+	char*			outGPRs,	// caller-allocated
+	unsigned int*	ioGPRSize,
+	char*			outFPRs,	// caller-allocated
+	unsigned int*	ioFPRSize)
+{
+	size_t			i;
+	unsigned int	srcMarker		= 0;
+	unsigned int	destGMarker		= 0;
+	unsigned int	destFMarker		= 0;
+	unsigned int	savedFMarker	= 0;
+	unsigned int	fprsUsed		= 0;
+	unsigned int	savedFPRsUsed	= 0;
+
+	static unsigned int	recurseCount	= 0;
+
+	if (ioStructMarker)
+		srcMarker	= *ioStructMarker;
+
+	if (ioFPRsUsed)
+	{
+		fprsUsed		= *ioFPRsUsed;
+		savedFPRsUsed	= fprsUsed;
+	}
+
+	if (ioGPRSize)
+		destGMarker	= *ioGPRSize;
+
+	if (ioFPRSize)
+	{
+		destFMarker		= *ioFPRSize;
+		savedFMarker	= destFMarker;
+	}
+
+	switch (inType->size)
+	{
+		case 1: case 2: case 4:
+			destGMarker += 8 - inType->size;
+			break;
+
+		default:
+			break;
+	}
+
+	for (i = 0; inType->elements[i] != NULL; i++)
+	{
+		switch (inType->elements[i]->type)
+		{
+			// Shadow floating-point types in GPRs for vararg and pre-ANSI
+			// functions.
+			case FFI_TYPE_FLOAT:
+				// Nudge markers to next 4/8-byte boundary
+				srcMarker = ALIGN(srcMarker, 4);
+				destGMarker = ALIGN(destGMarker, 4);
+				destFMarker = ALIGN(destFMarker, 8);
+
+				if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+				{
+					if (outFPRs != NULL && inStruct != NULL)
+						*(double*)&outFPRs[destFMarker] =
+							(double)*(float*)&inStruct[srcMarker];
+
+					destFMarker += 8;
+					fprsUsed++;
+				}
+
+				if (outGPRs != NULL && inStruct != NULL)
+					*(double*)&outGPRs[destGMarker] =
+						(double)*(float*)&inStruct[srcMarker];
+
+				srcMarker += 4;
+				destGMarker += 4;
+
+				// Skip to next GPR if next element won't fit and we're
+				// not already at a register boundary.
+				if (inType->elements[i + 1] != NULL && (srcMarker % 8))
+				{
+					if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+						(!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+						(ALIGN(destGMarker, 8) - destGMarker) < 2) &&
+						(!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+						(ALIGN(destGMarker, 8) - destGMarker) < 4))
+						destGMarker	= ALIGN(destGMarker, 8);
+				}
+
+				break;
+
+			case FFI_TYPE_DOUBLE:
+				srcMarker = ALIGN(srcMarker, 8);
+				destFMarker = ALIGN(destFMarker, 8);
+
+				if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+				{
+					if (outFPRs != NULL && inStruct != NULL)
+						*(double*)&outFPRs[destFMarker] =
+							*(double*)&inStruct[srcMarker];
+
+					destFMarker += 8;
+					fprsUsed++;
+				}
+
+				if (outGPRs != NULL && inStruct != NULL)
+					*(double*)&outGPRs[destGMarker] =
+						*(double*)&inStruct[srcMarker];
+
+				srcMarker += 8;
+
+				// Skip next GPR
+				destGMarker += 8;
+				destGMarker = ALIGN(destGMarker, 8);
+
+				break;
+
+			case FFI_TYPE_LONGDOUBLE:
+				srcMarker = ALIGN(srcMarker, 16);
+
+				if (fprsUsed < NUM_FPR_ARG_REGISTERS)
+				{
+					destFMarker = ALIGN(destFMarker, 8);
+					destGMarker = ALIGN(destGMarker, 8);
+
+					if (outFPRs != NULL && inStruct != NULL)
+						*(long double*)&outFPRs[destFMarker] =
+							*(long double*)&inStruct[srcMarker];
+
+					if (outGPRs != NULL && inStruct != NULL)
+						*(long double*)&outGPRs[destGMarker] =
+							*(long double*)&inStruct[srcMarker];
+
+					destFMarker += 16;
+					fprsUsed += 2;
+				}
+				else
+				{
+				 	destGMarker = ALIGN(destGMarker, 16);
+
+					 if (outGPRs != NULL && inStruct != NULL)
+						*(long double*)&outGPRs[destGMarker] =
+							*(long double*)&inStruct[srcMarker];
+				}
+
+				srcMarker += 16;
+				destGMarker += 16;	// Skip next 2 GPRs
+				destGMarker = ALIGN(destGMarker, 8);	// was 16
+
+				break;
+
+			case FFI_TYPE_UINT8:
+			case FFI_TYPE_SINT8:
+				if (inType->alignment == 1)	// bytes only
+				{
+					if (inType->size == 1)
+					{
+						if (outGPRs != NULL && inStruct != NULL)
+							outGPRs[destGMarker] = inStruct[srcMarker];
+
+						srcMarker++;
+						destGMarker++;
+					}
+					else if (inType->size == 2)
+					{
+						if (outGPRs != NULL && inStruct != NULL)
+						{
+							outGPRs[destGMarker] = inStruct[srcMarker];
+							outGPRs[destGMarker + 1] = inStruct[srcMarker + 1];
+						}
+
+						srcMarker += 2;
+						destGMarker += 2;
+
+						i++;
+					}
+					else
+					{
+						if (outGPRs != NULL && inStruct != NULL)
+						{
+							// Avoid memcpy for small chunks.
+							if (inType->size <= sizeof(long))
+								*(long*)&outGPRs[destGMarker] =
+									*(long*)&inStruct[srcMarker];
+							else
+								memcpy(&outGPRs[destGMarker],
+									&inStruct[srcMarker], inType->size);
+						}
+						
+						srcMarker += inType->size;
+						destGMarker += inType->size;
+						i += inType->size - 1;
+					}
+				}
+				else	// bytes and other stuff
+				{
+					if (outGPRs != NULL && inStruct != NULL)
+						outGPRs[destGMarker] = inStruct[srcMarker];
+
+					srcMarker++;
+					destGMarker++;
+
+					// Skip to next GPR if next element won't fit and we're
+					// not already at a register boundary.
+					if (inType->elements[i + 1] != NULL && (destGMarker % 8))
+					{
+						if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
+							(!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
+							(ALIGN(destGMarker, 8) - destGMarker) < 2) &&
+							(!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
+							(ALIGN(destGMarker, 8) - destGMarker) < 4))
+							destGMarker	= ALIGN(destGMarker, inType->alignment);	// was 8
+					}
+				}
+
+				break;
+
+			case FFI_TYPE_UINT16:
+			case FFI_TYPE_SINT16:
+				srcMarker = ALIGN(srcMarker, 2);
+				destGMarker = ALIGN(destGMarker, 2);
+
+				if (outGPRs != NULL && inStruct != NULL)
+					*(short*)&outGPRs[destGMarker] =
+						*(short*)&inStruct[srcMarker];
+
+				srcMarker += 2;
+				destGMarker += 2;
+
+				if (inType->elements[i + 1] == NULL)
+					destGMarker	= ALIGN(destGMarker, inType->alignment);
+
+				break;
+
+			case FFI_TYPE_INT:
+			case FFI_TYPE_UINT32:
+			case FFI_TYPE_SINT32:
+				srcMarker = ALIGN(srcMarker, 4);
+				destGMarker = ALIGN(destGMarker, 4);
+
+				if (outGPRs != NULL && inStruct != NULL)
+					*(int*)&outGPRs[destGMarker] =
+						*(int*)&inStruct[srcMarker];
+
+				srcMarker += 4;
+				destGMarker += 4;
+
+				break;
+
+			case FFI_TYPE_POINTER:
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_SINT64:
+				srcMarker = ALIGN(srcMarker, 8);
+				destGMarker = ALIGN(destGMarker, 8);
+
+				if (outGPRs != NULL && inStruct != NULL)
+					*(long long*)&outGPRs[destGMarker] =
+						*(long long*)&inStruct[srcMarker];
+
+				srcMarker += 8;
+				destGMarker += 8;
+
+				if (inType->elements[i + 1] == NULL)
+					destGMarker	= ALIGN(destGMarker, inType->alignment);
+
+				break;
+
+			case FFI_TYPE_STRUCT:
+				recurseCount++;
+				ffi64_struct_to_reg_form(inType->elements[i],
+					inStruct, &srcMarker, &fprsUsed, outGPRs, 
+					&destGMarker, outFPRs, &destFMarker);
+				recurseCount--;
+				break;
+
+			default:
+				FFI_ASSERT(0);
+				break;
+		}
+	}
+
+	destGMarker	= ALIGN(destGMarker, inType->alignment);
+
+	// Take care of the special case for 16-byte structs, but not for
+	// nested structs.
+	if (recurseCount == 0 && destGMarker == 16)
+	{
+		if (outGPRs != NULL && inStruct != NULL)
+			*(long double*)&outGPRs[0] = *(long double*)&inStruct[0];
+
+		destFMarker	= savedFMarker;
+		fprsUsed	= savedFPRsUsed;
+	}
+
+	if (ioStructMarker)
+		*ioStructMarker	= ALIGN(srcMarker, 8);
+
+	if (ioFPRsUsed)
+		*ioFPRsUsed	= fprsUsed;
+
+	if (ioGPRSize)
+		*ioGPRSize = ALIGN(destGMarker, 8);
+
+	if (ioFPRSize)
+		*ioFPRSize = ALIGN(destFMarker, 8);
+}
+
+/*	ffi64_stret_needs_ptr
+
+	Determine whether a returned struct needs a pointer in r3 or can fit
+	in registers.
+*/
+
+bool
+ffi64_stret_needs_ptr(
+	const ffi_type*	inType,
+	unsigned short*	ioGPRCount,
+	unsigned short*	ioFPRCount)
+{
+	// Obvious case first- struct is larger than combined FPR size.
+	if (inType->size > 14 * 8)
+		return true;
+
+	// Now the struct can physically fit in registers, determine if it
+	// also fits logically.
+	bool			needsPtr	= false;
+	unsigned short	gprsUsed	= 0;
+	unsigned short	fprsUsed	= 0;
+	size_t			i;
+
+	if (ioGPRCount)
+		gprsUsed = *ioGPRCount;
+
+	if (ioFPRCount)
+		fprsUsed = *ioFPRCount;
+
+	for (i = 0; inType->elements[i] != NULL && !needsPtr; i++)
+	{
+		switch (inType->elements[i]->type)
+		{
+			case FFI_TYPE_FLOAT:
+			case FFI_TYPE_DOUBLE:
+				gprsUsed++;
+				fprsUsed++;
+
+				if (fprsUsed > 13)
+					needsPtr = true;
+
+				break;
+
+			case FFI_TYPE_LONGDOUBLE:
+				gprsUsed += 2;
+				fprsUsed += 2;
+
+				if (fprsUsed > 14)
+					needsPtr = true;
+
+				break;
+
+			case FFI_TYPE_UINT8:
+			case FFI_TYPE_SINT8:
+			{
+				gprsUsed++;
+
+				if (gprsUsed > 8)
+				{
+					needsPtr = true;
+					break;
+				}
+
+				if (inType->elements[i + 1] == NULL)	// last byte in the struct
+					break;
+
+				// Count possible contiguous bytes ahead, up to 8.
+				unsigned short j;
+
+				for (j = 1; j < 8; j++)
+				{
+					if (inType->elements[i + j] == NULL ||
+						!FFI_TYPE_1_BYTE(inType->elements[i + j]->type))
+						break;
+				}
+
+				i += j - 1;	// allow for i++ before the test condition
+
+				break;
+			}
+
+			case FFI_TYPE_UINT16:
+			case FFI_TYPE_SINT16:
+			case FFI_TYPE_INT:
+			case FFI_TYPE_UINT32:
+			case FFI_TYPE_SINT32:
+			case FFI_TYPE_POINTER:
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_SINT64:
+				gprsUsed++;
+
+				if (gprsUsed > 8)
+					needsPtr = true;
+
+				break;
+
+			case FFI_TYPE_STRUCT:
+				needsPtr = ffi64_stret_needs_ptr(
+					inType->elements[i], &gprsUsed, &fprsUsed);
+
+				break;
+
+			default:
+				FFI_ASSERT(0);
+				break;
+		}
+	}
+
+	if (ioGPRCount)
+		*ioGPRCount = gprsUsed;
+
+	if (ioFPRCount)
+		*ioFPRCount = fprsUsed;
+
+	return needsPtr;
+}
+
+/*	ffi64_data_size
+
+	Calculate the size in bytes of an ffi type.
+*/
+
+unsigned int
+ffi64_data_size(
+	const ffi_type*	inType)
+{
+	unsigned int	size = 0;
+
+	switch (inType->type)
+	{
+		case FFI_TYPE_UINT8:
+		case FFI_TYPE_SINT8:
+			size = 1;
+			break;
+
+		case FFI_TYPE_UINT16:
+		case FFI_TYPE_SINT16:
+			size = 2;
+			break;
+
+		case FFI_TYPE_INT:
+		case FFI_TYPE_UINT32:
+		case FFI_TYPE_SINT32:
+		case FFI_TYPE_FLOAT:
+			size = 4;
+			break;
+
+		case FFI_TYPE_POINTER:
+		case FFI_TYPE_UINT64:
+		case FFI_TYPE_SINT64:
+		case FFI_TYPE_DOUBLE:
+			size = 8;
+			break;
+
+		case FFI_TYPE_LONGDOUBLE:
+			size = 16;
+			break;
+
+		case FFI_TYPE_STRUCT:
+			ffi64_struct_to_reg_form(
+				inType, NULL, NULL, NULL, NULL, &size, NULL, NULL);
+			break;
+
+		case FFI_TYPE_VOID:
+			break;
+
+		default:
+			FFI_ASSERT(0);
+			break;
+	}
+
+	return size;
+}
+
+#endif	/*	defined(__ppc64__)	*/
+#endif	/* __ppc__ || __ppc64__ */

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

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

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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-darwin.S
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-darwin.S	Tue Mar  4 14:25:41 2008
@@ -0,0 +1,243 @@
+#ifdef __i386__
+/* -----------------------------------------------------------------------
+   darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003  Red Hat, Inc.
+   
+   X86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+  
+/*
+ * This file is based on sysv.S and then hacked up by Ronald who hasn't done
+ * assembly programming in 8 years.
+ */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef PyObjC_STRICT_DEBUGGING
+  /* XXX: Debugging of stack alignment, to be removed */
+#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
+#else
+#define ASSERT_STACK_ALIGNED 
+#endif
+
+.text
+
+.globl _ffi_prep_args
+
+.align 4
+.globl _ffi_call_SYSV
+
+_ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+	subl  $8,%esp
+	ASSERT_STACK_ALIGNED
+.LCFI1:
+	/* Make room for all of the new args.  */
+	movl  16(%ebp),%ecx
+	subl  %ecx,%esp
+
+	ASSERT_STACK_ALIGNED
+
+	movl  %esp,%eax
+
+	/* Place all of the ffi_prep_args in position  */
+	subl  $8,%esp
+	pushl 12(%ebp)
+	pushl %eax
+	call  *8(%ebp)
+
+	ASSERT_STACK_ALIGNED
+
+	/* Return stack to previous state and call the function  */
+	addl  $16,%esp
+
+	ASSERT_STACK_ALIGNED
+
+	call  *28(%ebp)
+	
+	/* XXX: return returns return with 'ret $4', that upsets the stack! */
+	movl  16(%ebp),%ecx
+	addl  %ecx,%esp
+
+
+	/* Load %ecx with the return type code  */
+	movl  20(%ebp),%ecx	
+
+
+	/* If the return value pointer is NULL, assume no return value.  */
+	cmpl  $0,24(%ebp)
+	jne   retint
+
+	/* Even if there is no space for the return value, we are 
+	   obliged to handle floating-point values.  */
+	cmpl  $FFI_TYPE_FLOAT,%ecx
+	jne   noretval
+	fstp  %st(0)
+
+        jmp   epilogue
+
+retint:
+	cmpl  $FFI_TYPE_INT,%ecx
+	jne   retfloat
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	movl  %eax,0(%ecx)
+	jmp   epilogue
+
+retfloat:
+	cmpl  $FFI_TYPE_FLOAT,%ecx
+	jne   retdouble
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstps (%ecx)
+	jmp   epilogue
+
+retdouble:
+	cmpl  $FFI_TYPE_DOUBLE,%ecx
+	jne   retlongdouble
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstpl (%ecx)
+	jmp   epilogue
+
+retlongdouble:
+	cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
+	jne   retint64
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	fstpt (%ecx)
+	jmp   epilogue
+	
+retint64:	
+	cmpl  $FFI_TYPE_SINT64,%ecx
+        jne   retstruct1b
+	/* Load %ecx with the pointer to storage for the return value  */
+	movl  24(%ebp),%ecx	
+	movl  %eax,0(%ecx)
+	movl  %edx,4(%ecx)
+	jmp   epilogue
+
+retstruct1b:
+   cmpl $FFI_TYPE_SINT8,%ecx
+   jne  retstruct2b
+   movl 24(%ebp),%ecx
+   movb  %al,0(%ecx)
+   jmp  epilogue
+
+retstruct2b:
+   cmpl $FFI_TYPE_SINT16,%ecx
+   jne  retstruct
+   movl 24(%ebp),%ecx
+   movw %ax,0(%ecx)
+   jmp  epilogue
+	
+retstruct:
+   cmpl $FFI_TYPE_STRUCT,%ecx
+   jne  noretval
+	/* Nothing to do!  */
+
+	subl $4,%esp
+
+	ASSERT_STACK_ALIGNED
+
+	addl $8,%esp
+	movl %ebp, %esp
+	popl %ebp
+	ret
+
+noretval:
+epilogue:
+	ASSERT_STACK_ALIGNED
+	addl $8, %esp
+
+
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.LFE1:
+.ffi_call_SYSV_end:
+#if 0
+        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+#endif
+
+#if 0
+	.section	.eh_frame,EH_FRAME_FLAGS, at progbits
+.Lframe1:
+	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
+.LSCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+#ifdef __PIC__
+	.ascii "zR\0"	/* CIE Augmentation */
+#else
+	.ascii "\0"	/* CIE Augmentation */
+#endif
+	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
+	.byte	0x8	/* CIE RA Column */
+#ifdef __PIC__
+	.byte	0x1	/* .uleb128 0x1; Augmentation size */
+	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
+#endif
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x4	/* .uleb128 0x4 */
+	.byte	0x88	/* DW_CFA_offset, column 0x8 */
+	.byte	0x1	/* .uleb128 0x1 */
+	.align 4
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1	/* FDE Length */
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
+#ifdef __PIC__
+	.long	.LFB1-.	/* FDE initial location */
+#else
+	.long	.LFB1	/* FDE initial location */
+#endif
+	.long	.LFE1-.LFB1	/* FDE address range */
+#ifdef __PIC__
+	.byte	0x0	/* .uleb128 0x0; Augmentation size */
+#endif
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI0-.LFB1
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x8	/* .uleb128 0x8 */
+	.byte	0x85	/* DW_CFA_offset, column 0x5 */
+	.byte	0x2	/* .uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long	.LCFI1-.LCFI0
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x5	/* .uleb128 0x5 */
+	.align 4
+.LEFDE1:
+#endif
+
+#endif /* ifndef __x86_64__ */
+
+#endif /* defined __i386__ */

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

Added: python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c
==============================================================================
--- (empty file)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c	Tue Mar  4 14:25:41 2008
@@ -0,0 +1,569 @@
+#ifdef __i386__
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
+   
+   x86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+//#ifndef __x86_64__
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+//void ffi_prep_args(char *stack, extended_cif *ecif);
+
+static inline int
+retval_on_stack(
+	ffi_type*	tp)
+{
+	if (tp->type == FFI_TYPE_STRUCT)
+	{
+//		int size = tp->size;
+
+		if (tp->size > 8)
+			return 1;
+
+		switch (tp->size)
+		{
+			case 1: case 2: case 4: case 8:
+				return 0;
+			default:
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+/*@-exportheader@*/
+extern void ffi_prep_args(char*, extended_cif*);
+void
+ffi_prep_args(
+	char*			stack,
+	extended_cif*	ecif)
+/*@=exportheader@*/
+{
+	register unsigned int	i;
+	register void**			p_argv = ecif->avalue;
+	register char*			argp = stack;
+	register ffi_type**		p_arg;
+
+	if (retval_on_stack(ecif->cif->rtype))
+	{
+		*(void**)argp = ecif->rvalue;
+		argp += 4;
+	}
+
+	p_arg = ecif->cif->arg_types;
+
+	for (i = ecif->cif->nargs; i > 0; i--, p_arg++, p_argv++)
+    {
+		size_t z = (*p_arg)->size;
+
+		/* Align if necessary */
+		if ((sizeof(int) - 1) & (unsigned)argp)
+			argp = (char*)ALIGN(argp, sizeof(int));
+
+		if (z < sizeof(int))
+		{
+			z = sizeof(int);
+
+			switch ((*p_arg)->type)
+			{
+				case FFI_TYPE_SINT8:
+					*(signed int*)argp = (signed int)*(SINT8*)(*p_argv);
+					break;
+
+				case FFI_TYPE_UINT8:
+					*(unsigned int*)argp = (unsigned int)*(UINT8*)(*p_argv);
+					break;
+
+				case FFI_TYPE_SINT16:
+					*(signed int*)argp = (signed int)*(SINT16*)(*p_argv);
+					break;
+
+				case FFI_TYPE_UINT16:
+					*(unsigned int*)argp = (unsigned int)*(UINT16*)(*p_argv);
+					break;
+
+				case FFI_TYPE_SINT32:
+					*(signed int*)argp = (signed int)*(SINT32*)(*p_argv);
+					break;
+
+				case FFI_TYPE_UINT32:
+					*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
+					break;
+
+				case FFI_TYPE_STRUCT:
+					*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
+					break;
+
+				default:
+					FFI_ASSERT(0);
+					break;
+			}
+		}
+		else
+			memcpy(argp, *p_argv, z);
+
+		argp += z;
+	}
+}
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep(
+	ffi_cif*	cif)
+{
+	/* Set the return type flag */
+	switch (cif->rtype->type)
+	{
+#if !defined(X86_WIN32)  && !defined(X86_DARWIN)
+		case FFI_TYPE_STRUCT:
+#endif
+		case FFI_TYPE_VOID:
+		case FFI_TYPE_SINT64:
+		case FFI_TYPE_FLOAT:
+		case FFI_TYPE_DOUBLE:
+		case FFI_TYPE_LONGDOUBLE:
+			cif->flags = (unsigned)cif->rtype->type;
+			break;
+
+		case FFI_TYPE_UINT64:
+			cif->flags = FFI_TYPE_SINT64;
+			break;
+
+#if defined(X86_WIN32) || defined(X86_DARWIN)
+		case FFI_TYPE_STRUCT:
+			switch (cif->rtype->size)
+			{
+				case 1:
+					cif->flags = FFI_TYPE_SINT8;
+					break;
+
+				case 2:
+					cif->flags = FFI_TYPE_SINT16;
+					break;
+
+				case 4:
+					cif->flags = FFI_TYPE_INT;
+					break;
+
+				case 8:
+					cif->flags = FFI_TYPE_SINT64;
+					break;
+
+				default:
+					cif->flags = FFI_TYPE_STRUCT;
+					break;
+			}
+
+			break;
+#endif
+
+		default:
+			cif->flags = FFI_TYPE_INT;
+			break;
+	}
+
+	/* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
+	cif->bytes = (cif->bytes + 15) & ~0xF;
+
+	return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void
+ffi_call_SYSV(
+			void			(*)(char *, extended_cif *), 
+/*@out@*/	extended_cif*	, 
+			unsigned		,
+			unsigned		, 
+/*@out@*/	unsigned*		, 
+			void			(*fn)(void));
+/*@=declundef@*/
+/*@=exportheader@*/
+
+#ifdef X86_WIN32
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void
+ffi_call_STDCALL(
+			void			(char *, extended_cif *),
+/*@out@*/	extended_cif*	,
+			unsigned		,
+			unsigned		,
+/*@out@*/	unsigned*		,
+			void			(*fn)(void));
+/*@=declundef@*/
+/*@=exportheader@*/
+#endif /* X86_WIN32 */
+
+void
+ffi_call(
+/*@dependent@*/	ffi_cif*	cif, 
+				void		(*fn)(void), 
+/*@out@*/		void*		rvalue, 
+/*@dependent@*/	void**		avalue)
+{
+	extended_cif ecif;
+
+	ecif.cif = cif;
+	ecif.avalue = avalue;
+
+	/*	If the return value is a struct and we don't have a return
+		value address then we need to make one.	*/
+
+	if ((rvalue == NULL) && retval_on_stack(cif->rtype))
+	{
+		/*@-sysunrecog@*/
+		ecif.rvalue = alloca(cif->rtype->size);
+		/*@=sysunrecog@*/
+	}
+	else
+		ecif.rvalue = rvalue;
+
+	switch (cif->abi) 
+	{
+		case FFI_SYSV:
+			/*@-usedef@*/
+			/*	To avoid changing the assembly code make sure the size of the argument 
+				block is a multiple of 16. Then add 8 to compensate for local variables
+				in ffi_call_SYSV.	*/
+			ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+				cif->flags, ecif.rvalue, fn);
+			/*@=usedef@*/
+			break;
+
+#ifdef X86_WIN32
+		case FFI_STDCALL:
+			/*@-usedef@*/
+			ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
+				cif->flags, ecif.rvalue, fn);
+			/*@=usedef@*/
+			break;
+#endif /* X86_WIN32 */
+
+		default:
+			FFI_ASSERT(0);
+			break;
+	}
+}
+
+/** private members **/
+
+static void
+ffi_closure_SYSV(
+	ffi_closure*	closure) __attribute__((regparm(1)));
+
+#if !FFI_NO_RAW_API
+static void
+ffi_closure_raw_SYSV(
+	ffi_raw_closure*	closure) __attribute__((regparm(1)));
+#endif
+
+/*@-exportheader@*/
+static inline
+void 
+ffi_prep_incoming_args_SYSV(
+	char*		stack,
+	void**		rvalue,
+	void**		avalue,
+	ffi_cif*	cif)
+/*@=exportheader@*/
+{
+	register unsigned int	i;
+	register void**			p_argv = avalue;
+	register char*			argp = stack;
+	register ffi_type**		p_arg;
+
+	if (retval_on_stack(cif->rtype))
+	{
+		*rvalue = *(void**)argp;
+		argp += 4;
+	}
+
+	for (i = cif->nargs, p_arg = cif->arg_types; i > 0; i--, p_arg++, p_argv++)
+	{
+//		size_t z;
+
+		/* Align if necessary */
+		if ((sizeof(int) - 1) & (unsigned)argp)
+			argp = (char*)ALIGN(argp, sizeof(int));
+
+//		z = (*p_arg)->size;
+
+		/* because we're little endian, this is what it turns into.   */
+		*p_argv = (void*)argp;
+
+		argp += (*p_arg)->size;
+	}
+}
+
+/* This function is jumped to by the trampoline */
+__attribute__((regparm(1)))
+static void
+ffi_closure_SYSV(
+	ffi_closure*	closure)
+{
+	long double	res;
+	ffi_cif*	cif = closure->cif;
+	void**		arg_area = (void**)alloca(cif->nargs * sizeof(void*));
+	void*		resp = (void*)&res;
+	void*		args = __builtin_dwarf_cfa();
+
+	/*	This call will initialize ARG_AREA, such that each
+		element in that array points to the corresponding 
+		value on the stack; and if the function returns
+		a structure, it will reset RESP to point to the
+		structure return address.	*/
+	ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
+
+	(closure->fun)(cif, resp, arg_area, closure->user_data);
+
+	/* now, do a generic return based on the value of rtype */
+	if (cif->flags == FFI_TYPE_INT)
+		asm("movl	(%0),%%eax"
+			: : "r" (resp) : "eax");
+	else if (cif->flags == FFI_TYPE_FLOAT)
+		asm("flds	(%0)"
+			: : "r" (resp) : "st");
+	else if (cif->flags == FFI_TYPE_DOUBLE)
+		asm("fldl	(%0)"
+			: : "r" (resp) : "st", "st(1)");
+	else if (cif->flags == FFI_TYPE_LONGDOUBLE)
+ 		asm("fldt	(%0)"
+			: : "r" (resp) : "st", "st(1)");
+	else if (cif->flags == FFI_TYPE_SINT64)
+		asm("movl	0(%0),%%eax;"
+			"movl	4(%0),%%edx" 
+			: : "r" (resp)
+			: "eax", "edx");
+
+#if defined(X86_WIN32) || defined(X86_DARWIN)
+	else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct  */
+		asm("movsbl	(%0),%%eax"
+			: : "r" (resp) : "eax");
+	else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
+		asm("movswl	(%0),%%eax"
+			: : "r" (resp) : "eax");
+#endif
+
+	else if (cif->flags == FFI_TYPE_STRUCT)
+		asm("lea -8(%ebp),%esp;"
+			"pop %esi;"
+			"pop %edi;"
+			"pop %ebp;"
+			"ret $4");
+}
+
+
+/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
+#define FFI_INIT_TRAMPOLINE(TRAMP, FUN, CTX)											\
+	({																					\
+		unsigned char*	__tramp = (unsigned char*)(TRAMP);								\
+		unsigned int	__fun = (unsigned int)(FUN);									\
+		unsigned int	__ctx = (unsigned int)(CTX);									\
+		unsigned int	__dis = __fun - ((unsigned int)__tramp + FFI_TRAMPOLINE_SIZE);	\
+		*(unsigned char*)&__tramp[0] = 0xb8;											\
+		*(unsigned int*)&__tramp[1] = __ctx;	/* movl __ctx, %eax */					\
+		*(unsigned char*)&__tramp[5] = 0xe9;											\
+		*(unsigned int*)&__tramp[6] = __dis;	/* jmp __fun  */						\
+	})
+
+/* the cif must already be prep'ed */
+ffi_status
+ffi_prep_closure(
+	ffi_closure*	closure,
+	ffi_cif*		cif,
+	void			(*fun)(ffi_cif*,void*,void**,void*),
+	void*			user_data)
+{
+//	FFI_ASSERT(cif->abi == FFI_SYSV);
+	if (cif->abi != FFI_SYSV)
+		return FFI_BAD_ABI;
+
+	FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_SYSV, (void*)closure);
+
+	closure->cif		= cif;
+	closure->user_data	= user_data;
+	closure->fun		= fun;
+
+	return FFI_OK;
+}
+
+/* ------- Native raw API support -------------------------------- */
+
+#if !FFI_NO_RAW_API
+
+__attribute__((regparm(1)))
+static void
+ffi_closure_raw_SYSV(
+	ffi_raw_closure*	closure)
+{
+	long double		res;
+	ffi_raw*		raw_args = (ffi_raw*)__builtin_dwarf_cfa();
+	ffi_cif*		cif = closure->cif;
+	unsigned short	rtype = cif->flags;
+	void*			resp = (void*)&res;
+
+	(closure->fun)(cif, resp, raw_args, closure->user_data);
+
+	/* now, do a generic return based on the value of rtype */
+	if (rtype == FFI_TYPE_INT)
+		asm("movl	(%0),%%eax"
+			: : "r" (resp) : "eax");
+	else if (rtype == FFI_TYPE_FLOAT)
+		asm("flds	(%0)"
+			: : "r" (resp) : "st");
+	else if (rtype == FFI_TYPE_DOUBLE)
+		asm("fldl	(%0)"
+			: : "r" (resp) : "st", "st(1)");
+	else if (rtype == FFI_TYPE_LONGDOUBLE)
+		asm("fldt	(%0)"
+			: : "r" (resp) : "st", "st(1)");
+	else if (rtype == FFI_TYPE_SINT64)
+		asm("movl	0(%0),%%eax;"
+			"movl	4(%0),%%edx" 
+			: : "r" (resp) : "eax", "edx");
+}
+
+ffi_status
+ffi_prep_raw_closure(
+	ffi_raw_closure*	closure,
+	ffi_cif*			cif,
+	void				(*fun)(ffi_cif*,void*,ffi_raw*,void*),
+	void*				user_data)
+{
+//	FFI_ASSERT (cif->abi == FFI_SYSV);
+	if (cif->abi != FFI_SYSV)
+		return FFI_BAD_ABI;
+
+	int i;
+
+/*	We currently don't support certain kinds of arguments for raw
+	closures.  This should be implemented by a separate assembly language
+	routine, since it would require argument processing, something we
+	don't do now for performance.	*/
+	for (i = cif->nargs - 1; i >= 0; i--)
+	{
+		FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_STRUCT);
+		FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
+	}
+
+	FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_raw_SYSV, (void*)closure);
+
+	closure->cif		= cif;
+	closure->user_data	= user_data;
+	closure->fun		= fun;
+
+	return FFI_OK;
+}
+
+static void 
+ffi_prep_args_raw(
+	char*			stack,
+	extended_cif*	ecif)
+{
+	memcpy(stack, ecif->avalue, ecif->cif->bytes);
+}
+
+/*	We borrow this routine from libffi (it must be changed, though, to
+	actually call the function passed in the first argument.  as of
+	libffi-1.20, this is not the case.)	*/
+//extern void 
+//ffi_call_SYSV(
+//			void			(*)(char *, extended_cif *), 
+///*@out@*/	extended_cif*	, 
+//			unsigned		,
+//			unsigned		, 
+//*@out@*/	unsigned*		, 
+//			void			(*fn)());
+
+#ifdef X86_WIN32
+extern void
+ffi_call_STDCALL(
+			void			(*)(char *, extended_cif *),
+/*@out@*/	extended_cif*	,
+			unsigned		,
+			unsigned		,
+/*@out@*/	unsigned*		,
+			void			(*fn)());
+#endif // X86_WIN32
+
+void
+ffi_raw_call(
+/*@dependent@*/	ffi_cif*	cif, 
+				void		(*fn)(), 
+/*@out@*/		void*		rvalue, 
+/*@dependent@*/	ffi_raw*	fake_avalue)
+{
+	extended_cif ecif;
+	void **avalue = (void **)fake_avalue;
+
+	ecif.cif = cif;
+	ecif.avalue = avalue;
+
+	/*	If the return value is a struct and we don't have a return
+		value address then we need to make one	*/
+	if ((rvalue == NULL) && retval_on_stack(cif->rtype)) 
+	{
+		/*@-sysunrecog@*/
+		ecif.rvalue = alloca(cif->rtype->size);
+		/*@=sysunrecog@*/
+	}
+	else
+		ecif.rvalue = rvalue;
+
+	switch (cif->abi) 
+	{
+		case FFI_SYSV:
+			/*@-usedef@*/
+			ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, 
+				cif->flags, ecif.rvalue, fn);
+			/*@=usedef@*/
+			break;
+#ifdef X86_WIN32
+		case FFI_STDCALL:
+			/*@-usedef@*/
+			ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
+				cif->flags, ecif.rvalue, fn);
+			/*@=usedef@*/
+			break;
+#endif /* X86_WIN32 */
+		default:
+			FFI_ASSERT(0);
+			break;
+    }
+}
+
+#endif	// !FFI_NO_RAW_API
+//#endif	// !__x86_64__
+#endif	// __i386__

Modified: python/branches/libffi3-branch/setup.py
==============================================================================
--- python/branches/libffi3-branch/setup.py	(original)
+++ python/branches/libffi3-branch/setup.py	Tue Mar  4 14:25:41 2008
@@ -1452,8 +1452,37 @@
         # *** 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_vars('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/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:
+            if sys.platform == 'darwin':
+                return self.configure_ctypes_darwin(ext)
+
             (srcdir,) = sysconfig.get_config_vars('srcdir')
             ffi_builddir = os.path.join(self.build_temp, 'libffi')
             ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
@@ -1512,6 +1541,7 @@
 
         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'])
@@ -1541,6 +1571,11 @@
         if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
             return
 
+        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 = find_file('ffi.h', [], inc_dirs)
         if ffi_inc is not None:
             ffi_h = ffi_inc[0] + '/ffi.h'


More information about the Python-checkins mailing list