re PR libffi/13141 (FAIL: InvokeReturn output - source compiled test <libffi problem>)
authorDavid Daney <ddaney@avtrex.com>
Mon, 23 Aug 2004 16:49:17 +0000 (16:49 +0000)
committerDavid Daney <daney@gcc.gnu.org>
Mon, 23 Aug 2004 16:49:17 +0000 (16:49 +0000)
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

libffi/ChangeLog
libffi/src/mips/ffi.c
libffi/src/mips/ffitarget.h
libffi/src/mips/o32.S

index 483e483343c4868cf048f2e712b985fa50570a82..b33faeace235be64f4c2335df3d7463de840d23f 100644 (file)
@@ -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
index e12922aa0465b6c1a6c99c0abd918f5ed5336b7e..352226c7f547af59888fb8f40bc5d8a8a89d120b 100644 (file)
@@ -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 */
index 2e6fbaeec0ad4d308798ec57c8e8a601b0394738..6f28e70011132644a3cda36ac2f3e1de8282a917 100644 (file)
@@ -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
index e2dfa8debdb14647b4cd921a8d37164e18353e12..7391ce3fbfb2f8f85cdec04dd6069b01bb283d70 100644 (file)
@@ -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: