Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libffi / src / powerpc / ppc_closure.S
1 /* -----------------------------------------------------------------------
2    sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
3             Copyright (c) 2008 Red Hat, Inc.
4
5    PowerPC Assembly glue.
6
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:
14
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
17
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>
31
32         .file   "ppc_closure.S"
33
34 #ifndef __powerpc64__
35
36 ENTRY(ffi_closure_SYSV)
37 .LFB1:
38         stwu %r1,-144(%r1)
39 .LCFI0:
40         mflr %r0
41 .LCFI1:
42         stw %r0,148(%r1)
43
44 # we want to build up an areas for the parameters passed
45 # in registers (both floating point and integer)
46
47         # so first save gpr 3 to gpr 10 (aligned to 4)
48         stw   %r3, 16(%r1)
49         stw   %r4, 20(%r1)
50         stw   %r5, 24(%r1)
51         stw   %r6, 28(%r1)
52         stw   %r7, 32(%r1)
53         stw   %r8, 36(%r1)
54         stw   %r9, 40(%r1)
55         stw   %r10,44(%r1)
56
57 #ifndef __NO_FPRS__
58         # next save fpr 1 to fpr 8 (aligned to 8)
59         stfd  %f1, 48(%r1)
60         stfd  %f2, 56(%r1)
61         stfd  %f3, 64(%r1)
62         stfd  %f4, 72(%r1)
63         stfd  %f5, 80(%r1)
64         stfd  %f6, 88(%r1)
65         stfd  %f7, 96(%r1)
66         stfd  %f8, 104(%r1)
67 #endif
68
69         # set up registers for the routine that actually does the work
70         # get the context pointer from the trampoline
71         mr %r3,%r11
72
73         # now load up the pointer to the result storage
74         addi %r4,%r1,112
75
76         # now load up the pointer to the saved gpr registers
77         addi %r5,%r1,16
78
79         # now load up the pointer to the saved fpr registers */
80         addi %r6,%r1,48
81
82         # now load up the pointer to the outgoing parameter
83         # stack in the previous frame
84         # i.e. the previous frame pointer + 8
85         addi %r7,%r1,152
86
87         # make the call
88         bl ffi_closure_helper_SYSV@local
89 .Lret:
90         # now r3 contains the return type
91         # so use it to look up in a table
92         # so we know how to deal with each type
93
94         # look up the proper starting point in table
95         # by using return type as offset
96
97         mflr %r4                # move address of .Lret to r4
98         slwi %r3,%r3,4          # now multiply return type by 16
99         addi %r4, %r4, .Lret_type0 - .Lret
100         lwz %r0,148(%r1)
101         add %r3,%r3,%r4         # add contents of table to table address
102         mtctr %r3
103         bctr                    # jump to it
104 .LFE1:
105
106 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
107 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
108 # first.
109         .align 4
110 # case FFI_TYPE_VOID
111 .Lret_type0:
112         mtlr %r0
113         addi %r1,%r1,144
114         blr
115         nop
116
117 # case FFI_TYPE_INT
118         lwz %r3,112+0(%r1)
119         mtlr %r0
120 .Lfinish:
121         addi %r1,%r1,144
122         blr
123
124 # case FFI_TYPE_FLOAT
125 #ifndef __NO_FPRS__
126         lfs %f1,112+0(%r1)
127         mtlr %r0
128         addi %r1,%r1,144
129 #else
130         nop
131         nop
132         nop
133 #endif
134         blr
135
136 # case FFI_TYPE_DOUBLE
137 #ifndef __NO_FPRS__
138         lfd %f1,112+0(%r1)
139         mtlr %r0
140         addi %r1,%r1,144
141 #else
142         nop
143         nop
144         nop
145 #endif
146         blr
147
148 # case FFI_TYPE_LONGDOUBLE
149 #ifndef __NO_FPRS__
150         lfd %f1,112+0(%r1)
151         lfd %f2,112+8(%r1)
152         mtlr %r0
153         b .Lfinish
154 #else
155         nop
156         nop
157         nop
158         blr
159 #endif
160
161 # case FFI_TYPE_UINT8
162         lbz %r3,112+3(%r1)
163         mtlr %r0
164         addi %r1,%r1,144
165         blr
166
167 # case FFI_TYPE_SINT8
168         lbz %r3,112+3(%r1)
169         extsb %r3,%r3
170         mtlr %r0
171         b .Lfinish
172
173 # case FFI_TYPE_UINT16
174         lhz %r3,112+2(%r1)
175         mtlr %r0
176         addi %r1,%r1,144
177         blr
178
179 # case FFI_TYPE_SINT16
180         lha %r3,112+2(%r1)
181         mtlr %r0
182         addi %r1,%r1,144
183         blr
184
185 # case FFI_TYPE_UINT32
186         lwz %r3,112+0(%r1)
187         mtlr %r0
188         addi %r1,%r1,144
189         blr
190
191 # case FFI_TYPE_SINT32
192         lwz %r3,112+0(%r1)
193         mtlr %r0
194         addi %r1,%r1,144
195         blr
196
197 # case FFI_TYPE_UINT64
198         lwz %r3,112+0(%r1)
199         lwz %r4,112+4(%r1)
200         mtlr %r0
201         b .Lfinish
202
203 # case FFI_TYPE_SINT64
204         lwz %r3,112+0(%r1)
205         lwz %r4,112+4(%r1)
206         mtlr %r0
207         b .Lfinish
208
209 # case FFI_TYPE_STRUCT
210         mtlr %r0
211         addi %r1,%r1,144
212         blr
213         nop
214
215 # case FFI_TYPE_POINTER
216         lwz %r3,112+0(%r1)
217         mtlr %r0
218         addi %r1,%r1,144
219         blr
220
221 # case FFI_TYPE_UINT128
222         lwz %r3,112+0(%r1)
223         lwz %r4,112+4(%r1)
224         lwz %r5,112+8(%r1)
225         bl .Luint128
226
227 # The return types below are only used when the ABI type is FFI_SYSV.
228 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
229         lbz %r3,112+0(%r1)
230         mtlr %r0
231         addi %r1,%r1,144
232         blr
233
234 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
235         lhz %r3,112+0(%r1)
236         mtlr %r0
237         addi %r1,%r1,144
238         blr
239
240 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
241         lwz %r3,112+0(%r1)
242         srwi %r3,%r3,8
243         mtlr %r0
244         b .Lfinish
245
246 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
247         lwz %r3,112+0(%r1)
248         mtlr %r0
249         addi %r1,%r1,144
250         blr
251
252 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
253         lwz %r3,112+0(%r1)
254         lwz %r4,112+4(%r1)
255         li %r5,24
256         b .Lstruct567
257
258 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
259         lwz %r3,112+0(%r1)
260         lwz %r4,112+4(%r1)
261         li %r5,16
262         b .Lstruct567
263
264 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
265         lwz %r3,112+0(%r1)
266         lwz %r4,112+4(%r1)
267         li %r5,8
268         b .Lstruct567
269
270 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
271         lwz %r3,112+0(%r1)
272         lwz %r4,112+4(%r1)
273         mtlr %r0
274         b .Lfinish
275
276 .Lstruct567:
277         subfic %r6,%r5,32
278         srw %r4,%r4,%r5
279         slw %r6,%r3,%r6
280         srw %r3,%r3,%r5
281         or %r4,%r6,%r4
282         mtlr %r0
283         addi %r1,%r1,144
284         blr
285
286 .Luint128:
287         lwz %r6,112+12(%r1)
288         mtlr %r0
289         addi %r1,%r1,144
290         blr
291
292 END(ffi_closure_SYSV)
293
294         .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
295 .Lframe1:
296         .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
297 .LSCIE1:
298         .4byte  0x0      # CIE Identifier Tag
299         .byte   0x1      # CIE Version
300 #if defined _RELOCATABLE || defined __PIC__
301         .ascii "zR\0"    # CIE Augmentation
302 #else
303         .ascii "\0"      # CIE Augmentation
304 #endif
305         .uleb128 0x1     # CIE Code Alignment Factor
306         .sleb128 -4      # CIE Data Alignment Factor
307         .byte   0x41     # CIE RA Column
308 #if defined _RELOCATABLE || defined __PIC__
309         .uleb128 0x1     # Augmentation size
310         .byte   0x1b     # FDE Encoding (pcrel sdata4)
311 #endif
312         .byte   0xc      # DW_CFA_def_cfa
313         .uleb128 0x1
314         .uleb128 0x0
315         .align 2
316 .LECIE1:
317 .LSFDE1:
318         .4byte  .LEFDE1-.LASFDE1         # FDE Length
319 .LASFDE1:
320         .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
321 #if defined _RELOCATABLE || defined __PIC__
322         .4byte  .LFB1-.  # FDE initial location
323 #else
324         .4byte  .LFB1    # FDE initial location
325 #endif
326         .4byte  .LFE1-.LFB1      # FDE address range
327 #if defined _RELOCATABLE || defined __PIC__
328         .uleb128 0x0     # Augmentation size
329 #endif
330         .byte   0x4      # DW_CFA_advance_loc4
331         .4byte  .LCFI0-.LFB1
332         .byte   0xe      # DW_CFA_def_cfa_offset
333         .uleb128 144
334         .byte   0x4      # DW_CFA_advance_loc4
335         .4byte  .LCFI1-.LCFI0
336         .byte   0x11     # DW_CFA_offset_extended_sf
337         .uleb128 0x41
338         .sleb128 -1
339         .align 2
340 .LEFDE1:
341
342 #endif
343
344 #if defined __ELF__ && defined __linux__
345         .section        .note.GNU-stack,"",@progbits
346 #endif