[Patch,libffi] Add MIPS64 soft-float support to libffi.

View: New views
3 Messages — Rating Filter:   Alert me  

[Patch,libffi] Add MIPS64 soft-float support to libffi.

by David Daney-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

libffi is lacking support for the mips64 soft-float ABIs.  In addition
be being annoying in and of itself, it also causes libjava failures.

The patch adds soft-float support for both n32 and n64 ABIs.  Quite a
bit of code had to be touched as the rules for passing structures
containing floating point elements are a slightly complex.

While working on the patch I noticed that we were failing a bunch if
pointer passing test cases that where recently added.  It turns out that
the original closure support for returning pointers was incorrect and
this was unmasked by the new test cases.  I wrapped fixes for this into
the patch as well (Yes, I know it is technically a no-no).  The change
to ffi_java_raw_to_rvalue() is needed with with the fixed closure
pointer return.

I would like to add that I think there is still incorrect handling for
values of most types on big-endian systems in java_raw_api.c, but since
the java interpreter only uses a couple of types, the problematical
cases are never used.

The end result is that all libffi tests except for some long double
things now pass at -O0.  There are a couple of floating point failures
with optimization turned on, but they look like they may be issues with
  libgcc's soft-float support.  The long double FAILures seem to be due
to lack of support in my glibc's printf.


Tested on mips64-unknown-linux-gnu soft-float with both n32 and n64 ABIs
with no regressions.  Currently testing mips64-unknown-linux-gnu
hard-float n32 and n64.

OK to commit given the hard-float testing is good?


2009-08-28  David Daney  <ddaney@...>

        * src/java_raw_api.c (ffi_java_raw_to_rvalue): Remove special
        handling for FFI_TYPE_POINTER.
        * src/mips/ffitarget.h (FFI_TYPE_STRUCT_D_SOFT,
        FFI_TYPE_STRUCT_F_SOFT, FFI_TYPE_STRUCT_DD_SOFT,
        FFI_TYPE_STRUCT_FF_SOFT, FFI_TYPE_STRUCT_FD_SOFT,
        FFI_TYPE_STRUCT_DF_SOFT, FFI_TYPE_STRUCT_SOFT): New defines.
        (FFI_N32_SOFT_FLOAT, FFI_N64_SOFT_FLOAT): New ffi_abi enumerations.
        (enum ffi_abi): Set FFI_DEFAULT_ABI for soft-float.
        * src/mips/n32.S (ffi_call_N32): Add handling for soft-float
        structure and pointer returns.
        (ffi_closure_N32): Add handling for pointer returns.
        * src/mips/ffi.c (ffi_prep_args, calc_n32_struct_flags,
        calc_n32_return_struct_flags): Handle soft-float.
        (ffi_prep_cif_machdep):  Handle soft-float, fix pointer handling.
        (ffi_call_N32): Declare proper argument types.
        (ffi_call, copy_struct_N32, ffi_closure_mips_inner_N32): Handle
        soft-float.


Index: src/java_raw_api.c
===================================================================
--- src/java_raw_api.c (revision 151156)
+++ src/java_raw_api.c (working copy)
@@ -276,9 +276,6 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, vo
     case FFI_TYPE_SINT16:
     case FFI_TYPE_SINT32:
     case FFI_TYPE_INT:
-#if FFI_SIZEOF_JAVA_RAW == 4
-    case FFI_TYPE_POINTER:
-#endif
       *(SINT64 *)rvalue >>= 32;
       break;
 
Index: src/mips/ffitarget.h
===================================================================
--- src/mips/ffitarget.h (revision 151156)
+++ src/mips/ffitarget.h (working copy)
@@ -95,6 +95,15 @@
 #define FFI_TYPE_STRUCT_DF     189
 #define FFI_TYPE_STRUCT_SMALL  93
 #define FFI_TYPE_STRUCT_SMALL2 109
+
+/* and for n32 soft float, add 16 * 2^4 */
+#define FFI_TYPE_STRUCT_D_SOFT      317
+#define FFI_TYPE_STRUCT_F_SOFT      301
+#define FFI_TYPE_STRUCT_DD_SOFT     509
+#define FFI_TYPE_STRUCT_FF_SOFT     429
+#define FFI_TYPE_STRUCT_FD_SOFT     493
+#define FFI_TYPE_STRUCT_DF_SOFT     445
+#define FFI_TYPE_STRUCT_SOFT        16
 #endif
 
 #ifdef LIBFFI_ASM
@@ -161,6 +170,8 @@ typedef enum ffi_abi {
   FFI_N32,
   FFI_N64,
   FFI_O32_SOFT_FLOAT,
+  FFI_N32_SOFT_FLOAT,
+  FFI_N64_SOFT_FLOAT,
 
 #ifdef FFI_MIPS_O32
 #ifdef __mips_soft_float
@@ -170,9 +181,17 @@ typedef enum ffi_abi {
 #endif
 #else
 # if _MIPS_SIM==_ABI64
+#  ifdef __mips_soft_float
+  FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT,
+#  else
   FFI_DEFAULT_ABI = FFI_N64,
+#  endif
 # else
+#  ifdef __mips_soft_float
+  FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT,
+#  else
   FFI_DEFAULT_ABI = FFI_N32,
+#  endif
 # endif
 #endif
 
Index: src/mips/n32.S
===================================================================
--- src/mips/n32.S (revision 151156)
+++ src/mips/n32.S (working copy)
@@ -217,8 +217,10 @@ callit:
 
  # Shift the return type flag over
  SRL t6, 8*FFI_FLAG_BITS
-
+
+ beq t6, FFI_TYPE_SINT32, retint
  bne     t6, FFI_TYPE_INT, retfloat
+retint:
  jal t9
  REG_L t4, 4*FFI_SIZEOF_ARG($fp)
  REG_S v0, 0(t4)
@@ -277,12 +279,58 @@ retstruct_d_f:
  b epilogue
 
 retstruct_f_d:
- bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
+ bne t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft
  jal t9
  REG_L t4, 4*FFI_SIZEOF_ARG($fp)
  s.s $f0, 0(t4)
  s.d $f2, 8(t4)
  b epilogue
+
+retstruct_d_soft:
+ bne t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sd v0, 0(t4)
+ b epilogue
+
+retstruct_f_soft:
+ bne t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sw v0, 0(t4)
+ b epilogue
+
+retstruct_d_d_soft:
+ bne t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sd v0, 0(t4)
+ sd v1, 8(t4)
+ b epilogue
+
+retstruct_f_f_soft:
+ bne t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sw v0, 0(t4)
+ sw v1, 4(t4)
+ b epilogue
+
+retstruct_d_f_soft:
+ bne t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sd v0, 0(t4)
+ sw v1, 8(t4)
+ b epilogue
+
+retstruct_f_d_soft:
+ bne t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sw v0, 0(t4)
+ sd v1, 8(t4)
+ b epilogue
 
 retstruct_small:
  bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
@@ -413,6 +461,11 @@ ffi_closure_N32:
  jalr t9
 
  # Return flags are in v0
+ bne     v0, FFI_TYPE_SINT32, cls_retint
+ lw v0, V0_OFF2($sp)
+ b cls_epilogue
+
+cls_retint:
  bne     v0, FFI_TYPE_INT, cls_retfloat
  REG_L v0, V0_OFF2($sp)
  b cls_epilogue
Index: src/mips/ffi.c
===================================================================
--- src/mips/ffi.c (revision 151156)
+++ src/mips/ffi.c (working copy)
@@ -99,7 +99,7 @@ static void ffi_prep_args(char *stack,
 
   p_argv = ecif->avalue;
 
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
+  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
     {
       size_t z;
       unsigned int a;
@@ -123,9 +123,25 @@ static void ffi_prep_args(char *stack,
 
           /* The size of a pointer depends on the ABI */
           if (type == FFI_TYPE_POINTER)
-            type =
-              (ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+            type = (ecif->cif->abi == FFI_N64
+    || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
+      ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
 
+ if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
+      || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
+  {
+    switch (type)
+      {
+      case FFI_TYPE_FLOAT:
+ type = FFI_TYPE_UINT32;
+ break;
+      case FFI_TYPE_DOUBLE:
+ type = FFI_TYPE_UINT64;
+ break;
+      default:
+ break;
+      }
+  }
   switch (type)
     {
       case FFI_TYPE_SINT8:
@@ -205,13 +221,17 @@ static void ffi_prep_args(char *stack,
    definitions and generates the appropriate flags. */
 
 static unsigned
-calc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg)
+calc_n32_struct_flags(int soft_float, ffi_type *arg,
+      unsigned *loc, unsigned *arg_reg)
 {
   unsigned flags = 0;
   unsigned index = 0;
 
   ffi_type *e;
 
+  if (soft_float)
+    return 0;
+
   while ((e = arg->elements[index]))
     {
       /* Align this object.  */
@@ -236,7 +256,7 @@ calc_n32_struct_flags(ffi_type *arg, uns
 }
 
 static unsigned
-calc_n32_return_struct_flags(ffi_type *arg)
+calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
 {
   unsigned flags = 0;
   unsigned small = FFI_TYPE_SMALLSTRUCT;
@@ -256,6 +276,7 @@ calc_n32_return_struct_flags(ffi_type *a
     small = FFI_TYPE_SMALLSTRUCT2;
 
   e = arg->elements[0];
+
   if (e->type == FFI_TYPE_DOUBLE)
     flags = FFI_TYPE_DOUBLE;
   else if (e->type == FFI_TYPE_FLOAT)
@@ -276,6 +297,8 @@ calc_n32_return_struct_flags(ffi_type *a
      floats! This must be passed the old way. */
   return small;
  }
+      if (soft_float)
+ flags += FFI_TYPE_STRUCT_SOFT;
     }
   else
     if (!flags)
@@ -382,16 +405,19 @@ ffi_status ffi_prep_cif_machdep(ffi_cif
 #ifdef FFI_MIPS_N32
   /* Set the flags necessary for N32 processing */
   {
+    int type;
     unsigned arg_reg = 0;
     unsigned loc = 0;
     unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
     unsigned index = 0;
 
     unsigned struct_flags = 0;
+    int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
+      || cif->abi == FFI_N64_SOFT_FLOAT);
 
     if (cif->rtype->type == FFI_TYPE_STRUCT)
       {
- struct_flags = calc_n32_return_struct_flags(cif->rtype);
+ struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
 
  if (struct_flags == 0)
   {
@@ -411,7 +437,22 @@ ffi_status ffi_prep_cif_machdep(ffi_cif
 
     while (count-- > 0 && arg_reg < 8)
       {
- switch ((cif->arg_types)[index]->type)
+ type = (cif->arg_types)[index]->type;
+ if (soft_float)
+  {
+    switch (type)
+      {
+      case FFI_TYPE_FLOAT:
+ type = FFI_TYPE_UINT32;
+ break;
+      case FFI_TYPE_DOUBLE:
+ type = FFI_TYPE_UINT64;
+ break;
+      default:
+ break;
+      }
+  }
+ switch (type)
   {
   case FFI_TYPE_FLOAT:
   case FFI_TYPE_DOUBLE:
@@ -423,17 +464,25 @@ ffi_status ffi_prep_cif_machdep(ffi_cif
             /* Align it.  */
             arg_reg = ALIGN(arg_reg, 2);
             /* Treat it as two adjacent doubles.  */
-    cif->flags +=
-              (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
-            arg_reg++;
-    cif->flags +=
-              (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
-            arg_reg++;
+    if (soft_float)
+      {
+ arg_reg += 2;
+      }
+    else
+      {
+ cif->flags +=
+  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
+ arg_reg++;
+ cif->flags +=
+  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
+ arg_reg++;
+      }
             break;
 
   case FFI_TYPE_STRUCT:
             loc = arg_reg * FFI_SIZEOF_ARG;
-    cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
+    cif->flags += calc_n32_struct_flags(soft_float,
+ (cif->arg_types)[index],
  &loc, &arg_reg);
     break;
 
@@ -469,17 +518,43 @@ ffi_status ffi_prep_cif_machdep(ffi_cif
       case FFI_TYPE_VOID:
  /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
  break;
-
+
+      case FFI_TYPE_POINTER:
+ if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
+  cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
+ else
+  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+ break;
+
       case FFI_TYPE_FLOAT:
+ if (soft_float)
+  {
+    cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
+    break;
+  }
+ /* else fall through */
       case FFI_TYPE_DOUBLE:
- cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
+ if (soft_float)
+  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+ else
+  cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
  break;
+
       case FFI_TYPE_LONGDOUBLE:
  /* Long double is returned as if it were a struct containing
    two doubles.  */
- cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
- cif->flags += (FFI_TYPE_DOUBLE + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
-      << (4 + (FFI_FLAG_BITS * 8));
+ if (soft_float)
+  {
+    cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
+    cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
+  }
+ else
+  {
+    cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
+    cif->flags += (FFI_TYPE_DOUBLE
+   + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
+      << (4 + (FFI_FLAG_BITS * 8));
+  }
  break;
       default:
  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
@@ -499,7 +574,7 @@ extern int ffi_call_O32(void (*)(char *,
 /* Low level routine for calling N32 functions */
 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
  extended_cif *, unsigned,
- unsigned, unsigned *, void (*)(void));
+ unsigned, void *, void (*)(void));
 
 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 {
@@ -529,10 +604,13 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
 
 #ifdef FFI_MIPS_N32
     case FFI_N32:
+    case FFI_N32_SOFT_FLOAT:
     case FFI_N64:
+    case FFI_N64_SOFT_FLOAT:
       {
         int copy_rvalue = 0;
-        void *rvalue_copy = ecif.rvalue;
+ int copy_offset = 0;
+        char *rvalue_copy = ecif.rvalue;
         if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
           {
             /* For structures smaller than 16 bytes we clobber memory
@@ -541,10 +619,20 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
             rvalue_copy = alloca(16);
             copy_rvalue = 1;
           }
+ else if (cif->rtype->type == FFI_TYPE_FLOAT
+ && (cif->abi == FFI_N64_SOFT_FLOAT
+     || cif->abi == FFI_N32_SOFT_FLOAT))
+  {
+    rvalue_copy = alloca (8);
+    copy_rvalue = 1;
+#ifdef __MIPSEB__
+    copy_offset = 4;
+#endif
+  }
         ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
                      cif->flags, rvalue_copy, fn);
         if (copy_rvalue)
-          memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
+          memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
       }
       break;
 #endif
@@ -755,7 +843,7 @@ ffi_closure_mips_inner_O32 (ffi_closure
 static void
 copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
                 int argn, unsigned arg_offset, ffi_arg *ar,
-                ffi_arg *fpr)
+                ffi_arg *fpr, int soft_float)
 {
   ffi_type **elt_typep = type->elements;
   while(*elt_typep)
@@ -777,7 +865,7 @@ copy_struct_N32(char *target, unsigned o
 
       tp = target + offset;
 
-      if (elt_type->type == FFI_TYPE_DOUBLE)
+      if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
         *(double *)tp = *(double *)fpp;
       else
         memcpy(tp, argp + arg_offset, elt_type->size);
@@ -815,8 +903,12 @@ ffi_closure_mips_inner_N32 (ffi_closure
   ffi_arg *avalue;
   ffi_type **arg_types;
   int i, avn, argn;
+  int soft_float;
+  ffi_arg *argp;
 
   cif = closure->cif;
+  soft_float = cif->abi == FFI_N64_SOFT_FLOAT
+    || cif->abi == FFI_N32_SOFT_FLOAT;
   avalue = alloca (cif->nargs * sizeof (ffi_arg));
   avaluep = alloca (cif->nargs * sizeof (ffi_arg));
 
@@ -839,9 +931,9 @@ ffi_closure_mips_inner_N32 (ffi_closure
   while (i < avn)
     {
       if (arg_types[i]->type == FFI_TYPE_FLOAT
-          || arg_types[i]->type == FFI_TYPE_DOUBLE)
+  || arg_types[i]->type == FFI_TYPE_DOUBLE)
         {
-          ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn;
+          argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
 #ifdef __MIPSEB__
           if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
             avaluep[i] = ((char *) argp) + sizeof (float);
@@ -856,11 +948,15 @@ ffi_closure_mips_inner_N32 (ffi_closure
           if (arg_types[i]->alignment > sizeof(ffi_arg))
             argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
 
-          ffi_arg *argp = ar + argn;
+          argp = ar + argn;
 
           /* The size of a pointer depends on the ABI */
           if (type == FFI_TYPE_POINTER)
-            type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+            type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
+      ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+
+  if (soft_float && type ==  FFI_TYPE_FLOAT)
+    type = FFI_TYPE_UINT32;
 
           switch (type)
             {
@@ -901,7 +997,7 @@ ffi_closure_mips_inner_N32 (ffi_closure
                      it was passed in registers.  */
                   avaluep[i] = alloca(arg_types[i]->size);
                   copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
-                                  argn, 0, ar, fpr);
+                                  argn, 0, ar, fpr, soft_float);
 
                   break;
                 }

Re: [Patch,libffi] Add MIPS64 soft-float support to libffi.

by Anthony Green-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Daney wrote:

> libffi is lacking support for the mips64 soft-float ABIs.  In addition
> be being annoying in and of itself, it also causes libjava failures.
>
> The patch adds soft-float support for both n32 and n64 ABIs.  Quite a
> bit of code had to be touched as the rules for passing structures
> containing floating point elements are a slightly complex.
>
> While working on the patch I noticed that we were failing a bunch if
> pointer passing test cases that where recently added.  It turns out
> that the original closure support for returning pointers was incorrect
> and this was unmasked by the new test cases.  I wrapped fixes for this
> into the patch as well (Yes, I know it is technically a no-no).  The
> change to ffi_java_raw_to_rvalue() is needed with with the fixed
> closure pointer return.
>
> I would like to add that I think there is still incorrect handling for
> values of most types on big-endian systems in java_raw_api.c, but
> since the java interpreter only uses a couple of types, the
> problematical cases are never used.
>
> The end result is that all libffi tests except for some long double
> things now pass at -O0.  There are a couple of floating point failures
> with optimization turned on, but they look like they may be issues
> with  libgcc's soft-float support.  The long double FAILures seem to
> be due to lack of support in my glibc's printf.
>
>
> Tested on mips64-unknown-linux-gnu soft-float with both n32 and n64
> ABIs with no regressions.  Currently testing mips64-unknown-linux-gnu
> hard-float n32 and n64.
>
> OK to commit given the hard-float testing is good?
Thanks David.  Please commit once you've confirmed good test results.  
I'll move the patch to the libffi repository once I see your commit.

AG


Re: [Patch,libffi] Add MIPS64 soft-float support to libffi.

by David Daney-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Anthony Green wrote:

> David Daney wrote:
>> libffi is lacking support for the mips64 soft-float ABIs.  In addition
>> be being annoying in and of itself, it also causes libjava failures.
>>
>> The patch adds soft-float support for both n32 and n64 ABIs.  Quite a
>> bit of code had to be touched as the rules for passing structures
>> containing floating point elements are a slightly complex.
>>
>> While working on the patch I noticed that we were failing a bunch if
>> pointer passing test cases that where recently added.  It turns out
>> that the original closure support for returning pointers was incorrect
>> and this was unmasked by the new test cases.  I wrapped fixes for this
>> into the patch as well (Yes, I know it is technically a no-no).  The
>> change to ffi_java_raw_to_rvalue() is needed with with the fixed
>> closure pointer return.
>>
>> I would like to add that I think there is still incorrect handling for
>> values of most types on big-endian systems in java_raw_api.c, but
>> since the java interpreter only uses a couple of types, the
>> problematical cases are never used.
>>
>> The end result is that all libffi tests except for some long double
>> things now pass at -O0.  There are a couple of floating point failures
>> with optimization turned on, but they look like they may be issues
>> with  libgcc's soft-float support.  The long double FAILures seem to
>> be due to lack of support in my glibc's printf.
>>
>>
>> Tested on mips64-unknown-linux-gnu soft-float with both n32 and n64
>> ABIs with no regressions.  Currently testing mips64-unknown-linux-gnu
>> hard-float n32 and n64.
>>
>> OK to commit given the hard-float testing is good?
> Thanks David.  Please commit once you've confirmed good test results.  
> I'll move the patch to the libffi repository once I see your commit.
>

Now committed (r151726).  Sorry for the delay, but my O2 is not the
fastest machine and I was too lazy to put a hard float filesystem on my
fast machines.

David Daney