[Python-checkins] r60943 - python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffi.c python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffitarget.h python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/linux64.S python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ppc_closure.S python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/sysv.S

thomas.heller python-checkins at python.org
Fri Feb 22 08:36:46 CET 2008


Author: thomas.heller
Date: Fri Feb 22 08:36:45 2008
New Revision: 60943

Modified:
   python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffi.c
   python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffitarget.h
   python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/linux64.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ppc_closure.S
   python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/sysv.S
Log:
More files from libffi-3.0.2.

Modified: python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffi.c
==============================================================================
--- python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffi.c	(original)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffi.c	Fri Feb 22 08:36:45 2008
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 1998 Geoffrey Keating
+   Copyright (C) 2007 Free Software Foundation, Inc
 
    PowerPC Foreign Function Interface
 
@@ -39,7 +40,8 @@
   FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
   FLAG_RETURNS_FP       = 1 << (31-29),
   FLAG_RETURNS_64BITS   = 1 << (31-28),
-  FLAG_RETURNS_128BITS  = 1 << (31-27),
+
+  FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
 
   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
@@ -48,10 +50,13 @@
 };
 
 /* About the SYSV ABI.  */
-enum {
-  NUM_GPR_ARG_REGISTERS = 8,
-  NUM_FPR_ARG_REGISTERS = 8
-};
+unsigned int NUM_GPR_ARG_REGISTERS = 8;
+#ifndef __NO_FPRS__
+unsigned int NUM_FPR_ARG_REGISTERS = 8;
+#else
+unsigned int NUM_FPR_ARG_REGISTERS = 0;
+#endif
+
 enum { ASM_NEEDS_REGISTERS = 4 };
 
 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
@@ -80,10 +85,8 @@
 
 */
 
-/*@-exportheader@*/
 void
 ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
-/*@=exportheader@*/
 {
   const unsigned bytes = ecif->cif->bytes;
   const unsigned flags = ecif->cif->flags;
@@ -116,7 +119,7 @@
   /* 'next_arg' grows up as we put parameters in it.  */
   valp next_arg;
 
-  int i;
+  int i, ii MAYBE_UNUSED;
   ffi_type **ptr;
   double double_tmp;
   union {
@@ -134,6 +137,9 @@
   size_t struct_copy_size;
   unsigned gprvalue;
 
+  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+    NUM_FPR_ARG_REGISTERS = 0;
+
   stacktop.c = (char *) stack + bytes;
   gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
   intarg_count = 0;
@@ -165,6 +171,9 @@
       switch ((*ptr)->type)
 	{
 	case FFI_TYPE_FLOAT:
+	  /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
+	  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+	    goto soft_float_prep;
 	  double_tmp = **p_argv.f;
 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
 	    {
@@ -178,6 +187,9 @@
 	  break;
 
 	case FFI_TYPE_DOUBLE:
+	  /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
+	  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+	    goto soft_double_prep;
 	  double_tmp = **p_argv.d;
 
 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
@@ -197,8 +209,77 @@
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  if ((ecif->cif->abi != FFI_LINUX)
+		&& (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
+	    goto do_struct;
+	  /* The soft float ABI for long doubles works like this,
+	     a long double is passed in four consecutive gprs if available.
+	     A maximum of 2 long doubles can be passed in gprs.
+	     If we do not have 4 gprs left, the long double is passed on the
+	     stack, 4-byte aligned.  */
+	  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+	    {
+	      unsigned int int_tmp = (*p_argv.ui)[0];
+	      if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
+		{
+		  if (intarg_count < NUM_GPR_ARG_REGISTERS)
+		    intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
+		  *next_arg.u = int_tmp;
+		  next_arg.u++;
+		  for (ii = 1; ii < 4; ii++)
+		    {
+		      int_tmp = (*p_argv.ui)[ii];
+		      *next_arg.u = int_tmp;
+		      next_arg.u++;
+		    }
+		}
+	      else
+		{
+		  *gpr_base.u++ = int_tmp;
+		  for (ii = 1; ii < 4; ii++)
+		    {
+		      int_tmp = (*p_argv.ui)[ii];
+		      *gpr_base.u++ = int_tmp;
+		    }
+		}
+	      intarg_count +=4;
+	    }
+	  else
+	    {
+	      double_tmp = (*p_argv.d)[0];
+
+	      if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
+		{
+		  if (intarg_count >= NUM_GPR_ARG_REGISTERS
+		      && intarg_count % 2 != 0)
+		    {
+		      intarg_count++;
+		      next_arg.u++;
+		    }
+		  *next_arg.d = double_tmp;
+		  next_arg.u += 2;
+		  double_tmp = (*p_argv.d)[1];
+		  *next_arg.d = double_tmp;
+		  next_arg.u += 2;
+		}
+	      else
+		{
+		  *fpr_base.d++ = double_tmp;
+		  double_tmp = (*p_argv.d)[1];
+		  *fpr_base.d++ = double_tmp;
+		}
+
+	      fparg_count += 2;
+	      FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+	    }
+	  break;
+#endif
+
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
+	soft_double_prep:
 	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
 	    intarg_count++;
 	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
@@ -232,7 +313,7 @@
 
 	case FFI_TYPE_STRUCT:
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	case FFI_TYPE_LONGDOUBLE:
+	do_struct:
 #endif
 	  struct_copy_size = ((*ptr)->size + 15) & ~0xF;
 	  copy_space.c -= struct_copy_size;
@@ -261,6 +342,8 @@
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_POINTER:
+	soft_float_prep:
+
 	  gprvalue = **p_argv.ui;
 
 	putgpr:
@@ -322,10 +405,8 @@
 
 */
 
-/*@-exportheader@*/
 void FFI_HIDDEN
 ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
-/*@=exportheader@*/
 {
   const unsigned long bytes = ecif->cif->bytes;
   const unsigned long flags = ecif->cif->flags;
@@ -433,6 +514,7 @@
 	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
 	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
+	  FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 #endif
@@ -515,6 +597,9 @@
   unsigned type = cif->rtype->type;
   unsigned size = cif->rtype->size;
 
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+    NUM_FPR_ARG_REGISTERS = 0;
+
   if (cif->abi != FFI_LINUX64)
     {
       /* All the machine-independent calculation of cif->bytes will be wrong.
@@ -536,11 +621,6 @@
 
       /* Space for the mandatory parm save area and general registers.  */
       bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-      if (type == FFI_TYPE_LONGDOUBLE)
-	type = FFI_TYPE_DOUBLE;
-#endif
     }
 
   /* Return value handling.  The rules for SYSV are as follows:
@@ -549,19 +629,33 @@
      - 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;
-     - Larger structures and long double (if not equivalent to double) values
-     are allocated space and a pointer is passed as the first argument.
+     - Larger structures are allocated space and a pointer is passed as
+     the first argument.
+     - long doubles (if not equivalent to double) are returned in
+     fpr1,fpr2 for Linux and as for large structs for SysV.
      For LINUX64:
      - integer values in gpr3;
      - Structures/Unions by reference;
-     - Single/double FP values in fpr1, long double in fpr1,fpr2.  */
+     - Single/double FP values in fpr1, long double in fpr1,fpr2.
+     - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
+     - soft-float long doubles are returned in gpr3-gpr6.  */
   switch (type)
     {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
+	&& cif->abi != FFI_LINUX_SOFT_FLOAT)
+	goto byref;
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+#endif
     case FFI_TYPE_DOUBLE:
       flags |= FLAG_RETURNS_64BITS;
       /* Fall through.  */
     case FFI_TYPE_FLOAT:
-      flags |= FLAG_RETURNS_FP;
+      /* With FFI_LINUX_SOFT_FLOAT no fp registers are used.  */
+      if (cif->abi != FFI_LINUX_SOFT_FLOAT)
+	flags |= FLAG_RETURNS_FP;
       break;
 
     case FFI_TYPE_UINT64:
@@ -598,15 +692,8 @@
 		}
 	    }
 	}
-      /* else fall through.  */
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-    case FFI_TYPE_LONGDOUBLE:
-      if (type == FFI_TYPE_LONGDOUBLE && cif->abi == FFI_LINUX64)
-	{
-	  flags |= FLAG_RETURNS_128BITS;
-	  flags |= FLAG_RETURNS_FP;
-	  break;
-	}
+    byref:
 #endif
       intarg_count++;
       flags |= FLAG_RETVAL_REFERENCE;
@@ -631,11 +718,36 @@
 	switch ((*ptr)->type)
 	  {
 	  case FFI_TYPE_FLOAT:
+	    /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
+	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	      goto soft_float_cif;
 	    fparg_count++;
 	    /* floating singles are not 8-aligned on stack */
 	    break;
 
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	  case FFI_TYPE_LONGDOUBLE:
+	    if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+	      goto do_struct;
+	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	      {
+		if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
+		  || intarg_count < NUM_GPR_ARG_REGISTERS)
+		  /* A long double in FFI_LINUX_SOFT_FLOAT can use only
+		     a set of four consecutive gprs. If we have not enough,
+		     we have to adjust the intarg_count value.  */
+		  intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
+		intarg_count += 4;
+		break;
+	      }
+	    else
+	      fparg_count++;
+	    /* Fall thru */
+#endif
 	  case FFI_TYPE_DOUBLE:
+	    /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
+	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	      goto soft_double_cif;
 	    fparg_count++;
 	    /* If this FP arg is going on the stack, it must be
 	       8-byte-aligned.  */
@@ -647,6 +759,7 @@
 
 	  case FFI_TYPE_UINT64:
 	  case FFI_TYPE_SINT64:
+	  soft_double_cif:
 	    /* '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
@@ -664,7 +777,7 @@
 
 	  case FFI_TYPE_STRUCT:
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	  case FFI_TYPE_LONGDOUBLE:
+	  do_struct:
 #endif
 	    /* We must allocate space for a copy of these to enforce
 	       pass-by-value.  Pad the space up to a multiple of 16
@@ -674,6 +787,7 @@
 	    /* Fall through (allocate space for the pointer).  */
 
 	  default:
+	  soft_float_cif:
 	    /* Everything else is passed as a 4-byte word in a GPR, either
 	       the object itself or a pointer to it.  */
 	    intarg_count++;
@@ -687,8 +801,13 @@
 	  {
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	  case FFI_TYPE_LONGDOUBLE:
-	    fparg_count += 2;
-	    intarg_count += 2;
+	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	      intarg_count += 4;
+	    else
+	      {
+		fparg_count += 2;
+		intarg_count += 2;
+	      }
 	    break;
 #endif
 	  case FFI_TYPE_FLOAT:
@@ -751,24 +870,14 @@
   return FFI_OK;
 }
 
-/*@-declundef@*/
-/*@-exportheader@*/
-extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
-			  unsigned, unsigned,
-			  /*@out@*/ unsigned *,
+extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
 			  void (*fn)(void));
-extern void FFI_HIDDEN ffi_call_LINUX64(/*@out@*/ extended_cif *,
-					unsigned long, unsigned long,
-					/*@out@*/ unsigned long *,
+extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
+					unsigned long, unsigned long *,
 					void (*fn)(void));
-/*@=declundef@*/
-/*@=exportheader@*/
 
 void
-ffi_call(/*@dependent@*/ ffi_cif *cif,
-	 void (*fn)(void),
-	 /*@out@*/ void *rvalue,
-	 /*@dependent@*/ void **avalue)
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 {
   extended_cif ecif;
 
@@ -780,9 +889,7 @@
 
   if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
     {
-      /*@-sysunrecog@*/
       ecif.rvalue = alloca(cif->rtype->size);
-      /*@=sysunrecog@*/
     }
   else
     ecif.rvalue = rvalue;
@@ -793,15 +900,13 @@
 #ifndef POWERPC64
     case FFI_SYSV:
     case FFI_GCC_SYSV:
-      /*@-usedef@*/
+    case FFI_LINUX:
+    case FFI_LINUX_SOFT_FLOAT:
       ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
-      /*@=usedef@*/
       break;
 #else
     case FFI_LINUX64:
-      /*@-usedef@*/
       ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
-      /*@=usedef@*/
       break;
 #endif
     default:
@@ -815,27 +920,24 @@
 #define MIN_CACHE_LINE_SIZE 8
 
 static void
-flush_icache (char *addr1, int size)
+flush_icache (char *wraddr, char *xaddr, int size)
 {
   int i;
-  char * addr;
   for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
-    {
-      addr = addr1 + i;
-      __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;"
-			: : "r" (addr) : "memory");
-    }
-  addr = addr1 + size - 1;
-  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;"
-		    : : "r"(addr) : "memory");
+    __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
+		      : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
+  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
+		    : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
+		    : "memory");
 }
 #endif
 
 ffi_status
-ffi_prep_closure (ffi_closure *closure,
-		  ffi_cif *cif,
-		  void (*fun) (ffi_cif *, void *, void **, void *),
-		  void *user_data)
+ffi_prep_closure_loc (ffi_closure *closure,
+		      ffi_cif *cif,
+		      void (*fun) (ffi_cif *, void *, void **, void *),
+		      void *user_data,
+		      void *codeloc)
 {
 #ifdef POWERPC64
   void **tramp = (void **) &closure->tramp[0];
@@ -843,7 +945,7 @@
   FFI_ASSERT (cif->abi == FFI_LINUX64);
   /* Copy function address and TOC from ffi_closure_LINUX64.  */
   memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
-  tramp[2] = (void *) closure;
+  tramp[2] = codeloc;
 #else
   unsigned int *tramp;
 
@@ -859,10 +961,10 @@
   tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
   tramp[9] = 0x4e800420;  /*   bctr */
   *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
-  *(void **) &tramp[3] = (void *) closure;          /* context */
+  *(void **) &tramp[3] = codeloc;                   /* context */
 
   /* Flush the icache.  */
-  flush_icache (&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
+  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
 #endif
 
   closure->cif = cif;
@@ -920,14 +1022,17 @@
      For FFI_SYSV the result is passed in r3/r4 if the struct size is less
      or equal 8 bytes.  */
 
-  if (cif->rtype->type == FFI_TYPE_STRUCT)
+  if ((cif->rtype->type == FFI_TYPE_STRUCT
+       && !((cif->abi == FFI_SYSV) && (size <= 8)))
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
+	  && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+#endif
+      )
     {
-      if (!((cif->abi == FFI_SYSV) && (size <= 8)))
-	{
-	  rvalue = (void *) *pgr;
-	  ng++;
-	  pgr++;
-	}
+      rvalue = (void *) *pgr;
+      ng++;
+      pgr++;
     }
 
   i = 0;
@@ -974,6 +1079,7 @@
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_POINTER:
+	soft_float_closure:
 	  /* there are 8 gpr registers used to pass values */
 	  if (ng < 8)
 	    {
@@ -989,6 +1095,9 @@
 	  break;
 
 	case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	do_struct:
+#endif
 	  /* Structs are passed by reference. The address will appear in a
 	     gpr if it is one of the first 8 arguments.  */
 	  if (ng < 8)
@@ -1006,6 +1115,7 @@
 
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
+	soft_double_closure:
 	  /* passing long long ints are complex, they must
 	   * be passed in suitable register pairs such as
 	   * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
@@ -1037,6 +1147,9 @@
 	  break;
 
 	case FFI_TYPE_FLOAT:
+	  /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
+	  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	    goto soft_float_closure;
 	  /* unfortunately float values are stored as doubles
 	   * in the ffi_closure_SYSV code (since we don't check
 	   * the type in that routine).
@@ -1060,12 +1173,14 @@
 	       * naughty thing to do but...
 	       */
 	      avalue[i] = pst;
-	      nf++;
 	      pst += 1;
 	    }
 	  break;
 
 	case FFI_TYPE_DOUBLE:
+	  /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
+	  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	    goto soft_double_closure;
 	  /* On the outgoing stack all values are aligned to 8 */
 	  /* there are 8 64bit floating point registers */
 
@@ -1080,11 +1195,47 @@
 	      if (((long) pst) & 4)
 		pst++;
 	      avalue[i] = pst;
-	      nf++;
 	      pst += 2;
 	    }
 	  break;
 
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+	    goto do_struct;
+	  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+	    { /* Test if for the whole long double, 4 gprs are available.
+		 otherwise the stuff ends up on the stack.  */
+	      if (ng < 5)
+		{
+		  avalue[i] = pgr;
+		  pgr += 4;
+		  ng += 4;
+		}
+	      else
+		{
+		  avalue[i] = pst;
+		  pst += 4;
+		}
+	      break;
+	    }
+	  if (nf < 7)
+	    {
+	      avalue[i] = pfr;
+	      pfr += 2;
+	      nf += 2;
+	    }
+	  else
+	    {
+	      if (((long) pst) & 4)
+		pst++;
+	      avalue[i] = pst;
+	      pst += 4;
+	      nf = 8;
+	    }
+	  break;
+#endif
+
 	default:
 	  FFI_ASSERT (0);
 	}
@@ -1101,8 +1252,36 @@
   if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
       && size <= 8)
     return FFI_SYSV_TYPE_SMALL_STRUCT + size;
-  return cif->rtype->type;
-
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+  else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
+	   && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+    return FFI_TYPE_STRUCT;
+#endif
+  /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
+     respectivley UINT64.  */
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+    {
+      switch (cif->rtype->type)
+	{
+	case FFI_TYPE_FLOAT:
+	  return FFI_TYPE_UINT32;
+	  break;
+	case FFI_TYPE_DOUBLE:
+	  return FFI_TYPE_UINT64;
+	  break;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  return FFI_TYPE_UINT128;
+	  break;
+#endif
+	default:
+	  return cif->rtype->type;
+	}
+    }
+  else
+    {
+      return cif->rtype->type;
+    }
 }
 
 int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,

Modified: python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffitarget.h
==============================================================================
--- python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffitarget.h	(original)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ffitarget.h	Fri Feb 22 08:36:45 2008
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------*-C-*-
    ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Copyright (C) 2007 Free Software Foundation, Inc
    Target configuration macros for PowerPC.
 
    Permission is hereby granted, free of charge, to any person obtaining
@@ -13,13 +14,14 @@
    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 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 AUTHORS OR COPYRIGHT
+   HOLDERS 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.
 
    ----------------------------------------------------------------------- */
 
@@ -43,10 +45,20 @@
   FFI_SYSV,
   FFI_GCC_SYSV,
   FFI_LINUX64,
+  FFI_LINUX,
+  FFI_LINUX_SOFT_FLOAT,
 # ifdef POWERPC64
   FFI_DEFAULT_ABI = FFI_LINUX64,
 # else
+#  if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
+  FFI_DEFAULT_ABI = FFI_LINUX,
+#  else
+#   ifdef __NO_FPRS__
+  FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
+#   else
   FFI_DEFAULT_ABI = FFI_GCC_SYSV,
+#   endif
+#  endif
 # endif
 #endif
 
@@ -69,7 +81,7 @@
   FFI_DEFAULT_ABI = FFI_SYSV,
 #endif
 
-  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+  FFI_LAST_ABI
 } ffi_abi;
 #endif
 
@@ -78,8 +90,14 @@
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
 
+/* For additional types like the below, take care about the order in
+   ppc_closures.S. They must follow after the FFI_TYPE_LAST.  */
+
+/* Needed for soft-float long-double-128 support.  */
+#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
+
 /* Needed for FFI_SYSV small structure returns.  */
-#define FFI_SYSV_TYPE_SMALL_STRUCT  (FFI_TYPE_LAST)
+#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
 
 #if defined(POWERPC64) || defined(POWERPC_AIX)
 #define FFI_TRAMPOLINE_SIZE 24

Modified: python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/linux64.S
==============================================================================
--- python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/linux64.S	(original)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/linux64.S	Fri Feb 22 08:36:45 2008
@@ -47,8 +47,8 @@
 	std	%r0, 16(%r1)
 
 	mr	%r28, %r1	/* our AP.  */
-	stdux	%r1, %r1, %r4
 .LCFI0:
+	stdux	%r1, %r1, %r4
 	mr	%r31, %r5	/* flags, */
 	mr	%r30, %r6	/* rvalue, */
 	mr	%r29, %r7	/* function address.  */
@@ -100,6 +100,10 @@
 	/* Make the call.  */
 	bctrl
 
+	/* This must follow the call immediately, the unwinder
+	   uses this to find out if r2 has been saved or not.  */
+	ld	%r2, 40(%r1)
+
 	/* Now, deal with the return value.  */
 	mtcrf	0x01, %r31
 	bt-	30, .Ldone_return_value
@@ -109,7 +113,6 @@
 
 .Ldone_return_value:
 	/* Restore the registers we used and return.  */
-	ld	%r2, 40(%r1)
 	mr	%r1, %r28
 	ld	%r0, 16(%r28)
 	ld	%r28, -32(%r1)
@@ -120,12 +123,10 @@
 	blr
 
 .Lfp_return_value:
-	bt	27, .Lfd_return_value
 	bf	28, .Lfloat_return_value
 	stfd	%f1, 0(%r30)
-	b	.Ldone_return_value
-.Lfd_return_value:
-	stfd	%f1, 0(%r30)
+	mtcrf	0x02, %r31 /* cr6  */
+	bf	27, .Ldone_return_value
 	stfd	%f2, 8(%r30)
 	b	.Ldone_return_value
 .Lfloat_return_value:

Modified: python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ppc_closure.S
==============================================================================
--- python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ppc_closure.S	(original)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/ppc_closure.S	Fri Feb 22 08:36:45 2008
@@ -28,6 +28,7 @@
 	stw   %r9, 40(%r1)
 	stw   %r10,44(%r1)
 
+#ifndef __NO_FPRS__
 	# next save fpr 1 to fpr 8 (aligned to 8)
 	stfd  %f1, 48(%r1)
 	stfd  %f2, 56(%r1)
@@ -37,6 +38,7 @@
 	stfd  %f6, 88(%r1)
 	stfd  %f7, 96(%r1)
 	stfd  %f8, 104(%r1)
+#endif
 
 	# set up registers for the routine that actually does the work
 	# get the context pointer from the trampoline
@@ -58,218 +60,190 @@
 
 	# make the call
 	bl ffi_closure_helper_SYSV at local
-
+.Lret:
 	# 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 up the proper starting point in table
 	# by using return type as offset
-	addi %r6,%r1,112   # 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
+
+	mflr %r4		# move address of .Lret to r4
+	slwi %r3,%r3,4		# now multiply return type by 16
+	addi %r4, %r4, .Lret_type0 - .Lret
+	lwz %r0,148(%r1)
+	add %r3,%r3,%r4		# add contents of table to table address
 	mtctr %r3
-	bctr               # jump to it
+	bctr			# jump to it
 .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
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 	nop
 
 # case FFI_TYPE_INT
-.Lret_type1:
-	lwz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+.Lfinish:
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_FLOAT
-.Lret_type2:
-	lfs %f1,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lfs %f1,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_DOUBLE
-.Lret_type3:
-	lfd %f1,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lfd %f1,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_LONGDOUBLE
-.Lret_type4:
-	lfd %f1,0(%r6)
+	lfd %f1,112+0(%r1)
+	lfd %f2,112+8(%r1)
+	mtlr %r0
 	b .Lfinish
-	nop
-	nop
 
 # case FFI_TYPE_UINT8
-.Lret_type5:
-	lbz %r3,3(%r6)
-	b .Lfinish
-	nop
-	nop
+	lbz %r3,112+3(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_SINT8
-.Lret_type6:
-	lbz %r3,3(%r6)
+	lbz %r3,112+3(%r1)
 	extsb %r3,%r3
+	mtlr %r0
 	b .Lfinish
-	nop
 
 # case FFI_TYPE_UINT16
-.Lret_type7:
-	lhz %r3,2(%r6)
-	b .Lfinish
-	nop
-	nop
+	lhz %r3,112+2(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_SINT16
-.Lret_type8:
-	lha %r3,2(%r6)
-	b .Lfinish
-	nop
-	nop
+	lha %r3,112+2(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_UINT32
-.Lret_type9:
-	lwz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_SINT32
-.Lret_type10:
-	lwz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_TYPE_UINT64
-.Lret_type11:
-	lwz %r3,0(%r6)
-	lwz %r4,4(%r6)
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	mtlr %r0
 	b .Lfinish
-	nop
 
 # case FFI_TYPE_SINT64
-.Lret_type12:
-	lwz %r3,0(%r6)
-	lwz %r4,4(%r6)
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	mtlr %r0
 	b .Lfinish
-	nop
 
 # case FFI_TYPE_STRUCT
-.Lret_type13:
-	b .Lfinish
-	nop
-	nop
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 	nop
 
 # case FFI_TYPE_POINTER
-.Lret_type14:
-	lwz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+
+# case FFI_TYPE_UINT128
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	lwz %r5,112+8(%r1)
+	bl .Luint128
 
 # The return types below are only used when the ABI type is FFI_SYSV.
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
-.Lret_type15:
-# fall through.
-	lbz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lbz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
-.Lret_type16:
-# fall through.
-	lhz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lhz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
-.Lret_type17:
-# fall through.
-	lwz %r3,0(%r6)
+	lwz %r3,112+0(%r1)
 	srwi %r3,%r3,8
+	mtlr %r0
 	b .Lfinish
-	nop
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
-.Lret_type18:
-# this one handles the structs from above too.
-	lwz %r3,0(%r6)
-	b .Lfinish
-	nop
-	nop
+	lwz %r3,112+0(%r1)
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
-.Lret_type19:
-# fall through.
-	lwz %r3,0(%r6)
-	lwz %r4,4(%r6)
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
 	li %r5,24
 	b .Lstruct567
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
-.Lret_type20:
-# fall through.
-	lwz %r3,0(%r6)
-	lwz %r4,4(%r6)
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
 	li %r5,16
 	b .Lstruct567
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
-.Lret_type21:
-# fall through.
-	lwz %r3,0(%r6)
-	lwz %r4,4(%r6)
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
 	li %r5,8
 	b .Lstruct567
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
-.Lret_type22:
-# this one handles the above unhandled structs.
-	lwz %r3,0(%r6)
-	lwz %r4,4(%r6)
+	lwz %r3,112+0(%r1)
+	lwz %r4,112+4(%r1)
+	mtlr %r0
 	b .Lfinish
-	nop
 
-# case done
-.Lfinish:
+.Lstruct567:
+	subfic %r6,%r5,32
+	srw %r4,%r4,%r5
+	slw %r6,%r3,%r6
+	srw %r3,%r3,%r5
+	or %r4,%r6,%r4
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
 
-	lwz %r0,148(%r1)
+.Luint128:
+	lwz %r6,112+12(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
-.Lstruct567:
-	subfic %r0,%r5,32
-	srw %r4,%r4,%r5
-	slw %r0,%r3,%r0
-	srw %r3,%r3,%r5
-	or %r4,%r0,%r4
-	b .Lfinish
 END(ffi_closure_SYSV)
 
 	.section	".eh_frame",EH_FRAME_FLAGS, at progbits

Modified: python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/sysv.S
==============================================================================
--- python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/sysv.S	(original)
+++ python/branches/libffi3-branch/Modules/_ctypes/libffi/src/powerpc/sysv.S	Fri Feb 22 08:36:45 2008
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------------
-   sysv.h - Copyright (c) 1998 Geoffrey Keating
+   sysv.S - Copyright (c) 1998 Geoffrey Keating
+   Copyright (C) 2007 Free Software Foundation, Inc
 
    PowerPC Assembly glue.
 
@@ -98,13 +99,17 @@
 	bctrl
 
 	/* Now, deal with the return value.  */
-	mtcrf	0x01,%r31
+	mtcrf	0x01,%r31 /* cr7  */
 	bt-	31,L(small_struct_return_value)
 	bt-	30,L(done_return_value)
 	bt-	29,L(fp_return_value)
 	stw	%r3,0(%r30)
 	bf+	28,L(done_return_value)
 	stw	%r4,4(%r30)
+	mtcrf	0x02,%r31 /* cr6  */
+	bf	27,L(done_return_value)
+	stw     %r5,8(%r30)
+	stw	%r6,12(%r30)
 	/* Fall through...  */
 
 L(done_return_value):
@@ -121,6 +126,9 @@
 L(fp_return_value):
 	bf	28,L(float_return_value)
 	stfd	%f1,0(%r30)
+	mtcrf   0x02,%r31 /* cr6  */
+	bf	27,L(done_return_value)
+	stfd	%f2,8(%r30)
 	b	L(done_return_value)
 L(float_return_value):
 	stfs	%f1,0(%r30)


More information about the Python-checkins mailing list