blob: 7162fa1dda654db4de8cee2c0711255ae85b6a8b [file] [log] [blame]
Christian Heimes78644762008-03-04 23:39:23 +00001#if defined(__ppc64__)
2
3/* -----------------------------------------------------------------------
Ronald Oussoren6ce931f2009-09-20 18:57:50 +00004 ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
Christian Heimes78644762008-03-04 23:39:23 +00005 Inc. based on ppc_closure.S
6
7 PowerPC Assembly glue.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 ``Software''), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 OTHER DEALINGS IN THE SOFTWARE.
27 ----------------------------------------------------------------------- */
28
29#define LIBFFI_ASM
30
31#include <ffi.h>
32#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE
33#include <ppc-darwin.h>
34#include <architecture/ppc/mode_independent_asm.h>
35
36 .file "ppc64-darwin_closure.S"
37.text
38 .align LOG2_GPR_BYTES
39 .globl _ffi_closure_ASM
40
41.text
42 .align LOG2_GPR_BYTES
43
44_ffi_closure_ASM:
45LFB1:
46 mflr r0
47 stg r0,SF_RETURN(r1) // save return address
48
49 // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
50 stg r3,SF_ARG1(r1)
51 stg r4,SF_ARG2(r1)
52 stg r5,SF_ARG3(r1)
53 stg r6,SF_ARG4(r1)
54 stg r7,SF_ARG5(r1)
55 stg r8,SF_ARG6(r1)
56 stg r9,SF_ARG7(r1)
57 stg r10,SF_ARG8(r1)
58
59LCFI0:
60/* 48 bytes (Linkage Area)
61 64 bytes (outgoing parameter area, always reserved)
62 112 bytes (14*8 for incoming FPR)
63 ? bytes (result)
64 112 bytes (14*8 for outgoing FPR)
65 16 bytes (2 saved registers)
66 352 + ? total bytes
67*/
68
69 std r31,-8(r1) // Save registers we use.
70 std r30,-16(r1)
71 mr r30,r1 // Save the old SP.
72 mr r31,r11 // Save the ffi_closure around ffi64_data_size.
73
74 // Calculate the space we need.
75 stdu r1,-SF_MINSIZE(r1)
76 ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
77 ld r3,16(r3) // ffi_cif->rtype*
78 bl Lffi64_data_size$stub
79 ld r1,0(r1)
80
81 addi r3,r3,352 // Add our overhead.
82 neg r3,r3
83 li r0,-32 // Align to 32 bytes.
84 and r3,r3,r0
85 stdux r1,r1,r3 // Grow the stack.
86
87 mr r11,r31 // Copy the ffi_closure back.
88
89LCFI1:
90 // We want to build up an area for the parameters passed
91 // in registers. (both floating point and integer)
92
93/* 320 bytes (callee stack frame aligned to 32)
94 48 bytes (caller linkage area)
95 368 (start of caller parameter area aligned to 8)
96*/
97
98 // Save FPRs 1 - 14. (aligned to 8)
99 stfd f1,112(r1)
100 stfd f2,120(r1)
101 stfd f3,128(r1)
102 stfd f4,136(r1)
103 stfd f5,144(r1)
104 stfd f6,152(r1)
105 stfd f7,160(r1)
106 stfd f8,168(r1)
107 stfd f9,176(r1)
108 stfd f10,184(r1)
109 stfd f11,192(r1)
110 stfd f12,200(r1)
111 stfd f13,208(r1)
112 stfd f14,216(r1)
113
114 // Set up registers for the routine that actually does the work.
115 mr r3,r11 // context pointer from the trampoline
116 addi r4,r1,224 // result storage
117 addi r5,r30,SF_ARG1 // saved GPRs
118 addi r6,r1,112 // saved FPRs
119 bl Lffi_closure_helper_DARWIN$stub
120
121 // Look the proper starting point in table
122 // by using return type as an offset.
123 addi r5,r1,224 // Get pointer to results area.
124 bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
125 mflr r4 // Move to r4.
126 slwi r3,r3,4 // Now multiply return type by 16.
127 add r3,r3,r4 // Add contents of table to table address.
128 mtctr r3
129 bctr
130
131LFE1:
132 // Each of the ret_typeX code fragments has to be exactly 16 bytes long
133 // (4 instructions). For cache effectiveness we align to a 16 byte
134 // boundary first.
135 .align 4
136 nop
137 nop
138 nop
139
140Lget_ret_type0_addr:
141 blrl
142
143// case FFI_TYPE_VOID
144Lret_type0:
145 b Lfinish
146 nop
147 nop
148 nop
149
150// case FFI_TYPE_INT
151Lret_type1:
152 lwz r3,4(r5)
153 b Lfinish
154 nop
155 nop
156
157// case FFI_TYPE_FLOAT
158Lret_type2:
159 lfs f1,0(r5)
160 b Lfinish
161 nop
162 nop
163
164// case FFI_TYPE_DOUBLE
165Lret_type3:
166 lfd f1,0(r5)
167 b Lfinish
168 nop
169 nop
170
171// case FFI_TYPE_LONGDOUBLE
172Lret_type4:
173 lfd f1,0(r5)
174 lfd f2,8(r5)
175 b Lfinish
176 nop
177
178// case FFI_TYPE_UINT8
179Lret_type5:
180 lbz r3,7(r5)
181 b Lfinish
182 nop
183 nop
184
185// case FFI_TYPE_SINT8
186Lret_type6:
187 lbz r3,7(r5)
188 extsb r3,r3
189 b Lfinish
190 nop
191
192// case FFI_TYPE_UINT16
193Lret_type7:
194 lhz r3,6(r5)
195 b Lfinish
196 nop
197 nop
198
199// case FFI_TYPE_SINT16
200Lret_type8:
201 lha r3,6(r5)
202 b Lfinish
203 nop
204 nop
205
206// case FFI_TYPE_UINT32
207Lret_type9: // same as Lret_type1
208 lwz r3,4(r5)
209 b Lfinish
210 nop
211 nop
212
213// case FFI_TYPE_SINT32
214Lret_type10: // same as Lret_type1
215 lwz r3,4(r5)
216 b Lfinish
217 nop
218 nop
219
220// case FFI_TYPE_UINT64
221Lret_type11:
222 ld r3,0(r5)
223 b Lfinish
224 nop
225 nop
226
227// case FFI_TYPE_SINT64
228Lret_type12: // same as Lret_type11
229 ld r3,0(r5)
230 b Lfinish
231 nop
232 nop
233
234// case FFI_TYPE_STRUCT
235Lret_type13:
236 b Lret_struct
237 nop
238 nop
239 nop
240
241// ** End 16-byte aligned cases **
242// case FFI_TYPE_POINTER
243// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
244// are added in future, the following code will need to be updated and
245// padded to 16 bytes.
246Lret_type14:
247 lg r3,0(r5)
248 b Lfinish
249
250// copy struct into registers
251Lret_struct:
252 ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
253 ld r3,16(r31) // ffi_cif->rtype*
254 ld r31,24(r31) // ffi_cif->flags
255 mr r4,r5 // copy struct* to 2nd arg
256 addi r7,r1,SF_ARG9 // GPR return area
257 addi r9,r30,-16-(14*8) // FPR return area
258 li r5,0 // struct offset ptr (NULL)
259 li r6,0 // FPR used count ptr (NULL)
260 li r8,0 // GPR return area size ptr (NULL)
261 li r10,0 // FPR return area size ptr (NULL)
262 bl Lffi64_struct_to_reg_form$stub
263
264 // Load GPRs
265 ld r3,SF_ARG9(r1)
266 ld r4,SF_ARG10(r1)
267 ld r5,SF_ARG11(r1)
268 ld r6,SF_ARG12(r1)
269 nop
270 ld r7,SF_ARG13(r1)
271 ld r8,SF_ARG14(r1)
272 ld r9,SF_ARG15(r1)
273 ld r10,SF_ARG16(r1)
274 nop
275
276 // Load FPRs
277 mtcrf 0x2,r31
278 bf 26,Lfinish
279 lfd f1,-16-(14*8)(r30)
280 lfd f2,-16-(13*8)(r30)
281 lfd f3,-16-(12*8)(r30)
282 lfd f4,-16-(11*8)(r30)
283 nop
284 lfd f5,-16-(10*8)(r30)
285 lfd f6,-16-(9*8)(r30)
286 lfd f7,-16-(8*8)(r30)
287 lfd f8,-16-(7*8)(r30)
288 nop
289 lfd f9,-16-(6*8)(r30)
290 lfd f10,-16-(5*8)(r30)
291 lfd f11,-16-(4*8)(r30)
292 lfd f12,-16-(3*8)(r30)
293 nop
294 lfd f13,-16-(2*8)(r30)
295 lfd f14,-16-(1*8)(r30)
296 // Fall through
297
298// case done
299Lfinish:
Ronald Oussoren6ce931f2009-09-20 18:57:50 +0000300 lg r1,0(r1) // Restore stack pointer.
301 ld r31,-8(r1) // Restore registers we used.
Christian Heimes78644762008-03-04 23:39:23 +0000302 ld r30,-16(r1)
303 lg r0,SF_RETURN(r1) // Get return address.
304 mtlr r0 // Reset link register.
305 blr
306
307// END(ffi_closure_ASM)
308
309.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
310EH_frame1:
311 .set L$set$0,LECIE1-LSCIE1
312 .long L$set$0 ; Length of Common Information Entry
313LSCIE1:
314 .long 0x0 ; CIE Identifier Tag
315 .byte 0x1 ; CIE Version
316 .ascii "zR\0" ; CIE Augmentation
317 .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
318 .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
319 .byte 0x41 ; CIE RA Column
320 .byte 0x1 ; uleb128 0x1; Augmentation size
Ronald Oussoren6ce931f2009-09-20 18:57:50 +0000321 .byte 0x10 ; FDE Encoding (pcrel)
Christian Heimes78644762008-03-04 23:39:23 +0000322 .byte 0xc ; DW_CFA_def_cfa
323 .byte 0x1 ; uleb128 0x1
324 .byte 0x0 ; uleb128 0x0
325 .align LOG2_GPR_BYTES
326LECIE1:
327.globl _ffi_closure_ASM.eh
328_ffi_closure_ASM.eh:
329LSFDE1:
330 .set L$set$1,LEFDE1-LASFDE1
331 .long L$set$1 ; FDE Length
332
333LASFDE1:
334 .long LASFDE1-EH_frame1 ; FDE CIE offset
Ronald Oussoren6ce931f2009-09-20 18:57:50 +0000335 .g_long LFB1-. ; FDE initial location
Christian Heimes78644762008-03-04 23:39:23 +0000336 .set L$set$3,LFE1-LFB1
337 .g_long L$set$3 ; FDE address range
338 .byte 0x0 ; uleb128 0x0; Augmentation size
339 .byte 0x4 ; DW_CFA_advance_loc4
340 .set L$set$3,LCFI1-LCFI0
341 .long L$set$3
342 .byte 0xe ; DW_CFA_def_cfa_offset
343 .byte 176,1 ; uleb128 176
344 .byte 0x4 ; DW_CFA_advance_loc4
345 .set L$set$4,LCFI0-LFB1
346 .long L$set$4
347 .byte 0x11 ; DW_CFA_offset_extended_sf
348 .byte 0x41 ; uleb128 0x41
349 .byte 0x7e ; sleb128 -2
350 .align LOG2_GPR_BYTES
351
352LEFDE1:
353.data
354 .align LOG2_GPR_BYTES
355LDFCM0:
356.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
357 .align LOG2_GPR_BYTES
358
359Lffi_closure_helper_DARWIN$stub:
360 .indirect_symbol _ffi_closure_helper_DARWIN
361 mflr r0
362 bcl 20,31,LO$ffi_closure_helper_DARWIN
363
364LO$ffi_closure_helper_DARWIN:
365 mflr r11
366 addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
367 mtlr r0
368 lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
369 mtctr r12
370 bctr
371
372.lazy_symbol_pointer
373L_ffi_closure_helper_DARWIN$lazy_ptr:
374 .indirect_symbol _ffi_closure_helper_DARWIN
375 .g_long dyld_stub_binding_helper
376
Christian Heimes78644762008-03-04 23:39:23 +0000377.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
378 .align LOG2_GPR_BYTES
379
380Lffi64_struct_to_reg_form$stub:
381 .indirect_symbol _ffi64_struct_to_reg_form
382 mflr r0
383 bcl 20,31,LO$ffi64_struct_to_reg_form
384
385LO$ffi64_struct_to_reg_form:
386 mflr r11
387 addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
388 mtlr r0
389 lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
390 mtctr r12
391 bctr
392
393.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
394 .align LOG2_GPR_BYTES
395
396Lffi64_data_size$stub:
397 .indirect_symbol _ffi64_data_size
398 mflr r0
399 bcl 20,31,LO$ffi64_data_size
400
401LO$ffi64_data_size:
402 mflr r11
403 addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
404 mtlr r0
405 lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
406 mtctr r12
407 bctr
408
409.lazy_symbol_pointer
410L_ffi64_struct_to_reg_form$lazy_ptr:
411 .indirect_symbol _ffi64_struct_to_reg_form
412 .g_long dyld_stub_binding_helper
413
414L_ffi64_data_size$lazy_ptr:
415 .indirect_symbol _ffi64_data_size
416 .g_long dyld_stub_binding_helper
417
418#endif // __ppc64__