c647583cd730bebb8665e52b6d40cc6f0a01c6a1
[libffi.git] / patches / powerpc-sysv-without-string-ops
1 Index: libffi/ChangeLog
2 ===================================================================
3 --- libffi.orig/ChangeLog
4 +++ libffi/ChangeLog
5 @@ -41,6 +41,12 @@
6  
7         * configure: Regenerate.
8  
9 +2011-11-12  Kyle Moffett <Kyle.D.Moffett@boeing.com>
10 +           Anthony Green <green@moxielogic.com>
11 +
12 +       * src/ppc/sysv.S, src/ppc/ffi.c: Remove use of ppc string
13 +       instructions (not available on some cores, like the PPC440).
14 +
15  2011-11-12  Kimura Wataru  <kimuraw@i.nifty.jp>
16  
17         * m4/ax_enable_builddir: Change from string comparison to numeric
18 Index: libffi/src/powerpc/ffi.c
19 ===================================================================
20 --- libffi.orig/src/powerpc/ffi.c
21 +++ libffi/src/powerpc/ffi.c
22 @@ -1,5 +1,6 @@
23  /* -----------------------------------------------------------------------
24     ffi.c - Copyright (C) 2011 Anthony Green
25 +           Copyright (C) 2011 Kyle Moffett
26             Copyright (C) 2008 Red Hat, Inc
27             Copyright (C) 2007, 2008 Free Software Foundation, Inc
28            Copyright (c) 1998 Geoffrey Keating
29 @@ -44,11 +45,6 @@ enum {
30    FLAG_RETURNS_64BITS   = 1 << (31-28),
31  
32    FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
33 -  FLAG_SYSV_SMST_R4     = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
34 -                                          structs.  */
35 -  FLAG_SYSV_SMST_R3     = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
36 -                                          structs.  */
37 -  /* Bits (31-24) through (31-19) store shift value for SMST */
38  
39    FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
40    FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
41 @@ -672,34 +668,19 @@ ffi_prep_cif_machdep (ffi_cif *cif)
42        break;
43  
44      case FFI_TYPE_STRUCT:
45 -      if (cif->abi == FFI_SYSV)
46 -       {
47 -         /* The final SYSV ABI says that structures smaller or equal 8 bytes
48 -            are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
49 -            in memory.  */
50 -
51 -         /* Treat structs with size <= 8 bytes.  */
52 -         if (size <= 8)
53 -           {
54 -             flags |= FLAG_RETURNS_SMST;
55 -             /* These structs are returned in r3. We pack the type and the
56 -                precalculated shift value (needed in the sysv.S) into flags.
57 -                The same applies for the structs returned in r3/r4.  */
58 -             if (size <= 4)
59 -               {
60 -                 flags |= FLAG_SYSV_SMST_R3;
61 -                 flags |= 8 * (4 - size) << 8;
62 -                 break;
63 -               }
64 -             /* These structs are returned in r3 and r4. See above.   */
65 -             if  (size <= 8)
66 -               {
67 -                 flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
68 -                 flags |= 8 * (8 - size) << 8;
69 -                 break;
70 -               }
71 -           }
72 -       }
73 +      /*
74 +       * The final SYSV ABI says that structures smaller or equal 8 bytes
75 +       * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
76 +       * in memory.
77 +       *
78 +       * NOTE: The assembly code can safely assume that it just needs to
79 +       *       store both r3 and r4 into a 8-byte word-aligned buffer, as
80 +       *       we allocate a temporary buffer in ffi_call() if this flag is
81 +       *       set.
82 +       */
83 +      if (cif->abi == FFI_SYSV && size <= 8)
84 +       flags |= FLAG_RETURNS_SMST;
85 +      
86  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
87      byref:
88  #endif
89 @@ -887,21 +868,32 @@ extern void FFI_HIDDEN ffi_call_LINUX64(
90  void
91  ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
92  {
93 +  /*
94 +   * The final SYSV ABI says that structures smaller or equal 8 bytes
95 +   * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
96 +   * in memory.
97 +   *
98 +   * Just to keep things simple for the assembly code, we will always
99 +   * bounce-buffer struct return values less than or equal to 8 bytes.
100 +   * This allows the ASM to handle SYSV small structures by directly
101 +   * writing r3 and r4 to memory without worrying about struct size.
102 +   */
103 +  unsigned int smst_buffer[2];
104    extended_cif ecif;
105 +  unsigned int rsize;
106  
107    ecif.cif = cif;
108    ecif.avalue = avalue;
109  
110 -  /* If the return value is a struct and we don't have a return        */
111 -  /* value address then we need to make one                    */
112 -
113 -  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
114 -    {
115 -      ecif.rvalue = alloca(cif->rtype->size);
116 -    }
117 -  else
118 -    ecif.rvalue = rvalue;
119 -
120 +  /* Ensure that we have a valid struct return value */
121 +  ecif.rvalue = rvalue;
122 +  if (cif->rtype->type == FFI_TYPE_STRUCT) {
123 +    rsize = cif->rtype->size;
124 +    if (rsize <= 8)
125 +      ecif.rvalue = smst_buffer;
126 +    else if (!rvalue)
127 +      ecif.rvalue = alloca(rsize);
128 +  }
129  
130    switch (cif->abi)
131      {
132 @@ -921,6 +913,10 @@ ffi_call(ffi_cif *cif, void (*fn)(void),
133        FFI_ASSERT (0);
134        break;
135      }
136 +
137 +  /* Check for a bounce-buffered return value */
138 +  if (rvalue && ecif.rvalue == smst_buffer)
139 +    memcpy(rvalue, smst_buffer, rsize);
140  }
141  
142  
143 Index: libffi/src/powerpc/sysv.S
144 ===================================================================
145 --- libffi.orig/src/powerpc/sysv.S
146 +++ libffi/src/powerpc/sysv.S
147 @@ -136,19 +136,14 @@ L(float_return_value):
148         b       L(done_return_value)
149  
150  L(small_struct_return_value):
151 -       extrwi  %r6,%r31,2,19         /* number of bytes padding = shift/8 */
152 -       mtcrf   0x02,%r31             /* copy flags to cr[24:27] (cr6) */
153 -       extrwi  %r5,%r31,5,19         /* r5 <- number of bits of padding */
154 -       subfic  %r6,%r6,4             /* r6 <- number of useful bytes in r3 */
155 -       bf-     25,L(done_return_value) /* struct in r3 ? if not, done. */
156 -/* smst_one_register: */
157 -       slw     %r3,%r3,%r5           /* Left-justify value in r3 */
158 -       mtxer   %r6                   /* move byte count to XER ... */
159 -       stswx   %r3,0,%r30            /* ... and store that many bytes */
160 -       bf+     26,L(done_return_value)  /* struct in r3:r4 ? */
161 -       add     %r6,%r6,%r30          /* adjust pointer */
162 -       stswi   %r4,%r6,4             /* store last four bytes */
163 -       b       L(done_return_value)
164 +       /*
165 +        * The C code always allocates a properly-aligned 8-byte bounce
166 +        * buffer to make this assembly code very simple.  Just write out
167 +        * r3 and r4 to the buffer to allow the C code to handle the rest.
168 +        */
169 +       stw %r3, 0(%r30)
170 +       stw %r4, 4(%r30)
171 +       b L(done_return_value)
172  
173  .LFE1:
174  END(ffi_call_SYSV)