2009-06-16 Wim Lewis <wiml@hhhh.org>
authoraph <aph>
Tue, 16 Jun 2009 18:00:47 +0000 (18:00 +0000)
committeraph <aph>
Tue, 16 Jun 2009 18:00:47 +0000 (18:00 +0000)
* src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are
supposed to be callee-saved.
* src/powerpc/sysv.S (small_struct_return_value): Fix overrun of
return buffer for odd-size structs.

libffi/ChangeLog
libffi/src/powerpc/ffi.c
libffi/src/powerpc/sysv.S

index 8275975..3d94b9c 100644 (file)
@@ -1,3 +1,10 @@
+2009-06-16  Wim Lewis  <wiml@hhhh.org>
+
+       * src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are
+       supposed to be callee-saved.
+       * src/powerpc/sysv.S (small_struct_return_value): Fix overrun of
+       return buffer for odd-size structs.
+
 2009-06-16  Andreas Tobler  <a.tobler@schweiz.org>
 
        PR libffi/40444
index a0426f4..fbbfbe2 100644 (file)
@@ -43,11 +43,12 @@ enum {
   FLAG_RETURNS_64BITS   = 1 << (31-28),
 
   FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
-
-  FLAG_SYSV_SMST_R4     = 1 << (31-16), /* cr4, use r4 for FFI_SYSV 8 byte
+  FLAG_SYSV_SMST_R4     = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
                                           structs.  */
-  FLAG_SYSV_SMST_R3     = 1 << (31-15), /* cr3, use r3 for FFI_SYSV 4 byte
+  FLAG_SYSV_SMST_R3     = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
                                           structs.  */
+  /* Bits (31-24) through (31-19) store shift value for SMST */
+
   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
@@ -685,14 +686,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
              if (size <= 4)
                {
                  flags |= FLAG_SYSV_SMST_R3;
-                 flags |= 8 * (4 - size) << 4;
+                 flags |= 8 * (4 - size) << 8;
                  break;
                }
              /* These structs are returned in r3 and r4. See above.   */
              if  (size <= 8)
                {
-                 flags |= FLAG_SYSV_SMST_R4;
-                 flags |= 8 * (8 - size) << 4;
+                 flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
+                 flags |= 8 * (8 - size) << 8;
                  break;
                }
            }
index c06311f..96ea22b 100644 (file)
@@ -136,29 +136,18 @@ L(float_return_value):
        b       L(done_return_value)
 
 L(small_struct_return_value):
-       mtcrf   0x10,%r31       /* cr3  */
-       bt-     15,L(smst_one_register)
-       mtcrf   0x08,%r31       /* cr4  */
-       bt-     16,L(smst_two_register)
-       b       L(done_return_value)
-
-L(smst_one_register):
-       rlwinm  %r5,%r31,5+23,32-5,31 /* Extract the value to shift.  */
-       slw     %r3,%r3,%r5
-       stw     %r3,0(%r30)
-       b       L(done_return_value)
-L(smst_two_register):
-       rlwinm  %r5,%r31,5+23,32-5,31 /* Extract the value to shift.  */
-       cmpwi   %r5,0
-       subfic  %r9,%r5,32
-       slw     %r29,%r3,%r5
-       srw     %r9,%r4,%r9
-       beq-    L(smst_8byte)
-       or      %r3,%r9,%r29
-       slw     %r4,%r4,%r5
-L(smst_8byte):
-       stw     %r3,0(%r30)
-       stw     %r4,4(%r30)
+       extrwi  %r6,%r31,2,19         /* number of bytes padding = shift/8 */
+       mtcrf   0x02,%r31             /* copy flags to cr[24:27] (cr6) */
+       extrwi  %r5,%r31,5,19         /* r5 <- number of bits of padding */
+       subfic  %r6,%r6,4             /* r6 <- number of useful bytes in r3 */
+       bf-     25,L(done_return_value) /* struct in r3 ? if not, done. */
+/* smst_one_register: */
+       slw     %r3,%r3,%r5           /* Left-justify value in r3 */
+       mtxer   %r6                   /* move byte count to XER ... */
+       stswx   %r3,0,%r30            /* ... and store that many bytes */
+       bf+     26,L(done_return_value)  /* struct in r3:r4 ? */
+       add     %r6,%r6,%r30          /* adjust pointer */
+       stswi   %r4,%r6,4             /* store last four bytes */
        b       L(done_return_value)
 
 .LFE1: