mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54:07 +08:00
re PR libffi/13141 (FAIL: InvokeReturn output - source compiled test <libffi problem>)
2004-08-23 David Daney <daney@avtrex.com> PR libgcj/13141 * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI. * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation. (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point parameters and return types. (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI. (ffi_prep_closure): Ditto. (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix alignment calculations. * src/mips/o32.S (ffi_closure_O32): Don't use floating point instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant. From-SVN: r86429
This commit is contained in:
parent
106a720099
commit
39dca114a9
@ -1,3 +1,17 @@
|
||||
2004-08-23 David Daney <daney@avtrex.com>
|
||||
|
||||
PR libgcj/13141
|
||||
* src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI.
|
||||
* src/mips/ffi.c (ffi_prep_args): Fix alignment calculation.
|
||||
(ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point
|
||||
parameters and return types.
|
||||
(ffi_call): Handle FFI_O32_SOFT_FLOAT ABI.
|
||||
(ffi_prep_closure): Ditto.
|
||||
(ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix
|
||||
alignment calculations.
|
||||
* src/mips/o32.S (ffi_closure_O32): Don't use floating point
|
||||
instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant.
|
||||
|
||||
2004-08-14 Casey Marshall <csm@gnu.org>
|
||||
|
||||
* src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to
|
||||
|
@ -85,10 +85,15 @@ static void ffi_prep_args(char *stack,
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
unsigned short a;
|
||||
|
||||
/* Align if necessary */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
||||
a = (*p_arg)->alignment;
|
||||
if (a < FFI_SIZEOF_ARG)
|
||||
a = FFI_SIZEOF_ARG;
|
||||
|
||||
if ((a - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, a);
|
||||
FIX_ARGP;
|
||||
}
|
||||
|
||||
@ -268,9 +273,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
cif->flags = 0;
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
/* Set the flags necessary for O32 processing */
|
||||
/* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
|
||||
* does not have special handling for floating point args.
|
||||
*/
|
||||
|
||||
if (cif->rtype->type != FFI_TYPE_STRUCT)
|
||||
if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
|
||||
{
|
||||
if (cif->nargs > 0)
|
||||
{
|
||||
@ -307,23 +314,49 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
}
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
if (cif->abi == FFI_O32_SOFT_FLOAT)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FFI_O32 */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -448,6 +481,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||
{
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
case FFI_O32:
|
||||
case FFI_O32_SOFT_FLOAT:
|
||||
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
@ -482,7 +516,7 @@ ffi_prep_closure (ffi_closure *closure,
|
||||
unsigned int ctx = (unsigned int) closure;
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
FFI_ASSERT(cif->abi == FFI_O32);
|
||||
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
|
||||
fn = (unsigned int) ffi_closure_O32;
|
||||
#else /* FFI_MIPS_N32 */
|
||||
FFI_ASSERT(cif->abi == FFI_N32);
|
||||
@ -535,10 +569,10 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
seen_int = 0;
|
||||
seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
|
||||
argn = 0;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) ar[0];
|
||||
argn = 1;
|
||||
@ -558,12 +592,7 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 8-byte arguments are always 8-byte aligned. */
|
||||
if (arg_types[i]->size == 8 && (argn & 0x1))
|
||||
argn++;
|
||||
/* Float arguments take up two register slots. The float word
|
||||
is the upper one. */
|
||||
if (argn == 2 && arg_types[i]->type == FFI_TYPE_FLOAT)
|
||||
if (arg_types[i]->alignment == 8 && (argn & 0x1))
|
||||
argn++;
|
||||
avalue[i] = ((char *) &ar[argn]);
|
||||
seen_int = 1;
|
||||
@ -575,7 +604,22 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
return cif->rtype->type;
|
||||
if (cif->abi == FFI_O32_SOFT_FLOAT)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
return FFI_TYPE_INT;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
return FFI_TYPE_UINT64;
|
||||
default:
|
||||
return cif->rtype->type;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return cif->rtype->type;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
@ -138,9 +138,14 @@ typedef enum ffi_abi {
|
||||
FFI_O32,
|
||||
FFI_N32,
|
||||
FFI_N64,
|
||||
FFI_O32_SOFT_FLOAT,
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
#ifdef __mips_soft_float
|
||||
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
#endif
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
#endif
|
||||
|
@ -36,7 +36,6 @@
|
||||
#define flags a3
|
||||
|
||||
#define SIZEOF_FRAME ( 4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG )
|
||||
#define SIZEOF_FRAME2 ( 8 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG )
|
||||
|
||||
.text
|
||||
.align 2
|
||||
@ -188,7 +187,28 @@ $LFE0:
|
||||
/* ffi_closure_O32. Expects address of the passed-in ffi_closure
|
||||
in t0. Stores any arguments passed in registers onto the
|
||||
stack, then calls ffi_closure_mips_inner_O32, which
|
||||
then decodes them. */
|
||||
then decodes them.
|
||||
|
||||
Stack layout:
|
||||
|
||||
14 - Start of parameters, original sp
|
||||
13 - ra save
|
||||
12 - fp save
|
||||
11 - $16 (s0) save
|
||||
10 - cprestore
|
||||
9 - return value high (v1)
|
||||
8 - return value low (v0)
|
||||
7 - f14 (le high, be low)
|
||||
6 - f14 (le low, be high)
|
||||
5 - f12 (le high, be low)
|
||||
4 - f12 (le low, be high)
|
||||
3 - Called function a3 save
|
||||
2 - Called function a2 save
|
||||
1 - Called function a1 save
|
||||
0 - Called function a0 save our sp, fp point here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 ( 14 * FFI_SIZEOF_ARG )
|
||||
|
||||
.text
|
||||
.align 2
|
||||
@ -202,10 +222,10 @@ $LFB1:
|
||||
.cpload $25
|
||||
.set reorder
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.cprestore SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG
|
||||
.cprestore SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG
|
||||
$LCFI4:
|
||||
REG_S $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Save s0
|
||||
REG_S $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
|
||||
$LCFI5:
|
||||
REG_S ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Save return address
|
||||
$LCFI6:
|
||||
move $fp, $sp
|
||||
@ -218,14 +238,21 @@ $LCFI7:
|
||||
REG_S $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp)
|
||||
REG_S $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# Load ABI enum to $16
|
||||
REG_L $16, 20($8) # cif pointer follows tramp.
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG($fp)
|
||||
s.d $f14, SIZEOF_FRAME2 - 8*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
la $25, ffi_closure_mips_inner_O32
|
||||
move $4, $8 # Pointer to the ffi_closure
|
||||
addu $5, $fp, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG
|
||||
addu $5, $fp, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG
|
||||
addu $6, $fp, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG
|
||||
addu $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
|
||||
jal $31, $25
|
||||
@ -235,28 +262,30 @@ $LCFI7:
|
||||
li $9, FFI_TYPE_VOID
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT
|
||||
|
||||
li $9, FFI_TYPE_FLOAT
|
||||
l.s $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
|
||||
l.s $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_DOUBLE
|
||||
l.d $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
|
||||
l.d $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
1:
|
||||
li $9, FFI_TYPE_SINT64
|
||||
REG_L $3, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($fp)
|
||||
REG_L $3, SIZEOF_FRAME2 - 5*FFI_SIZEOF_ARG($fp)
|
||||
beq $8, $9, integer
|
||||
|
||||
li $9, FFI_TYPE_UINT64
|
||||
REG_L $3, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($fp)
|
||||
beq $8, $9, integer
|
||||
|
||||
integer:
|
||||
REG_L $2, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_L $2, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
closure_done:
|
||||
# Epilogue
|
||||
move $sp, $fp
|
||||
REG_L $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Restore s0
|
||||
REG_L $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
|
||||
REG_L ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Restore return address
|
||||
ADDU $sp, SIZEOF_FRAME2
|
||||
@ -319,10 +348,13 @@ $LASFDE1:
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI4-$LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x28
|
||||
.uleb128 0x38
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI4
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x10 # $16
|
||||
.sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x1e # $fp
|
||||
.sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
@ -332,7 +364,7 @@ $LASFDE1:
|
||||
.4byte $LCFI7-$LCFI6
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x28
|
||||
.uleb128 0x38
|
||||
.align 2
|
||||
$LEFDE1:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user