1#if defined(__ppc64__)
2
3/* -----------------------------------------------------------------------
4   ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
5   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:
300	lg		r1,0(r1)			// Restore stack pointer.
301	ld		r31,-8(r1)			// Restore registers we used.
302	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
321	.byte	0x10		; FDE Encoding (pcrel)
322	.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
335	.g_long	LFB1-.					; FDE initial location
336	.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
377.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__
419