This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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:
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]