Latest gcc svn sources
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Geoffrey Keating
|
||||
ffi_darwin.c
|
||||
|
||||
PowerPC Foreign Function Interface
|
||||
|
||||
Darwin ABI support (c) 2001 John Hornkvist
|
||||
AIX ABI support (c) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998 Geoffrey Keating
|
||||
Copyright (C) 2001 John Hornkvist
|
||||
Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
FFI support for Darwin and AIX.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
@@ -79,9 +80,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
@@ -227,6 +226,48 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
}
|
||||
|
||||
/* Adjust the size of S to be correct for Darwin.
|
||||
On Darwin, the first field of a structure has natural alignment. */
|
||||
|
||||
static void
|
||||
darwin_adjust_aggregate_sizes (ffi_type *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->type != FFI_TYPE_STRUCT)
|
||||
return;
|
||||
|
||||
s->size = 0;
|
||||
for (i = 0; s->elements[i] != NULL; i++)
|
||||
{
|
||||
ffi_type *p;
|
||||
int align;
|
||||
|
||||
p = s->elements[i];
|
||||
darwin_adjust_aggregate_sizes (p);
|
||||
if (i == 0
|
||||
&& (p->type == FFI_TYPE_UINT64
|
||||
|| p->type == FFI_TYPE_SINT64
|
||||
|| p->type == FFI_TYPE_DOUBLE
|
||||
|| p->alignment == 8))
|
||||
align = 8;
|
||||
else if (p->alignment == 16 || p->alignment < 4)
|
||||
align = p->alignment;
|
||||
else
|
||||
align = 4;
|
||||
s->size = ALIGN(s->size, align) + p->size;
|
||||
}
|
||||
|
||||
s->size = ALIGN(s->size, s->alignment);
|
||||
|
||||
if (s->elements[0]->type == FFI_TYPE_UINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_SINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_DOUBLE
|
||||
|| s->elements[0]->alignment == 8)
|
||||
s->alignment = s->alignment > 8 ? s->alignment : 8;
|
||||
/* Do not add additional tail padding. */
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
@@ -239,8 +280,16 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
unsigned size_al = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
All the calculation of structure sizes will also be wrong.
|
||||
Redo the calculation for DARWIN. */
|
||||
|
||||
if (cif->abi == FFI_DARWIN)
|
||||
{
|
||||
darwin_adjust_aggregate_sizes (cif->rtype);
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
darwin_adjust_aggregate_sizes (cif->arg_types[i]);
|
||||
}
|
||||
|
||||
/* Space for the frame pointer, callee's LR, CR, etc, and for
|
||||
the asm's temp regs. */
|
||||
|
||||
@@ -375,25 +424,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_AIX(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(),
|
||||
void (*fn2)());
|
||||
extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(),
|
||||
void (*fn2)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(), void (*fn2)());
|
||||
extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(), void (*fn2)());
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
@@ -406,9 +442,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
@@ -416,16 +450,12 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_AIX:
|
||||
/*@-usedef@*/
|
||||
ffi_call_AIX(&ecif, -cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn, ffi_prep_args);
|
||||
/*@=usedef@*/
|
||||
ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
case FFI_DARWIN:
|
||||
/*@-usedef@*/
|
||||
ffi_call_DARWIN(&ecif, -cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn, ffi_prep_args);
|
||||
/*@=usedef@*/
|
||||
ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
@@ -498,10 +528,11 @@ SP current --> +---------------------------------------+ 176 <- parent frame
|
||||
|
||||
*/
|
||||
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)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
struct ffi_aix_trampoline_struct *tramp_aix;
|
||||
@@ -523,14 +554,14 @@ ffi_prep_closure (ffi_closure* closure,
|
||||
tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
|
||||
tramp[3] = (unsigned long) closure; /* context */
|
||||
tramp[3] = (unsigned long) codeloc; /* context */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. Only necessary on Darwin. */
|
||||
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
break;
|
||||
|
||||
@@ -543,7 +574,7 @@ ffi_prep_closure (ffi_closure* closure,
|
||||
|
||||
tramp_aix->code_pointer = fd->code_pointer;
|
||||
tramp_aix->toc = fd->toc;
|
||||
tramp_aix->static_chain = closure;
|
||||
tramp_aix->static_chain = codeloc;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
@@ -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
|
||||
@@ -43,10 +44,20 @@ typedef enum ffi_abi {
|
||||
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 +80,7 @@ typedef enum ffi_abi {
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
FFI_LAST_ABI
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
@@ -78,8 +89,14 @@ typedef enum ffi_abi {
|
||||
#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
|
||||
|
||||
@@ -47,8 +47,8 @@ ffi_call_LINUX64:
|
||||
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 @@ ffi_call_LINUX64:
|
||||
/* 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 @@ ffi_call_LINUX64:
|
||||
|
||||
.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 @@ 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)
|
||||
mtcrf 0x02, %r31 /* cr6 */
|
||||
bf 27, .Ldone_return_value
|
||||
stfd %f2, 8(%r30)
|
||||
b .Ldone_return_value
|
||||
.Lfloat_return_value:
|
||||
|
||||
@@ -28,6 +28,7 @@ ENTRY(ffi_closure_SYSV)
|
||||
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 @@ ENTRY(ffi_closure_SYSV)
|
||||
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,223 +60,190 @@ 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
|
||||
|
||||
# Extract the size of the return type for small structures.
|
||||
# Then calculate (4 - size) and multiply the result by 8.
|
||||
# This gives the value needed for the shift operation below.
|
||||
# This part is only needed for FFI_SYSV and small structures.
|
||||
addi %r5,%r3,-(FFI_SYSV_TYPE_SMALL_STRUCT)
|
||||
cmpwi cr0,%r5,4
|
||||
ble cr0,.Lnext
|
||||
addi %r5,%r5,-4
|
||||
.Lnext:
|
||||
addi %r5,%r5,-4
|
||||
neg %r5,%r5
|
||||
slwi %r5,%r5,3
|
||||
|
||||
# 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
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_INT
|
||||
.Lret_type1:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# 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.
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
.Lret_type16:
|
||||
# fall through.
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
.Lret_type17:
|
||||
# fall through.
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
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)
|
||||
srw %r3,%r3,%r5
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
.Lret_type19:
|
||||
# fall through.
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
|
||||
.Lret_type20:
|
||||
# fall through.
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
|
||||
.Lret_type21:
|
||||
# fall through.
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# 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)
|
||||
bl __lshrdi3 # libgcc function to shift r3/r4, shift value in r5.
|
||||
b .Lfinish
|
||||
|
||||
# case done
|
||||
.Lfinish:
|
||||
|
||||
lwz %r0,148(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_INT
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# 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
|
||||
|
||||
# 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.
|
||||
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
|
||||
|
||||
.Luint128:
|
||||
lwz %r6,112+12(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
|
||||
@@ -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 @@ ENTRY(ffi_call_SYSV)
|
||||
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(done_return_value):
|
||||
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)
|
||||
@@ -140,8 +148,14 @@ L(smst_one_register):
|
||||
b L(done_return_value)
|
||||
L(smst_two_register):
|
||||
rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
|
||||
bl __ashldi3 /* libgcc function to shift r3/r4,
|
||||
shift value in r5. */
|
||||
cmpwi %r5,0
|
||||
subfic %r9,%r5,32
|
||||
slw %r29,%r3,%r5
|
||||
srw %r9,%r4,%r9
|
||||
beq- L(smst_8byte)
|
||||
or %r3,%r9,%r29
|
||||
slw %r4,%r4,%r5
|
||||
L(smst_8byte):
|
||||
stw %r3,0(%r30)
|
||||
stw %r4,4(%r30)
|
||||
b L(done_return_value)
|
||||
|
||||
Reference in New Issue
Block a user