runtime: copy mstats code from Go 1.7 runtime
[official-gcc.git] / libffi / src / powerpc / ppc_closure.S
blobb6d209de8635c59f06767ac7f1da083816ceea76
1 /* -----------------------------------------------------------------------
2    sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
3             Copyright (c) 2008 Red Hat, Inc.
5    PowerPC Assembly glue.
7    Permission is hereby granted, free of charge, to any person obtaining
8    a copy of this software and associated documentation files (the
9    ``Software''), to deal in the Software without restriction, including
10    without limitation the rights to use, copy, modify, merge, publish,
11    distribute, sublicense, and/or sell copies of the Software, and to
12    permit persons to whom the Software is furnished to do so, subject to
13    the following conditions:
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
18    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25    DEALINGS IN THE SOFTWARE.
26    ----------------------------------------------------------------------- */
27 #define LIBFFI_ASM
28 #include <fficonfig.h>
29 #include <ffi.h>
30 #include <powerpc/asm.h>
32         .file   "ppc_closure.S"
34 #ifndef POWERPC64
36 FFI_HIDDEN(ffi_closure_SYSV)
37 ENTRY(ffi_closure_SYSV)
38         .cfi_startproc
39         stwu %r1,-144(%r1)
40         .cfi_def_cfa_offset 144
41         mflr %r0
42         stw %r0,148(%r1)
43         .cfi_offset 65, 4
45 # we want to build up an areas for the parameters passed
46 # in registers (both floating point and integer)
48         # so first save gpr 3 to gpr 10 (aligned to 4)
49         stw   %r3, 16(%r1)
50         stw   %r4, 20(%r1)
51         stw   %r5, 24(%r1)
53         # set up registers for the routine that does the work
55         # closure->cif
56         lwz %r3,FFI_TRAMPOLINE_SIZE(%r11)
57         # closure->fun
58         lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11)
59         # closure->user_data
60         lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11)
62 .Ldoclosure:
63         stw   %r6, 28(%r1)
64         stw   %r7, 32(%r1)
65         stw   %r8, 36(%r1)
66         stw   %r9, 40(%r1)
67         stw   %r10,44(%r1)
69 #ifndef __NO_FPRS__
70         # next save fpr 1 to fpr 8 (aligned to 8)
71         stfd  %f1, 48(%r1)
72         stfd  %f2, 56(%r1)
73         stfd  %f3, 64(%r1)
74         stfd  %f4, 72(%r1)
75         stfd  %f5, 80(%r1)
76         stfd  %f6, 88(%r1)
77         stfd  %f7, 96(%r1)
78         stfd  %f8, 104(%r1)
79 #endif
81         # pointer to the result storage
82         addi %r6,%r1,112
84         # pointer to the saved gpr registers
85         addi %r7,%r1,16
87         # pointer to the saved fpr registers
88         addi %r8,%r1,48
90         # pointer to the outgoing parameter save area in the previous frame
91         # i.e. the previous frame pointer + 8
92         addi %r9,%r1,152
94         # make the call
95         bl ffi_closure_helper_SYSV@local
96 .Lret:
97         # now r3 contains the return type
98         # so use it to look up in a table
99         # so we know how to deal with each type
101         # look up the proper starting point in table
102         # by using return type as offset
104         mflr %r4                # move address of .Lret to r4
105         slwi %r3,%r3,4          # now multiply return type by 16
106         addi %r4, %r4, .Lret_type0 - .Lret
107         lwz %r0,148(%r1)
108         add %r3,%r3,%r4         # add contents of table to table address
109         mtctr %r3
110         bctr                    # jump to it
112 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
113 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
114 # first.
115         .align 4
116 # case FFI_TYPE_VOID
117 .Lret_type0:
118         mtlr %r0
119         addi %r1,%r1,144
120         .cfi_def_cfa_offset 0
121         blr
122         .cfi_def_cfa_offset 144
123         nop
125 # case FFI_TYPE_INT
126         lwz %r3,112+0(%r1)
127         mtlr %r0
128 .Lfinish:
129         addi %r1,%r1,144
130         .cfi_def_cfa_offset 0
131         blr
132         .cfi_def_cfa_offset 144
134 # case FFI_TYPE_FLOAT
135 #ifndef __NO_FPRS__
136         lfs %f1,112+0(%r1)
137 #else
138         nop
139 #endif
140         mtlr %r0
141         addi %r1,%r1,144
142         .cfi_def_cfa_offset 0
143         blr
144         .cfi_def_cfa_offset 144
146 # case FFI_TYPE_DOUBLE
147 #ifndef __NO_FPRS__
148         lfd %f1,112+0(%r1)
149 #else
150         nop
151 #endif
152         mtlr %r0
153         addi %r1,%r1,144
154         .cfi_def_cfa_offset 0
155         blr
156         .cfi_def_cfa_offset 144
158 # case FFI_TYPE_LONGDOUBLE
159 #ifndef __NO_FPRS__
160         lfd %f1,112+0(%r1)
161         lfd %f2,112+8(%r1)
162         mtlr %r0
163         b .Lfinish
164 #else
165         mtlr %r0
166         addi %r1,%r1,144
167         .cfi_def_cfa_offset 0
168         blr
169         .cfi_def_cfa_offset 144
170         nop
171 #endif
173 # case FFI_TYPE_UINT8
174 #ifdef __LITTLE_ENDIAN__
175         lbz %r3,112+0(%r1)
176 #else
177         lbz %r3,112+3(%r1)
178 #endif
179         mtlr %r0
180         addi %r1,%r1,144
181         .cfi_def_cfa_offset 0
182         blr
183         .cfi_def_cfa_offset 144
185 # case FFI_TYPE_SINT8
186 #ifdef __LITTLE_ENDIAN__
187         lbz %r3,112+0(%r1)
188 #else
189         lbz %r3,112+3(%r1)
190 #endif
191         extsb %r3,%r3
192         mtlr %r0
193         b .Lfinish
195 # case FFI_TYPE_UINT16
196 #ifdef __LITTLE_ENDIAN__
197         lhz %r3,112+0(%r1)
198 #else
199         lhz %r3,112+2(%r1)
200 #endif
201         mtlr %r0
202         addi %r1,%r1,144
203         .cfi_def_cfa_offset 0
204         blr
205         .cfi_def_cfa_offset 144
207 # case FFI_TYPE_SINT16
208 #ifdef __LITTLE_ENDIAN__
209         lha %r3,112+0(%r1)
210 #else
211         lha %r3,112+2(%r1)
212 #endif
213         mtlr %r0
214         addi %r1,%r1,144
215         .cfi_def_cfa_offset 0
216         blr
217         .cfi_def_cfa_offset 144
219 # case FFI_TYPE_UINT32
220         lwz %r3,112+0(%r1)
221         mtlr %r0
222         addi %r1,%r1,144
223         .cfi_def_cfa_offset 0
224         blr
225         .cfi_def_cfa_offset 144
227 # case FFI_TYPE_SINT32
228         lwz %r3,112+0(%r1)
229         mtlr %r0
230         addi %r1,%r1,144
231         .cfi_def_cfa_offset 0
232         blr
233         .cfi_def_cfa_offset 144
235 # case FFI_TYPE_UINT64
236         lwz %r3,112+0(%r1)
237         lwz %r4,112+4(%r1)
238         mtlr %r0
239         b .Lfinish
241 # case FFI_TYPE_SINT64
242         lwz %r3,112+0(%r1)
243         lwz %r4,112+4(%r1)
244         mtlr %r0
245         b .Lfinish
247 # case FFI_TYPE_STRUCT
248         mtlr %r0
249         addi %r1,%r1,144
250         .cfi_def_cfa_offset 0
251         blr
252         .cfi_def_cfa_offset 144
253         nop
255 # case FFI_TYPE_POINTER
256         lwz %r3,112+0(%r1)
257         mtlr %r0
258         addi %r1,%r1,144
259         .cfi_def_cfa_offset 0
260         blr
261         .cfi_def_cfa_offset 144
263 # case FFI_TYPE_UINT128
264         lwz %r3,112+0(%r1)
265         lwz %r4,112+4(%r1)
266         lwz %r5,112+8(%r1)
267         b .Luint128
269 # The return types below are only used when the ABI type is FFI_SYSV.
270 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
271         lbz %r3,112+0(%r1)
272         mtlr %r0
273         addi %r1,%r1,144
274         .cfi_def_cfa_offset 0
275         blr
276         .cfi_def_cfa_offset 144
278 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
279         lhz %r3,112+0(%r1)
280         mtlr %r0
281         addi %r1,%r1,144
282         .cfi_def_cfa_offset 0
283         blr
284         .cfi_def_cfa_offset 144
286 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
287         lwz %r3,112+0(%r1)
288 #ifdef __LITTLE_ENDIAN__
289         mtlr %r0
290         addi %r1,%r1,144
291         .cfi_def_cfa_offset 0
292         blr
293         .cfi_def_cfa_offset 144
294 #else
295         srwi %r3,%r3,8
296         mtlr %r0
297         b .Lfinish
298 #endif
300 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
301         lwz %r3,112+0(%r1)
302         mtlr %r0
303         addi %r1,%r1,144
304         .cfi_def_cfa_offset 0
305         blr
306         .cfi_def_cfa_offset 144
308 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
309         lwz %r3,112+0(%r1)
310         lwz %r4,112+4(%r1)
311 #ifdef __LITTLE_ENDIAN__
312         mtlr %r0
313         b .Lfinish
314 #else
315         li %r5,24
316         b .Lstruct567
317 #endif
319 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
320         lwz %r3,112+0(%r1)
321         lwz %r4,112+4(%r1)
322 #ifdef __LITTLE_ENDIAN__
323         mtlr %r0
324         b .Lfinish
325 #else
326         li %r5,16
327         b .Lstruct567
328 #endif
330 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
331         lwz %r3,112+0(%r1)
332         lwz %r4,112+4(%r1)
333 #ifdef __LITTLE_ENDIAN__
334         mtlr %r0
335         b .Lfinish
336 #else
337         li %r5,8
338         b .Lstruct567
339 #endif
341 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
342         lwz %r3,112+0(%r1)
343         lwz %r4,112+4(%r1)
344         mtlr %r0
345         b .Lfinish
347 #ifndef __LITTLE_ENDIAN__
348 .Lstruct567:
349         subfic %r6,%r5,32
350         srw %r4,%r4,%r5
351         slw %r6,%r3,%r6
352         srw %r3,%r3,%r5
353         or %r4,%r6,%r4
354         mtlr %r0
355         addi %r1,%r1,144
356         .cfi_def_cfa_offset 0
357         blr
358         .cfi_def_cfa_offset 144
359 #endif
361 .Luint128:
362         lwz %r6,112+12(%r1)
363         mtlr %r0
364         addi %r1,%r1,144
365         .cfi_def_cfa_offset 0
366         blr
367         .cfi_endproc
368 END(ffi_closure_SYSV)
371 FFI_HIDDEN(ffi_go_closure_sysv)
372 ENTRY(ffi_go_closure_sysv)
373         .cfi_startproc
374         stwu %r1,-144(%r1)
375         .cfi_def_cfa_offset 144
376         mflr %r0
377         stw %r0,148(%r1)
378         .cfi_offset 65, 4
380         stw   %r3, 16(%r1)
381         stw   %r4, 20(%r1)
382         stw   %r5, 24(%r1)
384         # closure->cif
385         lwz %r3,4(%r11)
386         # closure->fun
387         lwz %r4,8(%r11)
388         # user_data
389         mr %r5,%r11
390         b .Ldoclosure
391         .cfi_endproc
392 END(ffi_go_closure_sysv)
394 #if defined __ELF__ && defined __linux__
395         .section        .note.GNU-stack,"",@progbits
396 #endif
397 #endif