OSDN Git Service

* src/powerpc/ffi.c (ffi_prep_cif_machdep <FFI_LINUX64>): Correct
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 8 Feb 2004 12:11:25 +0000 (12:11 +0000)
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 8 Feb 2004 12:11:25 +0000 (12:11 +0000)
long double function return and long double arg handling.
(ffi_closure_helper_LINUX64): Formatting.  Delete unused "ng" var.
Use "end_pfr" instead of "nf".  Correct long double handling.
Localise "temp".
* src/powerpc/linux64.S (ffi_call_LINUX64): Save f2 long double
return value.
* src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Allocate
space for long double return value.  Adjust stack frame and offsets.
Load f2 long double return.

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

libffi/ChangeLog
libffi/src/powerpc/ffi.c
libffi/src/powerpc/linux64.S
libffi/src/powerpc/linux64_closure.S

index d19883a..4d931c9 100644 (file)
@@ -1,3 +1,16 @@
+2004-02-08  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/powerpc/ffi.c (ffi_prep_cif_machdep <FFI_LINUX64>): Correct
+       long double function return and long double arg handling.
+       (ffi_closure_helper_LINUX64): Formatting.  Delete unused "ng" var.
+       Use "end_pfr" instead of "nf".  Correct long double handling.
+       Localise "temp".
+       * src/powerpc/linux64.S (ffi_call_LINUX64): Save f2 long double
+       return value.
+       * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Allocate
+       space for long double return value.  Adjust stack frame and offsets.
+       Load f2 long double return.
+
 2004-02-07  Alan Modra  <amodra@bigpond.net.au>
 
        * src/types.c: Use 16 byte long double for POWERPC64.
index 9ad85ea..a2fb2d2 100644 (file)
@@ -446,6 +446,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
   int fparg_count = 0, intarg_count = 0;
   unsigned flags = 0;
   unsigned struct_copy_size = 0;
+  unsigned type = cif->rtype->type;
 
   if (cif->abi != FFI_LINUX64)
     {    
@@ -468,6 +469,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 
       /* Space for the mandatory parm save area and general registers.  */
       bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof(long);
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      if (type == FFI_TYPE_LONGDOUBLE)
+       type = FFI_TYPE_DOUBLE;
+#endif
     }
 
   /* Return value handling.  The rules for SYSV are as follows:
@@ -480,9 +486,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
        are allocated space and a pointer is passed as the first argument.
      For LINUX64:
      - integer values in gpr3;
-     - Structures/Unions and long double by reference;
-     - Single/double FP values in fpr1.  */
-  switch (cif->rtype->type)
+     - Structures/Unions by reference;
+     - Single/double FP values in fpr1, long double in fpr1,fpr2.  */
+  switch (type)
     {
     case FFI_TYPE_DOUBLE:
       flags |= FLAG_RETURNS_64BITS;
@@ -581,6 +587,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
       {
        switch ((*ptr)->type)
          {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         case FFI_TYPE_LONGDOUBLE:
+           fparg_count += 2;
+           intarg_count += 2;
+           break;
+#endif
          case FFI_TYPE_FLOAT:
          case FFI_TYPE_DOUBLE:
            fparg_count++;
@@ -588,9 +600,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
            break;
 
          case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-         case FFI_TYPE_LONGDOUBLE:
-#endif
            intarg_count += ((*ptr)->size + 7) / 8;
            break;
 
@@ -863,7 +872,7 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
              pst++;
           }
          break;
-       
+
        case FFI_TYPE_STRUCT:
          /* Structs are passed by reference. The address will appear in a 
             gpr if it is one of the first 8 arguments.  */
@@ -965,34 +974,28 @@ int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
                                       ffi_dblfl*);
 
 int hidden
-ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue, 
-            unsigned long * pst, ffi_dblfl * pfr)
+ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, 
+                           unsigned long *pst, ffi_dblfl *pfr)
 {
   /* rvalue is the pointer to space for return value in closure assembly */
   /* pst is the pointer to parameter save area
      (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
   /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
 
-  void **          avalue;
-  ffi_type **      arg_types;
-  long             i, avn;
-  long             nf;   /* number of floating registers already used */
-  long             ng;   /* number of general registers already used */
-  ffi_cif *        cif; 
-  double           temp; 
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn;
+  ffi_cif *cif; 
+  ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
 
   cif = closure->cif;
-  avalue = alloca(cif->nargs * sizeof(void *));
-
-  nf = 0;
-  ng = 0;
+  avalue = alloca (cif->nargs * sizeof (void *));
 
   /* Copy the caller's structure return value address so that the closure
      returns the data directly to the caller.  */
   if (cif->rtype->type == FFI_TYPE_STRUCT)
     {
       rvalue = (void *) *pst;
-      ng++;
       pst++;
     }
 
@@ -1008,21 +1011,18 @@ ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue,
        case FFI_TYPE_SINT8:
        case FFI_TYPE_UINT8:
          avalue[i] = (char *) pst + 7;
-         ng++;
          pst++;
          break;
            
        case FFI_TYPE_SINT16:
        case FFI_TYPE_UINT16:
          avalue[i] = (char *) pst + 6;
-         ng++;
          pst++;
          break;
 
        case FFI_TYPE_SINT32:
        case FFI_TYPE_UINT32:
          avalue[i] = (char *) pst + 4;
-         ng++;
          pst++;
          break;
 
@@ -1030,21 +1030,16 @@ ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue,
        case FFI_TYPE_UINT64:
        case FFI_TYPE_POINTER:
          avalue[i] = pst;
-         ng++;
          pst++;
          break;
 
        case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-       case FFI_TYPE_LONGDOUBLE:
-#endif
          /* Structures with size less than eight bytes are passed
             left-padded.  */
          if (arg_types[i]->size < 8)
            avalue[i] = (char *) pst + 8 - arg_types[i]->size;
          else
            avalue[i] = pst;
-         ng += (arg_types[i]->size + 7) / 8;
          pst += (arg_types[i]->size + 7) / 8;
          break;
 
@@ -1056,16 +1051,15 @@ ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue,
 
           /* there are 13 64bit floating point registers */
 
-          if (nf < NUM_FPR_ARG_REGISTERS64) {
-             temp = pfr->d;
-             pfr->f = (float)temp;
-             avalue[i] = pfr;
-             pfr++;
-          } else {
-            avalue[i] = pst;
-          }
-          nf++;
-         ng++;
+          if (pfr < end_pfr)
+           {
+             double temp = pfr->d;
+             pfr->f = (float) temp;
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           avalue[i] = pst;
          pst++;
          break;
 
@@ -1073,17 +1067,38 @@ ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue,
          /* On the outgoing stack all values are aligned to 8 */
           /* there are 13 64bit floating point registers */
 
-          if (nf < NUM_FPR_ARG_REGISTERS64) {
-            avalue[i] = pfr;
-             pfr++;
-          } else {
-            avalue[i] = pst;
-          }
-          nf++;
-         ng++;
+         if (pfr < end_pfr)
+           {
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           avalue[i] = pst;
          pst++;
          break;
 
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if (prf + 1 < end_pfr)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+           }
+         else
+           {
+             if (pfr < end_pfr)
+               {
+                 /* Passed partly in f13 and partly on the stack.
+                    Move it all to the stack.  */
+                 *pst = *(unsigned long *) pfr;
+                 pfr++;
+               }
+             avalue[i] = pst;
+           }
+         pst += 2;
+         break;
+#endif
+
        default:
          FFI_ASSERT(0);
        }
@@ -1096,5 +1111,4 @@ ffi_closure_helper_LINUX64 (ffi_closure* closure, void * rvalue,
 
   /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
   return cif->rtype->type;
-
 }
index f12d4ec..11cf926 100644 (file)
@@ -122,6 +122,7 @@ ffi_call_LINUX64:
 .Lfp_return_value:
        bf      28, .Lfloat_return_value
        stfd    %f1, 0(%r30)
+       stfd    %f2, 8(%r30)    /* It might be a long double */
        b       .Ldone_return_value
 .Lfloat_return_value:
        stfs    %f1, 0(%r30)
index db78ea6..fa331db 100644 (file)
@@ -30,24 +30,24 @@ ffi_closure_LINUX64:
        std     %r0, 16(%r1)
 
        # mandatory 48 bytes special reg save area + 64 bytes parm save area
-       # + 8 bytes retval area + 13*8 bytes fpr save area
-       stdu    %r1, -224(%r1)
+       # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
+       stdu    %r1, -240(%r1)
 .LCFI0:
 
        # next save fpr 1 to fpr 13
-       stfd  %f1, 120+(0*8)(%r1)
-       stfd  %f2, 120+(1*8)(%r1)
-       stfd  %f3, 120+(2*8)(%r1)
-       stfd  %f4, 120+(3*8)(%r1)
-       stfd  %f5, 120+(4*8)(%r1)
-       stfd  %f6, 120+(5*8)(%r1)
-       stfd  %f7, 120+(6*8)(%r1)
-       stfd  %f8, 120+(7*8)(%r1)
-       stfd  %f9, 120+(8*8)(%r1)
-       stfd  %f10, 120+(9*8)(%r1)
-       stfd  %f11, 120+(10*8)(%r1)
-       stfd  %f12, 120+(11*8)(%r1)
-       stfd  %f13, 120+(12*8)(%r1)
+       stfd  %f1, 128+(0*8)(%r1)
+       stfd  %f2, 128+(1*8)(%r1)
+       stfd  %f3, 128+(2*8)(%r1)
+       stfd  %f4, 128+(3*8)(%r1)
+       stfd  %f5, 128+(4*8)(%r1)
+       stfd  %f6, 128+(5*8)(%r1)
+       stfd  %f7, 128+(6*8)(%r1)
+       stfd  %f8, 128+(7*8)(%r1)
+       stfd  %f9, 128+(8*8)(%r1)
+       stfd  %f10, 128+(9*8)(%r1)
+       stfd  %f11, 128+(10*8)(%r1)
+       stfd  %f12, 128+(11*8)(%r1)
+       stfd  %f13, 128+(12*8)(%r1)
 
        # set up registers for the routine that actually does the work
        # get the context pointer from the trampoline
@@ -58,10 +58,10 @@ ffi_closure_LINUX64:
 
        # now load up the pointer to the parameter save area
        # in the previous frame
-       addi %r5, %r1, 224 + 48
+       addi %r5, %r1, 240 + 48
 
        # now load up the pointer to the saved fpr registers */
-       addi %r6, %r1, 120
+       addi %r6, %r1, 128
 
        # make the call
        bl .ffi_closure_helper_LINUX64
@@ -76,7 +76,7 @@ ffi_closure_LINUX64:
        mflr %r4                # move address of .Lret to r4
        sldi %r3, %r3, 4        # now multiply return type by 16
        addi %r4, %r4, .Lret_type0 - .Lret
-       ld %r0, 224+16(%r1)
+       ld %r0, 240+16(%r1)
        add %r3, %r3, %r4       # add contents of table to table address
        mtctr %r3
        bctr                    # jump to it
@@ -89,33 +89,33 @@ ffi_closure_LINUX64:
 .Lret_type0:
 # case FFI_TYPE_VOID
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
        nop
 # case FFI_TYPE_INT
        lwa %r3, 112+4(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_FLOAT
        lfs %f1, 112+0(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_DOUBLE
        lfd %f1, 112+0(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_LONGDOUBLE
        lfd %f1, 112+0(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
-       blr
+       lfd %f2, 112+8(%r1)
+       b .Lfinish
 # case FFI_TYPE_UINT8
        lbz %r3, 112+7(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_SINT8
        lbz %r3, 112+7(%r1)
@@ -126,42 +126,42 @@ ffi_closure_LINUX64:
        lhz %r3, 112+6(%r1)
        mtlr %r0
 .Lfinish:
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_SINT16
        lha %r3, 112+6(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_UINT32
        lwz %r3, 112+4(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_SINT32
        lwa %r3, 112+4(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_UINT64
        ld %r3, 112+0(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_SINT64
        ld %r3, 112+0(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # case FFI_TYPE_STRUCT
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
        nop
 # case FFI_TYPE_POINTER
        ld %r3, 112+0(%r1)
        mtlr %r0
-       addi %r1, %r1, 224
+       addi %r1, %r1, 240
        blr
 # esac
 .LFE1:
@@ -196,7 +196,7 @@ ffi_closure_LINUX64:
        .byte   0x2      # DW_CFA_advance_loc1
        .byte   .LCFI0-.LFB1
        .byte   0xe      # DW_CFA_def_cfa_offset
-       .uleb128 224
+       .uleb128 240
        .byte   0x11     # DW_CFA_offset_extended_sf
        .uleb128 0x41
        .sleb128 -2