Merge from gcc

This commit is contained in:
green
2008-01-29 12:28:15 +00:00
parent e680ecfbfc
commit ccabd2b16b
119 changed files with 9458 additions and 9444 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,11 @@
/* -----------------------------------------------------------------------
ffi_darwin.c
ffi.c - Copyright (c) 1998 Geoffrey Keating
Copyright (C) 1998 Geoffrey Keating
Copyright (C) 2001 John Hornkvist
Copyright (C) 2002, 2006 Free Software Foundation, Inc.
PowerPC Foreign Function Interface
Darwin ABI support (c) 2001 John Hornkvist
AIX ABI support (c) 2002 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
@@ -80,7 +79,9 @@ 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;
@@ -226,48 +227,6 @@ 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)
{
@@ -280,16 +239,8 @@ 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. */
@@ -424,12 +375,25 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
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)());
/*@-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@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
@@ -442,7 +406,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -450,12 +416,16 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_AIX:
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);
/*@=usedef@*/
break;
case FFI_DARWIN:
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);
/*@=usedef@*/
break;
default:
FFI_ASSERT(0);

View File

@@ -43,15 +43,10 @@ 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
@@ -74,7 +69,7 @@ typedef enum ffi_abi {
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
FFI_LAST_ABI
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif

View File

@@ -120,9 +120,12 @@ ffi_call_LINUX64:
blr
.Lfp_return_value:
bt 27, .Lfd_return_value
bf 28, .Lfloat_return_value
stfd %f1, 0(%r30)
bf 27, .Ldone_return_value
b .Ldone_return_value
.Lfd_return_value:
stfd %f1, 0(%r30)
stfd %f2, 8(%r30)
b .Ldone_return_value
.Lfloat_return_value:

View File

@@ -58,178 +58,223 @@ 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
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
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
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:
mtlr %r0
addi %r1,%r1,144
blr
b .Lfinish
nop
nop
nop
# case FFI_TYPE_INT
lwz %r3,112+0(%r1)
mtlr %r0
.Lfinish:
addi %r1,%r1,144
blr
.Lret_type1:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_FLOAT
lfs %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type2:
lfs %f1,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_DOUBLE
lfd %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type3:
lfd %f1,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_LONGDOUBLE
lfd %f1,112+0(%r1)
lfd %f2,112+8(%r1)
mtlr %r0
.Lret_type4:
lfd %f1,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT8
lbz %r3,112+3(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type5:
lbz %r3,3(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT8
lbz %r3,112+3(%r1)
.Lret_type6:
lbz %r3,3(%r6)
extsb %r3,%r3
mtlr %r0
b .Lfinish
nop
# case FFI_TYPE_UINT16
lhz %r3,112+2(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type7:
lhz %r3,2(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT16
lha %r3,112+2(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type8:
lha %r3,2(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT32
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type9:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT32
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type10:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT64
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
mtlr %r0
.Lret_type11:
lwz %r3,0(%r6)
lwz %r4,4(%r6)
b .Lfinish
nop
# case FFI_TYPE_SINT64
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
mtlr %r0
.Lret_type12:
lwz %r3,0(%r6)
lwz %r4,4(%r6)
b .Lfinish
nop
# case FFI_TYPE_STRUCT
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type13:
b .Lfinish
nop
nop
nop
# case FFI_TYPE_POINTER
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.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.
lbz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type15:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
lhz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type16:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
lwz %r3,112+0(%r1)
srwi %r3,%r3,8
mtlr %r0
b .Lfinish
.Lret_type17:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.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.
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
li %r5,24
b .Lstruct567
.Lret_type19:
# fall through.
nop
nop
nop
nop
# 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
.Lret_type20:
# fall through.
nop
nop
nop
nop
# 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
.Lret_type21:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
mtlr %r0
.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
.Lstruct567:
subfic %r6,%r5,32
srw %r4,%r4,%r5
slw %r6,%r3,%r6
srw %r3,%r3,%r5
or %r4,%r6,%r4
# case done
.Lfinish:
lwz %r0,148(%r1)
mtlr %r0
addi %r1,%r1,144
blr
END(ffi_closure_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits

View File

@@ -121,8 +121,6 @@ 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)
@@ -142,14 +140,8 @@ 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. */
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):
bl __ashldi3 /* libgcc function to shift r3/r4,
shift value in r5. */
stw %r3,0(%r30)
stw %r4,4(%r30)
b L(done_return_value)