1#if defined(__ppc__) || defined(__ppc64__)
2
3/* -----------------------------------------------------------------------
4   ppc-darwin.S - Copyright (c) 2000 John Hornkvist
5	      Copyright (c) 2004 Free Software Foundation, Inc.
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 <fficonfig.h>
32#include <ffi.h>
33#include <ppc-darwin.h>
34#include <architecture/ppc/mode_independent_asm.h>
35
36.text
37	.align 2
38.globl _ffi_prep_args
39
40.text
41	.align 2
42.globl _ffi_call_DARWIN
43
44.text
45	.align 2
46_ffi_call_DARWIN:
47LFB0:
48	mr		r12,r8	/* We only need r12 until the call,
49					so it doesn't have to be saved.  */
50
51LFB1:
52	/* Save the old stack pointer as AP.  */
53	mr		r8,r1
54
55LCFI0:
56#if defined(__ppc64__)
57	/*	Allocate the stack space we need.
58		r4 (size of input data)
59		48 bytes (linkage area)
60		40 bytes (saved registers)
61		8 bytes (extra FPR)
62		r4 + 96 bytes total
63	*/
64
65	addi	r4,r4,-96	// Add our overhead.
66	li		r0,-32		// Align to 32 bytes.
67	and		r4,r4,r0
68#endif
69	stgux	r1,r1,r4	// Grow the stack.
70	mflr	r9
71
72	/* Save registers we use.  */
73#if defined(__ppc64__)
74	std		r27,-40(r8)
75#endif
76	stg		r28,MODE_CHOICE(-16,-32)(r8)
77	stg		r29,MODE_CHOICE(-12,-24)(r8)
78	stg		r30,MODE_CHOICE(-8,-16)(r8)
79	stg		r31,MODE_CHOICE(-4,-8)(r8)
80	stg		r9,SF_RETURN(r8)			/* return address */
81#if !defined(POWERPC_DARWIN)			/* TOC unused in OS X */
82	stg		r2,MODE_CHOICE(20,40)(r1)
83#endif
84
85LCFI1:
86#if defined(__ppc64__)
87	mr		r27,r3	// our extended_cif
88#endif
89	/* Save arguments over call.  */
90	mr		r31,r5	/* flags,  */
91	mr		r30,r6	/* rvalue,  */
92	mr		r29,r7	/* function address,  */
93	mr		r28,r8	/* our AP.  */
94
95LCFI2:
96	/* Call ffi_prep_args.  */
97	mr		r4,r1
98	li		r9,0
99	mtctr	r12 /* r12 holds address of _ffi_prep_args.  */
100	bctrl
101#if !defined(POWERPC_DARWIN)			/* TOC unused in OS X */
102	lg		r2,MODE_CHOICE(20,40)(r1)
103#endif
104
105	/* Now do the call.
106	   Set up cr1 with bits 4-7 of the flags.  */
107	mtcrf	0x40,r31
108
109	/* Load all those argument registers.
110	   We have set up a nice stack frame, just load it into registers.  */
111	lg		r3,SF_ARG1(r1)
112	lg		r4,SF_ARG2(r1)
113	lg		r5,SF_ARG3(r1)
114	lg		r6,SF_ARG4(r1)
115	nop
116	lg		r7,SF_ARG5(r1)
117	lg		r8,SF_ARG6(r1)
118	lg		r9,SF_ARG7(r1)
119	lg		r10,SF_ARG8(r1)
120
121	/* Load all the FP registers.  */
122	bf		6,L2	/* No floats to load.  */
123#if defined(__ppc64__)
124	lfd		f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
125	lfd		f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
126	lfd		f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
127	lfd		f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
128	nop
129	lfd		f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
130	lfd		f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
131	lfd		f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
132	lfd		f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
133	nop
134	lfd		f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
135	lfd		f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
136	lfd		f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
137	lfd		f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
138	nop
139	lfd		f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
140	lfd		f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
141#elif defined(__ppc__)
142	lfd		f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
143	lfd		f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
144	lfd		f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
145	lfd		f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
146	nop
147	lfd		f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
148	lfd		f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
149	lfd		f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
150	lfd		f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
151	nop
152	lfd		f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
153	lfd		f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
154	lfd		f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
155	lfd		f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
156	nop
157	lfd		f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
158#else
159#error undefined architecture
160#endif
161
162L2:
163	mr		r12,r29	// Put the target address in r12 as specified.
164	mtctr  	r12		// Get the address to call into CTR.
165	nop
166	nop
167	bctrl	// Make the call.
168
169	// Deal with the return value.
170#if defined(__ppc64__)
171	mtcrf	0x3,r31		// flags in cr6 and cr7
172	bt		27,L(st_return_value)
173#elif defined(__ppc__)
174	mtcrf	0x1,r31		// flags in cr7
175#else
176#error undefined architecture
177#endif
178
179	bt		30,L(done_return_value)
180	bt		29,L(fp_return_value)
181	stg		r3,0(r30)
182#if defined(__ppc__)
183	bf		28,L(done_return_value)	// Store the second long if necessary.
184	stg		r4,4(r30)
185#endif
186	// Fall through
187
188L(done_return_value):
189	lg		r1,0(r1)			// Restore stack pointer.
190	// Restore the registers we used.
191	lg		r9,SF_RETURN(r1)	// return address
192	lg		r31,MODE_CHOICE(-4,-8)(r1)
193	mtlr	r9
194	lg		r30,MODE_CHOICE(-8,-16)(r1)
195	lg		r29,MODE_CHOICE(-12,-24)(r1)
196	lg		r28,MODE_CHOICE(-16,-32)(r1)
197#if defined(__ppc64__)
198	ld		r27,-40(r1)
199#endif
200	blr
201
202#if defined(__ppc64__)
203L(st_return_value):
204	// Grow the stack enough to fit the registers. Leave room for 8 args
205	// to trample the 1st 8 slots in param area.
206	stgu	r1,-SF_ROUND(280)(r1)	// 64 + 104 + 48 + 64
207
208	// Store GPRs
209	std		r3,SF_ARG9(r1)
210	std		r4,SF_ARG10(r1)
211	std		r5,SF_ARG11(r1)
212	std		r6,SF_ARG12(r1)
213	nop
214	std		r7,SF_ARG13(r1)
215	std		r8,SF_ARG14(r1)
216	std		r9,SF_ARG15(r1)
217	std		r10,SF_ARG16(r1)
218
219	// Store FPRs
220	nop
221	bf		26,L(call_struct_to_ram_form)
222	stfd	f1,SF_ARG17(r1)
223	stfd	f2,SF_ARG18(r1)
224	stfd	f3,SF_ARG19(r1)
225	stfd	f4,SF_ARG20(r1)
226	nop
227	stfd	f5,SF_ARG21(r1)
228	stfd	f6,SF_ARG22(r1)
229	stfd	f7,SF_ARG23(r1)
230	stfd	f8,SF_ARG24(r1)
231	nop
232	stfd	f9,SF_ARG25(r1)
233	stfd	f10,SF_ARG26(r1)
234	stfd	f11,SF_ARG27(r1)
235	stfd	f12,SF_ARG28(r1)
236	nop
237	stfd	f13,SF_ARG29(r1)
238
239L(call_struct_to_ram_form):
240	ld		r3,0(r27)			// extended_cif->cif*
241	ld		r3,16(r3)			// ffi_cif->rtype*
242	addi	r4,r1,SF_ARG9		// stored GPRs
243	addi	r6,r1,SF_ARG17		// stored FPRs
244	li		r5,0				// GPR size ptr (NULL)
245	li		r7,0				// FPR size ptr (NULL)
246	li		r8,0				// FPR count ptr (NULL)
247	li		r10,0				// struct offset (NULL)
248	mr		r9,r30				// return area
249	bl		Lffi64_struct_to_ram_form$stub
250	lg		r1,0(r1)			// Restore stack pointer.
251	b		L(done_return_value)
252#endif
253
254L(fp_return_value):
255	/* Do we have long double to store?  */
256	bf		31,L(fd_return_value)
257	stfd	f1,0(r30)
258	stfd	f2,8(r30)
259	b		L(done_return_value)
260
261L(fd_return_value):
262	/* Do we have double to store?  */
263	bf		28,L(float_return_value)
264	stfd	f1,0(r30)
265	b		L(done_return_value)
266
267L(float_return_value):
268	/* We only have a float to store.  */
269	stfs	f1,0(r30)
270	b		L(done_return_value)
271
272LFE1:
273/* END(_ffi_call_DARWIN)  */
274
275/* Provide a null definition of _ffi_call_AIX.  */
276.text
277	.align 2
278.globl _ffi_call_AIX
279.text
280	.align 2
281_ffi_call_AIX:
282	blr
283/* END(_ffi_call_AIX)  */
284
285.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
286EH_frame1:
287	.set	L$set$0,LECIE1-LSCIE1
288	.long	L$set$0		; Length of Common Information Entry
289LSCIE1:
290	.long	0x0			; CIE Identifier Tag
291	.byte	0x1			; CIE Version
292	.ascii	"zR\0"		; CIE Augmentation
293	.byte	0x1			; uleb128 0x1; CIE Code Alignment Factor
294	.byte	0x7c		; sleb128 -4; CIE Data Alignment Factor
295	.byte	0x41		; CIE RA Column
296	.byte	0x1			; uleb128 0x1; Augmentation size
297	.byte	0x10		; FDE Encoding (pcrel)
298	.byte	0xc			; DW_CFA_def_cfa
299	.byte	0x1			; uleb128 0x1
300	.byte	0x0			; uleb128 0x0
301	.align	LOG2_GPR_BYTES
302LECIE1:
303.globl _ffi_call_DARWIN.eh
304_ffi_call_DARWIN.eh:
305LSFDE1:
306	.set	L$set$1,LEFDE1-LASFDE1
307	.long	L$set$1		; FDE Length
308
309LASFDE1:
310	.long	LASFDE1-EH_frame1		; FDE CIE offset
311	.g_long	LFB0-.					; FDE initial location
312	.set	L$set$3,LFE1-LFB0
313	.g_long	L$set$3					; FDE address range
314	.byte   0x0     				; uleb128 0x0; Augmentation size
315	.byte	0x4						; DW_CFA_advance_loc4
316	.set	L$set$4,LCFI0-LFB1
317	.long	L$set$4
318	.byte	0xd						; DW_CFA_def_cfa_register
319	.byte	0x08					; uleb128 0x08
320	.byte	0x4						; DW_CFA_advance_loc4
321	.set	L$set$5,LCFI1-LCFI0
322	.long	L$set$5
323	.byte   0x11					; DW_CFA_offset_extended_sf
324	.byte	0x41					; uleb128 0x41
325	.byte   0x7e					; sleb128 -2
326	.byte	0x9f					; DW_CFA_offset, column 0x1f
327	.byte	0x1						; uleb128 0x1
328	.byte	0x9e					; DW_CFA_offset, column 0x1e
329	.byte	0x2						; uleb128 0x2
330	.byte	0x9d					; DW_CFA_offset, column 0x1d
331	.byte	0x3						; uleb128 0x3
332	.byte	0x9c					; DW_CFA_offset, column 0x1c
333	.byte	0x4						; uleb128 0x4
334	.byte	0x4						; DW_CFA_advance_loc4
335	.set	L$set$6,LCFI2-LCFI1
336	.long	L$set$6
337	.byte	0xd						; DW_CFA_def_cfa_register
338	.byte	0x1c					; uleb128 0x1c
339	.align LOG2_GPR_BYTES
340LEFDE1:
341
342#if defined(__ppc64__)
343.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
344	.align	LOG2_GPR_BYTES
345
346Lffi64_struct_to_ram_form$stub:
347	.indirect_symbol _ffi64_struct_to_ram_form
348	mflr	r0
349	bcl		20,31,LO$ffi64_struct_to_ram_form
350
351LO$ffi64_struct_to_ram_form:
352	mflr	r11
353	addis	r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
354	mtlr	r0
355	lgu		r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
356	mtctr	r12
357	bctr
358
359.lazy_symbol_pointer
360L_ffi64_struct_to_ram_form$lazy_ptr:
361	.indirect_symbol _ffi64_struct_to_ram_form
362	.g_long dyld_stub_binding_helper
363
364#endif // __ppc64__
365#endif // __ppc__ || __ppc64__
366