OSDN Git Service

2009-06-04 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.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         lfs %f1,112+0(%r1)
126         mtlr %r0
127         addi %r1,%r1,144
128         blr
129
130 # case FFI_TYPE_DOUBLE
131         lfd %f1,112+0(%r1)
132         mtlr %r0
133         addi %r1,%r1,144
134         blr
135
136 # case FFI_TYPE_LONGDOUBLE
137         lfd %f1,112+0(%r1)
138         lfd %f2,112+8(%r1)
139         mtlr %r0
140         b .Lfinish
141
142 # case FFI_TYPE_UINT8
143         lbz %r3,112+3(%r1)
144         mtlr %r0
145         addi %r1,%r1,144
146         blr
147
148 # case FFI_TYPE_SINT8
149         lbz %r3,112+3(%r1)
150         extsb %r3,%r3
151         mtlr %r0
152         b .Lfinish
153
154 # case FFI_TYPE_UINT16
155         lhz %r3,112+2(%r1)
156         mtlr %r0
157         addi %r1,%r1,144
158         blr
159
160 # case FFI_TYPE_SINT16
161         lha %r3,112+2(%r1)
162         mtlr %r0
163         addi %r1,%r1,144
164         blr
165
166 # case FFI_TYPE_UINT32
167         lwz %r3,112+0(%r1)
168         mtlr %r0
169         addi %r1,%r1,144
170         blr
171
172 # case FFI_TYPE_SINT32
173         lwz %r3,112+0(%r1)
174         mtlr %r0
175         addi %r1,%r1,144
176         blr
177
178 # case FFI_TYPE_UINT64
179         lwz %r3,112+0(%r1)
180         lwz %r4,112+4(%r1)
181         mtlr %r0
182         b .Lfinish
183
184 # case FFI_TYPE_SINT64
185         lwz %r3,112+0(%r1)
186         lwz %r4,112+4(%r1)
187         mtlr %r0
188         b .Lfinish
189
190 # case FFI_TYPE_STRUCT
191         mtlr %r0
192         addi %r1,%r1,144
193         blr
194         nop
195
196 # case FFI_TYPE_POINTER
197         lwz %r3,112+0(%r1)
198         mtlr %r0
199         addi %r1,%r1,144
200         blr
201
202 # case FFI_TYPE_UINT128
203         lwz %r3,112+0(%r1)
204         lwz %r4,112+4(%r1)
205         lwz %r5,112+8(%r1)
206         bl .Luint128
207
208 # The return types below are only used when the ABI type is FFI_SYSV.
209 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
210         lbz %r3,112+0(%r1)
211         mtlr %r0
212         addi %r1,%r1,144
213         blr
214
215 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
216         lhz %r3,112+0(%r1)
217         mtlr %r0
218         addi %r1,%r1,144
219         blr
220
221 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
222         lwz %r3,112+0(%r1)
223         srwi %r3,%r3,8
224         mtlr %r0
225         b .Lfinish
226
227 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
228         lwz %r3,112+0(%r1)
229         mtlr %r0
230         addi %r1,%r1,144
231         blr
232
233 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
234         lwz %r3,112+0(%r1)
235         lwz %r4,112+4(%r1)
236         li %r5,24
237         b .Lstruct567
238
239 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
240         lwz %r3,112+0(%r1)
241         lwz %r4,112+4(%r1)
242         li %r5,16
243         b .Lstruct567
244
245 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
246         lwz %r3,112+0(%r1)
247         lwz %r4,112+4(%r1)
248         li %r5,8
249         b .Lstruct567
250
251 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
252         lwz %r3,112+0(%r1)
253         lwz %r4,112+4(%r1)
254         mtlr %r0
255         b .Lfinish
256
257 .Lstruct567:
258         subfic %r6,%r5,32
259         srw %r4,%r4,%r5
260         slw %r6,%r3,%r6
261         srw %r3,%r3,%r5
262         or %r4,%r6,%r4
263         mtlr %r0
264         addi %r1,%r1,144
265         blr
266
267 .Luint128:
268         lwz %r6,112+12(%r1)
269         mtlr %r0
270         addi %r1,%r1,144
271         blr
272
273 END(ffi_closure_SYSV)
274
275         .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
276 .Lframe1:
277         .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
278 .LSCIE1:
279         .4byte  0x0      # CIE Identifier Tag
280         .byte   0x1      # CIE Version
281 #if defined _RELOCATABLE || defined __PIC__
282         .ascii "zR\0"    # CIE Augmentation
283 #else
284         .ascii "\0"      # CIE Augmentation
285 #endif
286         .uleb128 0x1     # CIE Code Alignment Factor
287         .sleb128 -4      # CIE Data Alignment Factor
288         .byte   0x41     # CIE RA Column
289 #if defined _RELOCATABLE || defined __PIC__
290         .uleb128 0x1     # Augmentation size
291         .byte   0x1b     # FDE Encoding (pcrel sdata4)
292 #endif
293         .byte   0xc      # DW_CFA_def_cfa
294         .uleb128 0x1
295         .uleb128 0x0
296         .align 2
297 .LECIE1:
298 .LSFDE1:
299         .4byte  .LEFDE1-.LASFDE1         # FDE Length
300 .LASFDE1:
301         .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
302 #if defined _RELOCATABLE || defined __PIC__
303         .4byte  .LFB1-.  # FDE initial location
304 #else
305         .4byte  .LFB1    # FDE initial location
306 #endif
307         .4byte  .LFE1-.LFB1      # FDE address range
308 #if defined _RELOCATABLE || defined __PIC__
309         .uleb128 0x0     # Augmentation size
310 #endif
311         .byte   0x4      # DW_CFA_advance_loc4
312         .4byte  .LCFI0-.LFB1
313         .byte   0xe      # DW_CFA_def_cfa_offset
314         .uleb128 144
315         .byte   0x4      # DW_CFA_advance_loc4
316         .4byte  .LCFI1-.LCFI0
317         .byte   0x11     # DW_CFA_offset_extended_sf
318         .uleb128 0x41
319         .sleb128 -1
320         .align 2
321 .LEFDE1:
322
323 #endif
324
325 #if defined __ELF__ && defined __linux__
326         .section        .note.GNU-stack,"",@progbits
327 #endif