[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