OSDN Git Service

2009-09-15 David Daney <ddaney@caviumnetworks.com>
authordaney <daney@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Sep 2009 17:15:33 +0000 (17:15 +0000)
committerdaney <daney@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Sep 2009 17:15:33 +0000 (17:15 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151726 138bc75d-0d04-0410-961f-82ee72b054a4

libffi/ChangeLog
libffi/src/java_raw_api.c
libffi/src/mips/ffi.c
libffi/src/mips/ffitarget.h
libffi/src/mips/n32.S

index a8b9228..684a0e8 100644 (file)
@@ -1,3 +1,23 @@
+2009-09-15  David Daney  <ddaney@caviumnetworks.com>
+
+       * 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.
+
 2009-08-24  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
        * configure.ac (AC_PREREQ): Bump to 2.64.
index 1f8f983..9c5383e 100644 (file)
@@ -276,9 +276,6 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
     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 b6887be..3143dcf 100644 (file)
@@ -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, unsigned *loc, unsigned *arg_reg)
 }
 
 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 *arg)
     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 *arg)
             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 *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 *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 *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 *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 *, extended_cif *, int, int),
 /* 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)(void), void *rvalue, void **avalue)
 
 #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)(void), void *rvalue, void **avalue)
             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 *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 offset, ffi_abi abi, ffi_type *type,
 
       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 *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 *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 *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 *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;
                 }
index 214afe4..dd3fe73 100644 (file)
 #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 477f30b..6f0f4c6 100644 (file)
@@ -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