Merge from mainline
[official-gcc.git] / libffi / src / powerpc / ppc_closure.S
blob370381378f91dafb77175dda2d26207c24160c12
1 #define LIBFFI_ASM
2 #include <fficonfig.h>
3 #include <ffi.h>
4 #include <powerpc/asm.h>
6         .file   "ppc_closure.S"
8 #ifndef __powerpc64__
10 ENTRY(ffi_closure_SYSV)
11 .LFB1:
12         stwu %r1,-144(%r1)
13 .LCFI0:
14         mflr %r0
15 .LCFI1:
16         stw %r0,148(%r1)
18 # we want to build up an areas for the parameters passed
19 # in registers (both floating point and integer)
21         # so first save gpr 3 to gpr 10 (aligned to 4)
22         stw   %r3, 16(%r1)
23         stw   %r4, 20(%r1)
24         stw   %r5, 24(%r1)
25         stw   %r6, 28(%r1)
26         stw   %r7, 32(%r1)
27         stw   %r8, 36(%r1)
28         stw   %r9, 40(%r1)
29         stw   %r10,44(%r1)
31         # next save fpr 1 to fpr 8 (aligned to 8)
32         stfd  %f1, 48(%r1)
33         stfd  %f2, 56(%r1)
34         stfd  %f3, 64(%r1)
35         stfd  %f4, 72(%r1)
36         stfd  %f5, 80(%r1)
37         stfd  %f6, 88(%r1)
38         stfd  %f7, 96(%r1)
39         stfd  %f8, 104(%r1)
41         # set up registers for the routine that actually does the work
42         # get the context pointer from the trampoline
43         mr %r3,%r11
45         # now load up the pointer to the result storage
46         addi %r4,%r1,112
48         # now load up the pointer to the saved gpr registers
49         addi %r5,%r1,16
51         # now load up the pointer to the saved fpr registers */
52         addi %r6,%r1,48
54         # now load up the pointer to the outgoing parameter
55         # stack in the previous frame
56         # i.e. the previous frame pointer + 8
57         addi %r7,%r1,152
59         # make the call
60         bl ffi_closure_helper_SYSV@local
62         # now r3 contains the return type
63         # so use it to look up in a table
64         # so we know how to deal with each type
66         # look up the proper starting point in table
67         # by using return type as offset
68         addi %r6,%r1,112   # get pointer to results area
69         bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
70         mflr %r4           # move to r4
71         slwi %r3,%r3,4     # now multiply return type by 16
72         add %r3,%r3,%r4    # add contents of table to table address
73         mtctr %r3
74         bctr               # jump to it
75 .LFE1:
77 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
78 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
79 # first.
80         .align 4
82         nop
83         nop
84         nop
85 .Lget_ret_type0_addr:
86         blrl
88 # case FFI_TYPE_VOID
89 .Lret_type0:
90         b .Lfinish
91         nop
92         nop
93         nop
95 # case FFI_TYPE_INT
96 .Lret_type1:
97         lwz %r3,0(%r6)
98         b .Lfinish
99         nop
100         nop
102 # case FFI_TYPE_FLOAT
103 .Lret_type2:
104         lfs %f1,0(%r6)
105         b .Lfinish
106         nop
107         nop
109 # case FFI_TYPE_DOUBLE
110 .Lret_type3:
111         lfd %f1,0(%r6)
112         b .Lfinish
113         nop
114         nop
116 # case FFI_TYPE_LONGDOUBLE
117 .Lret_type4:
118         lfd %f1,0(%r6)
119         b .Lfinish
120         nop
121         nop
123 # case FFI_TYPE_UINT8
124 .Lret_type5:
125         lbz %r3,3(%r6)
126         b .Lfinish
127         nop
128         nop
130 # case FFI_TYPE_SINT8
131 .Lret_type6:
132         lbz %r3,3(%r6)
133         extsb %r3,%r3
134         b .Lfinish
135         nop
137 # case FFI_TYPE_UINT16
138 .Lret_type7:
139         lhz %r3,2(%r6)
140         b .Lfinish
141         nop
142         nop
144 # case FFI_TYPE_SINT16
145 .Lret_type8:
146         lha %r3,2(%r6)
147         b .Lfinish
148         nop
149         nop
151 # case FFI_TYPE_UINT32
152 .Lret_type9:
153         lwz %r3,0(%r6)
154         b .Lfinish
155         nop
156         nop
158 # case FFI_TYPE_SINT32
159 .Lret_type10:
160         lwz %r3,0(%r6)
161         b .Lfinish
162         nop
163         nop
165 # case FFI_TYPE_UINT64
166 .Lret_type11:
167         lwz %r3,0(%r6)
168         lwz %r4,4(%r6)
169         b .Lfinish
170         nop
172 # case FFI_TYPE_SINT64
173 .Lret_type12:
174         lwz %r3,0(%r6)
175         lwz %r4,4(%r6)
176         b .Lfinish
177         nop
179 # case FFI_TYPE_STRUCT
180 .Lret_type13:
181         b .Lfinish
182         nop
183         nop
184         nop
186 # case FFI_TYPE_POINTER
187 .Lret_type14:
188         lwz %r3,0(%r6)
189         b .Lfinish
190         nop
191         nop
193 # The return types below are only used when the ABI type is FFI_SYSV.
194 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
195 .Lret_type15:
196 # fall through.
197         lbz %r3,0(%r6)
198         b .Lfinish
199         nop
200         nop
202 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
203 .Lret_type16:
204 # fall through.
205         lhz %r3,0(%r6)
206         b .Lfinish
207         nop
208         nop
210 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
211 .Lret_type17:
212 # fall through.
213         lwz %r3,0(%r6)
214         srwi %r3,%r3,8
215         b .Lfinish
216         nop
218 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
219 .Lret_type18:
220 # this one handles the structs from above too.
221         lwz %r3,0(%r6)
222         b .Lfinish
223         nop
224         nop
226 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
227 .Lret_type19:
228 # fall through.
229         lwz %r3,0(%r6)
230         lwz %r4,4(%r6)
231         li %r5,24
232         b .Lstruct567
234 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
235 .Lret_type20:
236 # fall through.
237         lwz %r3,0(%r6)
238         lwz %r4,4(%r6)
239         li %r5,16
240         b .Lstruct567
242 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
243 .Lret_type21:
244 # fall through.
245         lwz %r3,0(%r6)
246         lwz %r4,4(%r6)
247         li %r5,8
248         b .Lstruct567
250 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
251 .Lret_type22:
252 # this one handles the above unhandled structs.
253         lwz %r3,0(%r6)
254         lwz %r4,4(%r6)
255         b .Lfinish
256         nop
258 # case done
259 .Lfinish:
261         lwz %r0,148(%r1)
262         mtlr %r0
263         addi %r1,%r1,144
264         blr
266 .Lstruct567:
267         subfic %r0,%r5,32
268         srw %r4,%r4,%r5
269         slw %r0,%r3,%r0
270         srw %r3,%r3,%r5
271         or %r4,%r0,%r4
272         b .Lfinish
273 END(ffi_closure_SYSV)
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:
323 #endif