This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA PATCH: PR 13141 MIPS libffi fixes...
- From: David Daney <ddaney at avtrex dot com>
- To: java-patches at gcc dot gnu dot org, gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 18 Aug 2004 12:30:38 -0700
- Subject: RFA PATCH: PR 13141 MIPS libffi fixes...
This patch fixes many problems in the MIPS port of libffi as well as the
corresponding reflection support in libgcj (ie PR 13141).
I added a new ABI constant for the MIPS O32 soft float ABI.
Tested on: mipsel-linux --with-float=soft
make check in libffi no failures.
make check in libjava no regressions.
Who OKs things in libffi? gcc-patches gets to enjoy this message also
(just in case).
O.K. to commit?
David Daney.
2004-08-18 David Daney <daney@avtrex.com>
PR libgcj/13141
* 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.
Index: src/mips/ffi.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/mips/ffi.c,v
retrieving revision 1.7
diff -c -p -r1.7 ffi.c
*** src/mips/ffi.c 15 Aug 2004 04:05:18 -0000 1.7
--- src/mips/ffi.c 18 Aug 2004 18:25:57 -0000
*************** static void ffi_prep_args(char *stack,
*** 85,94 ****
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
{
size_t z;
/* Align if necessary */
! if (((*p_arg)->alignment - 1) & (unsigned) argp) {
! argp = (char *) ALIGN(argp, (*p_arg)->alignment);
FIX_ARGP;
}
--- 85,99 ----
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
{
size_t z;
+ unsigned short a;
/* Align if necessary */
! 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;
}
*************** ffi_status ffi_prep_cif_machdep(ffi_cif
*** 268,276 ****
cif->flags = 0;
#if _MIPS_SIM == _ABIO32
! /* Set the flags necessary for O32 processing */
! if (cif->rtype->type != FFI_TYPE_STRUCT)
{
if (cif->nargs > 0)
{
--- 273,283 ----
cif->flags = 0;
#if _MIPS_SIM == _ABIO32
! /* 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 && cif->abi == FFI_O32)
{
if (cif->nargs > 0)
{
*************** ffi_status ffi_prep_cif_machdep(ffi_cif
*** 307,329 ****
}
/* 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;
! default:
! cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
! break;
}
#endif
--- 314,362 ----
}
/* Set the return type flag */
! 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;
! 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
*************** void ffi_call(ffi_cif *cif, void (*fn)()
*** 448,453 ****
--- 481,487 ----
{
#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;
*************** ffi_prep_closure (ffi_closure *closure,
*** 482,488 ****
unsigned int ctx = (unsigned int) closure;
#if defined(FFI_MIPS_O32)
! FFI_ASSERT(cif->abi == FFI_O32);
fn = (unsigned int) ffi_closure_O32;
#else /* FFI_MIPS_N32 */
FFI_ASSERT(cif->abi == FFI_N32);
--- 516,522 ----
unsigned int ctx = (unsigned int) closure;
#if defined(FFI_MIPS_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);
*************** ffi_closure_mips_inner_O32 (ffi_closure
*** 535,544 ****
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
! seen_int = 0;
argn = 0;
! if (cif->flags == FFI_TYPE_STRUCT)
{
rvalue = (void *) ar[0];
argn = 1;
--- 569,578 ----
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
! seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
argn = 0;
! if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
{
rvalue = (void *) ar[0];
argn = 1;
*************** ffi_closure_mips_inner_O32 (ffi_closure
*** 558,569 ****
}
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)
argn++;
avalue[i] = ((char *) &ar[argn]);
seen_int = 1;
--- 592,598 ----
}
else
{
! if (arg_types[i]->alignment == 8 && (argn & 0x1))
argn++;
avalue[i] = ((char *) &ar[argn]);
seen_int = 1;
*************** ffi_closure_mips_inner_O32 (ffi_closure
*** 575,581 ****
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data);
! return cif->rtype->type;
}
#endif /* FFI_CLOSURES */
--- 604,625 ----
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data);
! 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 */
Index: src/mips/ffitarget.h
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/mips/ffitarget.h,v
retrieving revision 1.3
diff -c -p -r1.3 ffitarget.h
*** src/mips/ffitarget.h 15 Aug 2004 04:05:18 -0000 1.3
--- src/mips/ffitarget.h 18 Aug 2004 18:25:57 -0000
*************** typedef enum ffi_abi {
*** 138,146 ****
--- 138,151 ----
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
Index: src/mips/o32.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/mips/o32.S,v
retrieving revision 1.4
diff -c -p -r1.4 o32.S
*** src/mips/o32.S 15 Aug 2004 04:05:18 -0000 1.4
--- src/mips/o32.S 18 Aug 2004 18:25:57 -0000
***************
*** 36,42 ****
#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
--- 36,41 ----
*************** $LFE0:
*** 188,194 ****
/* 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. */
.text
.align 2
--- 187,214 ----
/* 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.
!
! 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
*************** $LFB1:
*** 202,211 ****
.cpload $25
.set reorder
SUBU $sp, SIZEOF_FRAME2
! .cprestore SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG
$LCFI4:
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
--- 222,231 ----
.cpload $25
.set reorder
SUBU $sp, SIZEOF_FRAME2
! .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
REG_S ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Save return address
$LCFI6:
move $fp, $sp
*************** $LCFI7:
*** 218,231 ****
REG_S $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp)
REG_S $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp)
# 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)
!
# 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 $6, $fp, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG
addu $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
jal $31, $25
--- 238,258 ----
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 - 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
*************** $LCFI7:
*** 235,262 ****
li $9, FFI_TYPE_VOID
beq $8, $9, closure_done
li $9, FFI_TYPE_FLOAT
! l.s $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
beq $8, $9, closure_done
li $9, FFI_TYPE_DOUBLE
! l.d $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
beq $8, $9, closure_done
!
li $9, FFI_TYPE_SINT64
! REG_L $3, SIZEOF_FRAME2 - 3*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)
closure_done:
# Epilogue
move $sp, $fp
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
--- 262,291 ----
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 - 6*FFI_SIZEOF_ARG($fp)
beq $8, $9, closure_done
li $9, FFI_TYPE_DOUBLE
! 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 - 5*FFI_SIZEOF_ARG($fp)
beq $8, $9, integer
li $9, FFI_TYPE_UINT64
beq $8, $9, integer
integer:
! 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
*************** $LASFDE1:
*** 319,328 ****
.byte 0x4 # DW_CFA_advance_loc4
.4byte $LCFI4-$LFB1
.byte 0xe # DW_CFA_def_cfa_offset
! .uleb128 0x28
.byte 0x4 # DW_CFA_advance_loc4
.4byte $LCFI6-$LCFI4
.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
--- 348,360 ----
.byte 0x4 # DW_CFA_advance_loc4
.4byte $LCFI4-$LFB1
.byte 0xe # DW_CFA_def_cfa_offset
! .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
*************** $LASFDE1:
*** 332,338 ****
.4byte $LCFI7-$LCFI6
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1e
! .uleb128 0x28
.align 2
$LEFDE1:
--- 364,370 ----
.4byte $LCFI7-$LCFI6
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1e
! .uleb128 0x38
.align 2
$LEFDE1: