Commit 75b8b1be by Alan Modra Committed by Alan Modra

ffitarget.h (enum ffi_abi): Add FFI_LINUX.

	* src/powerpc/ffitarget.h (enum ffi_abi): Add FFI_LINUX.  Default
	for 32-bit using IBM extended double format.  Fix FFI_LAST_ABI.
	* src/powerpc/ffi.c (ffi_prep_args_SYSV): Handle linux variant of
	FFI_TYPE_LONGDOUBLE.
	(ffi_prep_args64): Assert using IBM extended double.
	(ffi_prep_cif_machdep): Don't munge FFI_TYPE_LONGDOUBLE type.
	Handle FFI_LINUX FFI_TYPE_LONGDOUBLE return and args.
	(ffi_call): Handle FFI_LINUX.
	(ffi_closure_helper_SYSV): Non FFI_LINUX long double return needs
	gpr3 return pointer as for struct return.  Handle FFI_LINUX
	FFI_TYPE_LONGDOUBLE return and args.  Don't increment "nf"
	unnecessarily.
	* src/powerpc/ppc_closure.S (ffi_closure_SYSV): Load both f1 and f2
	for FFI_TYPE_LONGDOUBLE.  Move epilogue insns into case table.
	Don't use r6 as pointer to results, instead use sp offset.  Don't
	make a special call to load lr with case table address, instead
	use offset from previous call.
	* src/powerpc/sysv.S (ffi_call_SYSV): Save long double return.
	* src/powerpc/linux64.S (ffi_call_LINUX64): Simplify long double
	return.

From-SVN: r112340
parent 5b314bb3
2006-03-24 Alan Modra <amodra@bigpond.net.au>
* src/powerpc/ffitarget.h (enum ffi_abi): Add FFI_LINUX. Default
for 32-bit using IBM extended double format. Fix FFI_LAST_ABI.
* src/powerpc/ffi.c (ffi_prep_args_SYSV): Handle linux variant of
FFI_TYPE_LONGDOUBLE.
(ffi_prep_args64): Assert using IBM extended double.
(ffi_prep_cif_machdep): Don't munge FFI_TYPE_LONGDOUBLE type.
Handle FFI_LINUX FFI_TYPE_LONGDOUBLE return and args.
(ffi_call): Handle FFI_LINUX.
(ffi_closure_helper_SYSV): Non FFI_LINUX long double return needs
gpr3 return pointer as for struct return. Handle FFI_LINUX
FFI_TYPE_LONGDOUBLE return and args. Don't increment "nf"
unnecessarily.
* src/powerpc/ppc_closure.S (ffi_closure_SYSV): Load both f1 and f2
for FFI_TYPE_LONGDOUBLE. Move epilogue insns into case table.
Don't use r6 as pointer to results, instead use sp offset. Don't
make a special call to load lr with case table address, instead
use offset from previous call.
* src/powerpc/sysv.S (ffi_call_SYSV): Save long double return.
* src/powerpc/linux64.S (ffi_call_LINUX64): Simplify long double
return.
2006-03-15 Kaz Kojima <kkojima@gcc.gnu.org> 2006-03-15 Kaz Kojima <kkojima@gcc.gnu.org>
* src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments * src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments
......
...@@ -197,6 +197,38 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) ...@@ -197,6 +197,38 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
break; break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (ecif->cif->abi != FFI_LINUX)
goto do_struct;
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_UINT64:
case FFI_TYPE_SINT64: case FFI_TYPE_SINT64:
if (intarg_count == NUM_GPR_ARG_REGISTERS-1) if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
...@@ -232,7 +264,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) ...@@ -232,7 +264,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: do_struct:
#endif #endif
struct_copy_size = ((*ptr)->size + 15) & ~0xF; struct_copy_size = ((*ptr)->size + 15) & ~0xF;
copy_space.c -= struct_copy_size; copy_space.c -= struct_copy_size;
...@@ -433,6 +465,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) ...@@ -433,6 +465,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
if (fparg_count < NUM_FPR_ARG_REGISTERS64) if (fparg_count < NUM_FPR_ARG_REGISTERS64)
*fpr_base.d++ = double_tmp; *fpr_base.d++ = double_tmp;
fparg_count++; fparg_count++;
FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
break; break;
#endif #endif
...@@ -536,11 +569,6 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -536,11 +569,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
/* Space for the mandatory parm save area and general registers. */ /* Space for the mandatory parm save area and general registers. */
bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long); 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: /* Return value handling. The rules for SYSV are as follows:
...@@ -549,14 +577,24 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -549,14 +577,24 @@ ffi_prep_cif_machdep (ffi_cif *cif)
- 64-bit integer values and structures between 5 and 8 bytes are returned - 64-bit integer values and structures between 5 and 8 bytes are returned
in gpr3 and gpr4; in gpr3 and gpr4;
- Single/double FP values are returned in fpr1; - Single/double FP values are returned in fpr1;
- Larger structures and long double (if not equivalent to double) values - Larger structures are allocated space and a pointer is passed as
are allocated space and a pointer is passed as the first argument. 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: For LINUX64:
- integer values in gpr3; - integer values in gpr3;
- Structures/Unions by reference; - 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. */
switch (type) switch (type)
{ {
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64)
goto byref;
flags |= FLAG_RETURNS_128BITS;
/* Fall through. */
#endif
case FFI_TYPE_DOUBLE: case FFI_TYPE_DOUBLE:
flags |= FLAG_RETURNS_64BITS; flags |= FLAG_RETURNS_64BITS;
/* Fall through. */ /* Fall through. */
...@@ -598,15 +636,8 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -598,15 +636,8 @@ ffi_prep_cif_machdep (ffi_cif *cif)
} }
} }
} }
/* else fall through. */
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: byref:
if (type == FFI_TYPE_LONGDOUBLE && cif->abi == FFI_LINUX64)
{
flags |= FLAG_RETURNS_128BITS;
flags |= FLAG_RETURNS_FP;
break;
}
#endif #endif
intarg_count++; intarg_count++;
flags |= FLAG_RETVAL_REFERENCE; flags |= FLAG_RETVAL_REFERENCE;
...@@ -635,6 +666,13 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -635,6 +666,13 @@ ffi_prep_cif_machdep (ffi_cif *cif)
/* floating singles are not 8-aligned on stack */ /* floating singles are not 8-aligned on stack */
break; break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (cif->abi != FFI_LINUX)
goto do_struct;
fparg_count++;
/* Fall thru */
#endif
case FFI_TYPE_DOUBLE: case FFI_TYPE_DOUBLE:
fparg_count++; fparg_count++;
/* If this FP arg is going on the stack, it must be /* If this FP arg is going on the stack, it must be
...@@ -664,7 +702,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) ...@@ -664,7 +702,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE: do_struct:
#endif #endif
/* We must allocate space for a copy of these to enforce /* We must allocate space for a copy of these to enforce
pass-by-value. Pad the space up to a multiple of 16 pass-by-value. Pad the space up to a multiple of 16
...@@ -793,6 +831,7 @@ ffi_call(/*@dependent@*/ ffi_cif *cif, ...@@ -793,6 +831,7 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
#ifndef POWERPC64 #ifndef POWERPC64
case FFI_SYSV: case FFI_SYSV:
case FFI_GCC_SYSV: case FFI_GCC_SYSV:
case FFI_LINUX:
/*@-usedef@*/ /*@-usedef@*/
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn); ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
/*@=usedef@*/ /*@=usedef@*/
...@@ -920,14 +959,17 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, ...@@ -920,14 +959,17 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
For FFI_SYSV the result is passed in r3/r4 if the struct size is less For FFI_SYSV the result is passed in r3/r4 if the struct size is less
or equal 8 bytes. */ 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)
#endif
)
{ {
if (!((cif->abi == FFI_SYSV) && (size <= 8))) rvalue = (void *) *pgr;
{ ng++;
rvalue = (void *) *pgr; pgr++;
ng++;
pgr++;
}
} }
i = 0; i = 0;
...@@ -989,6 +1031,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, ...@@ -989,6 +1031,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
break; break;
case FFI_TYPE_STRUCT: 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 /* Structs are passed by reference. The address will appear in a
gpr if it is one of the first 8 arguments. */ gpr if it is one of the first 8 arguments. */
if (ng < 8) if (ng < 8)
...@@ -1060,7 +1105,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, ...@@ -1060,7 +1105,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
* naughty thing to do but... * naughty thing to do but...
*/ */
avalue[i] = pst; avalue[i] = pst;
nf++;
pst += 1; pst += 1;
} }
break; break;
...@@ -1080,11 +1124,32 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, ...@@ -1080,11 +1124,32 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
if (((long) pst) & 4) if (((long) pst) & 4)
pst++; pst++;
avalue[i] = pst; avalue[i] = pst;
nf++;
pst += 2; pst += 2;
} }
break; break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (cif->abi != FFI_LINUX)
goto do_struct;
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: default:
FFI_ASSERT (0); FFI_ASSERT (0);
} }
...@@ -1101,8 +1166,12 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, ...@@ -1101,8 +1166,12 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
&& size <= 8) && size <= 8)
return FFI_SYSV_TYPE_SMALL_STRUCT + size; return FFI_SYSV_TYPE_SMALL_STRUCT + size;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_LINUX)
return FFI_TYPE_STRUCT;
#endif
return cif->rtype->type; return cif->rtype->type;
} }
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *, int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
......
...@@ -43,10 +43,15 @@ typedef enum ffi_abi { ...@@ -43,10 +43,15 @@ typedef enum ffi_abi {
FFI_SYSV, FFI_SYSV,
FFI_GCC_SYSV, FFI_GCC_SYSV,
FFI_LINUX64, FFI_LINUX64,
FFI_LINUX,
# ifdef POWERPC64 # ifdef POWERPC64
FFI_DEFAULT_ABI = FFI_LINUX64, FFI_DEFAULT_ABI = FFI_LINUX64,
# else # else
# if __LDBL_MANT_DIG__ == 106
FFI_DEFAULT_ABI = FFI_LINUX,
# else
FFI_DEFAULT_ABI = FFI_GCC_SYSV, FFI_DEFAULT_ABI = FFI_GCC_SYSV,
# endif
# endif # endif
#endif #endif
...@@ -69,7 +74,7 @@ typedef enum ffi_abi { ...@@ -69,7 +74,7 @@ typedef enum ffi_abi {
FFI_DEFAULT_ABI = FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV,
#endif #endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_LAST_ABI
} ffi_abi; } ffi_abi;
#endif #endif
......
...@@ -120,12 +120,9 @@ ffi_call_LINUX64: ...@@ -120,12 +120,9 @@ ffi_call_LINUX64:
blr blr
.Lfp_return_value: .Lfp_return_value:
bt 27, .Lfd_return_value
bf 28, .Lfloat_return_value bf 28, .Lfloat_return_value
stfd %f1, 0(%r30) stfd %f1, 0(%r30)
b .Ldone_return_value bf 27, .Ldone_return_value
.Lfd_return_value:
stfd %f1, 0(%r30)
stfd %f2, 8(%r30) stfd %f2, 8(%r30)
b .Ldone_return_value b .Ldone_return_value
.Lfloat_return_value: .Lfloat_return_value:
......
...@@ -58,218 +58,178 @@ ENTRY(ffi_closure_SYSV) ...@@ -58,218 +58,178 @@ ENTRY(ffi_closure_SYSV)
# make the call # make the call
bl ffi_closure_helper_SYSV@local bl ffi_closure_helper_SYSV@local
.Lret:
# now r3 contains the return type # now r3 contains the return type
# so use it to look up in a table # so use it to look up in a table
# so we know how to deal with each type # so we know how to deal with each type
# look up the proper starting point in table # look up the proper starting point in table
# by using return type as offset # 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 address of .Lret to r4
mflr %r4 # move to r4 slwi %r3,%r3,4 # now multiply return type by 16
slwi %r3,%r3,4 # now multiply return type by 16 addi %r4, %r4, .Lret_type0 - .Lret
add %r3,%r3,%r4 # add contents of table to table address lwz %r0,148(%r1)
add %r3,%r3,%r4 # add contents of table to table address
mtctr %r3 mtctr %r3
bctr # jump to it bctr # jump to it
.LFE1: .LFE1:
# Each of the ret_typeX code fragments has to be exactly 16 bytes long # 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 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
# first. # first.
.align 4 .align 4
nop
nop
nop
.Lget_ret_type0_addr:
blrl
# case FFI_TYPE_VOID # case FFI_TYPE_VOID
.Lret_type0: .Lret_type0:
b .Lfinish mtlr %r0
nop addi %r1,%r1,144
nop blr
nop nop
# case FFI_TYPE_INT # case FFI_TYPE_INT
.Lret_type1: lwz %r3,112+0(%r1)
lwz %r3,0(%r6) mtlr %r0
b .Lfinish .Lfinish:
nop addi %r1,%r1,144
nop blr
# case FFI_TYPE_FLOAT # case FFI_TYPE_FLOAT
.Lret_type2: lfs %f1,112+0(%r1)
lfs %f1,0(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_DOUBLE # case FFI_TYPE_DOUBLE
.Lret_type3: lfd %f1,112+0(%r1)
lfd %f1,0(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_LONGDOUBLE # case FFI_TYPE_LONGDOUBLE
.Lret_type4: lfd %f1,112+0(%r1)
lfd %f1,0(%r6) lfd %f2,112+8(%r1)
mtlr %r0
b .Lfinish b .Lfinish
nop
nop
# case FFI_TYPE_UINT8 # case FFI_TYPE_UINT8
.Lret_type5: lbz %r3,112+3(%r1)
lbz %r3,3(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_SINT8 # case FFI_TYPE_SINT8
.Lret_type6: lbz %r3,112+3(%r1)
lbz %r3,3(%r6)
extsb %r3,%r3 extsb %r3,%r3
mtlr %r0
b .Lfinish b .Lfinish
nop
# case FFI_TYPE_UINT16 # case FFI_TYPE_UINT16
.Lret_type7: lhz %r3,112+2(%r1)
lhz %r3,2(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_SINT16 # case FFI_TYPE_SINT16
.Lret_type8: lha %r3,112+2(%r1)
lha %r3,2(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_UINT32 # case FFI_TYPE_UINT32
.Lret_type9: lwz %r3,112+0(%r1)
lwz %r3,0(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_SINT32 # case FFI_TYPE_SINT32
.Lret_type10: lwz %r3,112+0(%r1)
lwz %r3,0(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# case FFI_TYPE_UINT64 # case FFI_TYPE_UINT64
.Lret_type11: lwz %r3,112+0(%r1)
lwz %r3,0(%r6) lwz %r4,112+4(%r1)
lwz %r4,4(%r6) mtlr %r0
b .Lfinish b .Lfinish
nop
# case FFI_TYPE_SINT64 # case FFI_TYPE_SINT64
.Lret_type12: lwz %r3,112+0(%r1)
lwz %r3,0(%r6) lwz %r4,112+4(%r1)
lwz %r4,4(%r6) mtlr %r0
b .Lfinish b .Lfinish
nop
# case FFI_TYPE_STRUCT # case FFI_TYPE_STRUCT
.Lret_type13: mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
nop nop
# case FFI_TYPE_POINTER # case FFI_TYPE_POINTER
.Lret_type14: lwz %r3,112+0(%r1)
lwz %r3,0(%r6) mtlr %r0
b .Lfinish addi %r1,%r1,144
nop blr
nop
# The return types below are only used when the ABI type is FFI_SYSV. # The return types below are only used when the ABI type is FFI_SYSV.
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
.Lret_type15: lbz %r3,112+0(%r1)
# fall through. mtlr %r0
lbz %r3,0(%r6) addi %r1,%r1,144
b .Lfinish blr
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
.Lret_type16: lhz %r3,112+0(%r1)
# fall through. mtlr %r0
lhz %r3,0(%r6) addi %r1,%r1,144
b .Lfinish blr
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
.Lret_type17: lwz %r3,112+0(%r1)
# fall through.
lwz %r3,0(%r6)
srwi %r3,%r3,8 srwi %r3,%r3,8
mtlr %r0
b .Lfinish b .Lfinish
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
.Lret_type18: lwz %r3,112+0(%r1)
# this one handles the structs from above too. mtlr %r0
lwz %r3,0(%r6) addi %r1,%r1,144
b .Lfinish blr
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
.Lret_type19: lwz %r3,112+0(%r1)
# fall through. lwz %r4,112+4(%r1)
lwz %r3,0(%r6)
lwz %r4,4(%r6)
li %r5,24 li %r5,24
b .Lstruct567 b .Lstruct567
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
.Lret_type20: lwz %r3,112+0(%r1)
# fall through. lwz %r4,112+4(%r1)
lwz %r3,0(%r6)
lwz %r4,4(%r6)
li %r5,16 li %r5,16
b .Lstruct567 b .Lstruct567
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
.Lret_type21: lwz %r3,112+0(%r1)
# fall through. lwz %r4,112+4(%r1)
lwz %r3,0(%r6)
lwz %r4,4(%r6)
li %r5,8 li %r5,8
b .Lstruct567 b .Lstruct567
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
.Lret_type22: lwz %r3,112+0(%r1)
# this one handles the above unhandled structs. lwz %r4,112+4(%r1)
lwz %r3,0(%r6) mtlr %r0
lwz %r4,4(%r6)
b .Lfinish b .Lfinish
nop
# case done .Lstruct567:
.Lfinish: subfic %r6,%r5,32
srw %r4,%r4,%r5
lwz %r0,148(%r1) slw %r6,%r3,%r6
srw %r3,%r3,%r5
or %r4,%r6,%r4
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
blr 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) END(ffi_closure_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits .section ".eh_frame",EH_FRAME_FLAGS,@progbits
......
...@@ -121,6 +121,8 @@ L(done_return_value): ...@@ -121,6 +121,8 @@ L(done_return_value):
L(fp_return_value): L(fp_return_value):
bf 28,L(float_return_value) bf 28,L(float_return_value)
stfd %f1,0(%r30) stfd %f1,0(%r30)
bf 27,L(done_return_value)
stfd %f2,8(%r30)
b L(done_return_value) b L(done_return_value)
L(float_return_value): L(float_return_value):
stfs %f1,0(%r30) stfs %f1,0(%r30)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment