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
This commit is contained in:
parent
5b314bb3ef
commit
75b8b1becb
|
@ -1,3 +1,26 @@
|
|||
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>
|
||||
|
||||
* 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)
|
|||
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
||||
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_SINT64:
|
||||
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
|
||||
|
@ -232,7 +264,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
|
||||
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;
|
||||
|
@ -433,6 +465,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
|
|||
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
|
||||
|
@ -536,11 +569,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
|
||||
/* 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,14 +577,24 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
- 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. */
|
||||
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:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
/* Fall through. */
|
||||
|
@ -598,15 +636,8 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
}
|
||||
}
|
||||
}
|
||||
/* 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;
|
||||
|
@ -635,6 +666,13 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
/* 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)
|
||||
goto do_struct;
|
||||
fparg_count++;
|
||||
/* Fall thru */
|
||||
#endif
|
||||
case FFI_TYPE_DOUBLE:
|
||||
fparg_count++;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
|
@ -664,7 +702,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
|
||||
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
|
||||
|
@ -793,6 +831,7 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
#ifndef POWERPC64
|
||||
case FFI_SYSV:
|
||||
case FFI_GCC_SYSV:
|
||||
case FFI_LINUX:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
|
@ -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
|
||||
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++;
|
||||
pgr++;
|
||||
}
|
||||
rvalue = (void *) *pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
@ -989,6 +1031,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
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)
|
||||
|
@ -1060,7 +1105,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
* naughty thing to do but...
|
||||
*/
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst += 1;
|
||||
}
|
||||
break;
|
||||
|
@ -1080,11 +1124,32 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
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)
|
||||
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:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
|
@ -1101,8 +1166,12 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& size <= 8)
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
|
||||
|
|
|
@ -43,10 +43,15 @@ typedef enum ffi_abi {
|
|||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_LINUX,
|
||||
# ifdef POWERPC64
|
||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||
# else
|
||||
# if __LDBL_MANT_DIG__ == 106
|
||||
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -69,7 +74,7 @@ typedef enum ffi_abi {
|
|||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
FFI_LAST_ABI
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -120,12 +120,9 @@ ffi_call_LINUX64:
|
|||
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)
|
||||
bf 27, .Ldone_return_value
|
||||
stfd %f2, 8(%r30)
|
||||
b .Ldone_return_value
|
||||
.Lfloat_return_value:
|
||||
|
|
|
@ -58,218 +58,178 @@ ENTRY(ffi_closure_SYSV)
|
|||
|
||||
# make the call
|
||||
bl ffi_closure_helper_SYSV@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
|
||||
|
||||
# case FFI_TYPE_DOUBLE
|
||||
.Lret_type3:
|
||||
lfd %f1,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
.Lret_type4:
|
||||
lfd %f1,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
.Lret_type5:
|
||||
lbz %r3,3(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
.Lret_type6:
|
||||
lbz %r3,3(%r6)
|
||||
extsb %r3,%r3
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT16
|
||||
.Lret_type7:
|
||||
lhz %r3,2(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
.Lret_type8:
|
||||
lha %r3,2(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
.Lret_type9:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
.Lret_type10:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
.Lret_type11:
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT64
|
||||
.Lret_type12:
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_STRUCT
|
||||
.Lret_type13:
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
.Lret_type14:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# 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
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
.Lret_type16:
|
||||
# fall through.
|
||||
lhz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
.Lret_type17:
|
||||
# fall through.
|
||||
lwz %r3,0(%r6)
|
||||
srwi %r3,%r3,8
|
||||
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
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
.Lret_type19:
|
||||
# fall through.
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case done
|
||||
.Lfinish:
|
||||
|
||||
lwz %r0,148(%r1)
|
||||
lfs %f1,112+0(%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
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
lfd %f2,112+8(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
extsb %r3,%r3
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_SINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# The return types below are only used when the ABI type is FFI_SYSV.
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
|
||||
lbz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
lhz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
srwi %r3,%r3,8
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .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
|
||||
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
|
|
|
@ -121,6 +121,8 @@ L(done_return_value):
|
|||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd %f1,0(%r30)
|
||||
bf 27,L(done_return_value)
|
||||
stfd %f2,8(%r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs %f1,0(%r30)
|
||||
|
|
Loading…
Reference in New Issue