mirror of git://gcc.gnu.org/git/gcc.git
ffi_darwin.c: Add flag for longdouble return values.
2004-09-02 Andreas Tobler <a.tobler@schweiz.ch> * src/powerpc/ffi_darwin.c: Add flag for longdouble return values. (ffi_prep_args): Handle longdouble arguments. (ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for longdouble. (ffi_closure_helper_DARWIN): Add closure handling for longdouble. * src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble values. * src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise. * src/types.c: Defined longdouble size and alignment for darwin. From-SVN: r86992
This commit is contained in:
parent
16070e459c
commit
2fe7404ad4
|
@ -1,3 +1,15 @@
|
||||||
|
2004-09-02 Andreas Tobler <a.tobler@schweiz.ch>
|
||||||
|
|
||||||
|
* src/powerpc/ffi_darwin.c: Add flag for longdouble return values.
|
||||||
|
(ffi_prep_args): Handle longdouble arguments.
|
||||||
|
(ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for
|
||||||
|
longdouble.
|
||||||
|
(ffi_closure_helper_DARWIN): Add closure handling for longdouble.
|
||||||
|
* src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble
|
||||||
|
values.
|
||||||
|
* src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise.
|
||||||
|
* src/types.c: Defined longdouble size and alignment for darwin.
|
||||||
|
|
||||||
2004-09-02 Andreas Tobler <a.tobler@schweiz.ch>
|
2004-09-02 Andreas Tobler <a.tobler@schweiz.ch>
|
||||||
|
|
||||||
* src/powerpc/aix.S: Remove whitespaces.
|
* src/powerpc/aix.S: Remove whitespaces.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
darwin.S - Copyright (c) 2000 John Hornkvist
|
||||||
|
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||||
|
|
||||||
PowerPC Assembly glue.
|
PowerPC Assembly glue.
|
||||||
|
|
||||||
|
@ -142,12 +143,23 @@ L(done_return_value):
|
||||||
blr
|
blr
|
||||||
|
|
||||||
L(fp_return_value):
|
L(fp_return_value):
|
||||||
|
/* Do we have long double to store? */
|
||||||
|
bf 31,L(fd_return_value)
|
||||||
|
stfd f1,0(r30)
|
||||||
|
stfd f2,8(r30)
|
||||||
|
b L(done_return_value)
|
||||||
|
|
||||||
|
L(fd_return_value):
|
||||||
|
/* Do we have double to store? */
|
||||||
bf 28,L(float_return_value)
|
bf 28,L(float_return_value)
|
||||||
stfd f1,0(r30)
|
stfd f1,0(r30)
|
||||||
b L(done_return_value)
|
b L(done_return_value)
|
||||||
|
|
||||||
L(float_return_value):
|
L(float_return_value):
|
||||||
|
/* We only have a float to store. */
|
||||||
stfs f1,0(r30)
|
stfs f1,0(r30)
|
||||||
b L(done_return_value)
|
b L(done_return_value)
|
||||||
|
|
||||||
LFE1:
|
LFE1:
|
||||||
/* END(_ffi_call_DARWIN) */
|
/* END(_ffi_call_DARWIN) */
|
||||||
|
|
||||||
|
@ -218,6 +230,6 @@ LASFDE1:
|
||||||
.align 2
|
.align 2
|
||||||
LEFDE1:
|
LEFDE1:
|
||||||
.data
|
.data
|
||||||
.align 2
|
.align 2
|
||||||
LLFB0$non_lazy_ptr:
|
LLFB0$non_lazy_ptr:
|
||||||
.long LFB0
|
.long LFB0
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
darwin_closure.S - Copyright (c) 2002 2003 Free Software Foundation,
|
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||||
Inc. based on ppc_closure.S
|
Inc. based on ppc_closure.S
|
||||||
|
|
||||||
PowerPC Assembly glue.
|
PowerPC Assembly glue.
|
||||||
|
@ -42,8 +42,8 @@ LCFI0:
|
||||||
/* 24 Bytes (Linkage Area)
|
/* 24 Bytes (Linkage Area)
|
||||||
32 Bytes (outgoing parameter area, always reserved)
|
32 Bytes (outgoing parameter area, always reserved)
|
||||||
104 Bytes (13*8 from FPR)
|
104 Bytes (13*8 from FPR)
|
||||||
8 Bytes (result)
|
16 Bytes (result)
|
||||||
168 Bytes */
|
176 Bytes */
|
||||||
|
|
||||||
stwu r1,-176(r1) /* skip over caller save area
|
stwu r1,-176(r1) /* skip over caller save area
|
||||||
keep stack aligned to 16. */
|
keep stack aligned to 16. */
|
||||||
|
@ -150,9 +150,9 @@ Lret_type3:
|
||||||
/* case FFI_TYPE_LONGDOUBLE */
|
/* case FFI_TYPE_LONGDOUBLE */
|
||||||
Lret_type4:
|
Lret_type4:
|
||||||
lfd f1,0(r5)
|
lfd f1,0(r5)
|
||||||
|
lfd f2,8(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
|
||||||
|
|
||||||
/* case FFI_TYPE_UINT8 */
|
/* case FFI_TYPE_UINT8 */
|
||||||
Lret_type5:
|
Lret_type5:
|
||||||
|
@ -301,4 +301,4 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||||
.data
|
.data
|
||||||
.align 2
|
.align 2
|
||||||
LLFB1$non_lazy_ptr:
|
LLFB1$non_lazy_ptr:
|
||||||
.long LFB1
|
.long LFB1
|
||||||
|
|
|
@ -38,6 +38,7 @@ enum {
|
||||||
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||||
FLAG_RETURNS_FP = 1 << (31-29),
|
FLAG_RETURNS_FP = 1 << (31-29),
|
||||||
FLAG_RETURNS_64BITS = 1 << (31-28),
|
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||||
|
FLAG_RETURNS_128BITS = 1 << (31-31),
|
||||||
|
|
||||||
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||||
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||||
|
@ -86,7 +87,7 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||||
const unsigned flags = ecif->cif->flags;
|
const unsigned flags = ecif->cif->flags;
|
||||||
|
|
||||||
/* 'stacktop' points at the previous backchain pointer. */
|
/* 'stacktop' points at the previous backchain pointer. */
|
||||||
unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
|
unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
|
||||||
|
|
||||||
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
||||||
we use FPR registers. */
|
we use FPR registers. */
|
||||||
|
@ -95,7 +96,7 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||||
|
|
||||||
|
|
||||||
/* 'next_arg' grows up as we put parameters in it. */
|
/* 'next_arg' grows up as we put parameters in it. */
|
||||||
unsigned *next_arg = stack + 6; /* 6 reserved posistions. */
|
unsigned *next_arg = stack + 6; /* 6 reserved positions. */
|
||||||
|
|
||||||
int i = ecif->cif->nargs;
|
int i = ecif->cif->nargs;
|
||||||
double double_tmp;
|
double double_tmp;
|
||||||
|
@ -137,6 +138,7 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||||
fparg_count++;
|
fparg_count++;
|
||||||
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
double_tmp = *(double *)*p_argv;
|
double_tmp = *(double *)*p_argv;
|
||||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||||
|
@ -148,6 +150,26 @@ void ffi_prep_args(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:
|
||||||
|
double_tmp = ((double *)*p_argv)[0];
|
||||||
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||||
|
*(double *)next_arg = double_tmp;
|
||||||
|
else
|
||||||
|
*fpr_base++ = double_tmp;
|
||||||
|
next_arg += 2;
|
||||||
|
fparg_count++;
|
||||||
|
double_tmp = ((double *)*p_argv)[1];
|
||||||
|
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||||
|
*(double *)next_arg = double_tmp;
|
||||||
|
else
|
||||||
|
*fpr_base++ = double_tmp;
|
||||||
|
next_arg += 2;
|
||||||
|
fparg_count++;
|
||||||
|
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
*(long long *)next_arg = *(long long *)*p_argv;
|
*(long long *)next_arg = *(long long *)*p_argv;
|
||||||
|
@ -167,10 +189,6 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||||
goto putgpr;
|
goto putgpr;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
|
||||||
#endif
|
|
||||||
dest_cpy = (char *) next_arg;
|
dest_cpy = (char *) next_arg;
|
||||||
|
|
||||||
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
||||||
|
@ -240,10 +258,14 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||||
as the first argument. */
|
as the first argument. */
|
||||||
switch (cif->rtype->type)
|
switch (cif->rtype->type)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
flags |= FLAG_RETURNS_128BITS;
|
||||||
|
flags |= FLAG_RETURNS_FP;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
/* Fall through. */
|
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
flags |= FLAG_RETURNS_64BITS;
|
flags |= FLAG_RETURNS_64BITS;
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
@ -272,9 +294,8 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||||
|
|
||||||
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
||||||
first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
|
first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
|
||||||
goes on the stack. Structures and long doubles (if not equivalent
|
goes on the stack. Structures are passed as a pointer to a copy of
|
||||||
to double) are passed as a pointer to a copy of the structure.
|
the structure. Stuff on the stack needs to keep proper alignment. */
|
||||||
Stuff on the stack needs to keep proper alignment. */
|
|
||||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||||
{
|
{
|
||||||
switch ((*ptr)->type)
|
switch ((*ptr)->type)
|
||||||
|
@ -289,6 +310,19 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||||
intarg_count++;
|
intarg_count++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
fparg_count += 2;
|
||||||
|
/* If this FP arg is going on the stack, it must be
|
||||||
|
8-byte-aligned. */
|
||||||
|
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
||||||
|
&& intarg_count%2 != 0)
|
||||||
|
intarg_count++;
|
||||||
|
intarg_count +=2;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
/* 'long long' arguments are passed as two words, but
|
/* 'long long' arguments are passed as two words, but
|
||||||
|
@ -302,9 +336,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
|
||||||
#endif
|
|
||||||
size_al = (*ptr)->size;
|
size_al = (*ptr)->size;
|
||||||
/* If the first member of the struct is a double, then align
|
/* If the first member of the struct is a double, then align
|
||||||
the struct to double-word.
|
the struct to double-word.
|
||||||
|
@ -409,8 +440,8 @@ static void flush_range(char *, int);
|
||||||
points to one of these. */
|
points to one of these. */
|
||||||
|
|
||||||
typedef struct aix_fd_struct {
|
typedef struct aix_fd_struct {
|
||||||
void *code_pointer;
|
void *code_pointer;
|
||||||
void *toc;
|
void *toc;
|
||||||
} aix_fd;
|
} aix_fd;
|
||||||
|
|
||||||
/* here I'd like to add the stack frame layout we use in darwin_closure.S
|
/* here I'd like to add the stack frame layout we use in darwin_closure.S
|
||||||
|
@ -572,6 +603,13 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
||||||
pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
|
pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
|
||||||
pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
|
pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
|
||||||
|
|
||||||
|
typedef double ldbits[2];
|
||||||
|
|
||||||
|
union ldu
|
||||||
|
{
|
||||||
|
ldbits lb;
|
||||||
|
long double ld;
|
||||||
|
};
|
||||||
|
|
||||||
void ** avalue;
|
void ** avalue;
|
||||||
ffi_type ** arg_types;
|
ffi_type ** arg_types;
|
||||||
|
@ -581,6 +619,7 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
||||||
ffi_cif * cif;
|
ffi_cif * cif;
|
||||||
double temp;
|
double temp;
|
||||||
unsigned size_al;
|
unsigned size_al;
|
||||||
|
union ldu temp_ld;
|
||||||
|
|
||||||
cif = closure->cif;
|
cif = closure->cif;
|
||||||
avalue = alloca(cif->nargs * sizeof(void *));
|
avalue = alloca(cif->nargs * sizeof(void *));
|
||||||
|
@ -689,6 +728,34 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
||||||
pgr += 2;
|
pgr += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
|
||||||
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
|
/* A long double value consumes four GPRs and two FPRs.
|
||||||
|
There are 13 64bit floating point registers. */
|
||||||
|
if (nf < NUM_FPR_ARG_REGISTERS - 1)
|
||||||
|
{
|
||||||
|
avalue[i] = pfr;
|
||||||
|
pfr += 2;
|
||||||
|
}
|
||||||
|
/* Here we have the situation where one part of the long double
|
||||||
|
is stored in fpr13 and the other part is already on the stack.
|
||||||
|
We use a union to pass the long double to avalue[i]. */
|
||||||
|
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
|
||||||
|
{
|
||||||
|
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
|
||||||
|
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
|
||||||
|
avalue[i] = &temp_ld.ld;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
avalue[i] = pgr;
|
||||||
|
}
|
||||||
|
nf += 2;
|
||||||
|
ng += 4;
|
||||||
|
pgr += 4;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
FFI_ASSERT(0);
|
FFI_ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,11 +80,16 @@ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||||
#endif
|
#endif
|
||||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||||
|
|
||||||
#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
|
#elif defined ARM || defined SH || defined POWERPC_AIX
|
||||||
|
|
||||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
|
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
|
||||||
|
|
||||||
|
#elif defined POWERPC_DARWIN
|
||||||
|
|
||||||
|
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||||
|
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||||
|
|
||||||
#elif defined SPARC
|
#elif defined SPARC
|
||||||
|
|
||||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||||
|
|
Loading…
Reference in New Issue