1/* -----------------------------------------------------------------------
2   darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
3   Inc. based on ppc_closure.S
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, EXPRESS
19   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
22   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24   OTHER DEALINGS IN THE SOFTWARE.
25   ----------------------------------------------------------------------- */
26
27#define LIBFFI_ASM
28#define L(x) x
29
30#if defined(__ppc64__)
31#define MODE_CHOICE(x, y) y
32#else
33#define MODE_CHOICE(x, y) x
34#endif
35
36#define lgu     MODE_CHOICE(lwzu, ldu)
37
38#define g_long  MODE_CHOICE(long, quad)         /* usage is ".g_long" */
39
40#define LOG2_GPR_BYTES  MODE_CHOICE(2,3)        /* log2(GPR_BYTES) */
41
42	.file	"darwin_closure.S"
43.text
44	.align LOG2_GPR_BYTES
45.globl _ffi_closure_ASM
46
47.text
48	.align LOG2_GPR_BYTES
49_ffi_closure_ASM:
50LFB1:
51	mflr	r0		/* extract return address  */
52	stw	r0,8(r1)	/* save the return address  */
53LCFI0:
54	/* 24 Bytes (Linkage Area)
55	   32 Bytes (outgoing parameter area, always reserved)
56	   104 Bytes (13*8 from FPR)
57	   16 Bytes (result)
58	   176 Bytes  */
59
60	stwu	r1,-176(r1)	/* skip over caller save area
61				keep stack aligned to 16.  */
62LCFI1:
63	/* We want to build up an area for the parameters passed
64	   in registers. (both floating point and integer)  */
65
66	/* We store gpr 3 to gpr 10 (aligned to 4)
67	   in the parents outgoing area.  */
68	stw   r3,200(r1)
69	stw   r4,204(r1)
70	stw   r5,208(r1)
71	stw   r6,212(r1)
72	stw   r7,216(r1)
73	stw   r8,220(r1)
74	stw   r9,224(r1)
75	stw   r10,228(r1)
76
77	/* We save fpr 1 to fpr 13. (aligned to 8)  */
78	stfd  f1,56(r1)
79	stfd  f2,64(r1)
80	stfd  f3,72(r1)
81	stfd  f4,80(r1)
82	stfd  f5,88(r1)
83	stfd  f6,96(r1)
84	stfd  f7,104(r1)
85	stfd  f8,112(r1)
86	stfd  f9,120(r1)
87	stfd  f10,128(r1)
88	stfd  f11,136(r1)
89	stfd  f12,144(r1)
90	stfd  f13,152(r1)
91
92	/* Set up registers for the routine that actually does the work
93	   get the context pointer from the trampoline.  */
94	mr r3,r11
95
96	/* Now load up the pointer to the result storage.  */
97	addi r4,r1,160
98
99	/* Now load up the pointer to the saved gpr registers.  */
100	addi r5,r1,200
101
102	/* Now load up the pointer to the saved fpr registers.  */
103	addi r6,r1,56
104
105	/* Make the call.  */
106	bl	Lffi_closure_helper_DARWIN$stub
107
108	/* Now r3 contains the return type
109	   so use it to look up in a table
110	   so we know how to deal with each type.  */
111
112	/* Look up the proper starting point in table
113	   by using return type as offset.  */
114	addi  r5,r1,160		  /* Get pointer to results area.  */
115	bl    Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR.  */
116	mflr  r4		  /* Move to r4.  */
117	slwi  r3,r3,4		  /* Now multiply return type by 16.  */
118	add   r3,r3,r4		  /* Add contents of table to table address.  */
119	mtctr r3
120	bctr			  /* Jump to it.  */
121LFE1:
122/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
123   (4 instructions). For cache effectiveness we align to a 16 byte boundary
124   first.  */
125
126	.align 4
127
128	nop
129	nop
130	nop
131Lget_ret_type0_addr:
132	blrl
133
134/* case FFI_TYPE_VOID  */
135Lret_type0:
136	b	Lfinish
137	nop
138	nop
139	nop
140
141/* case FFI_TYPE_INT  */
142Lret_type1:
143	lwz	r3,0(r5)
144	b	Lfinish
145	nop
146	nop
147
148/* case FFI_TYPE_FLOAT  */
149Lret_type2:
150	lfs	f1,0(r5)
151	b	Lfinish
152	nop
153	nop
154
155/* case FFI_TYPE_DOUBLE  */
156Lret_type3:
157	lfd	f1,0(r5)
158	b	Lfinish
159	nop
160	nop
161
162/* case FFI_TYPE_LONGDOUBLE  */
163Lret_type4:
164	lfd	f1,0(r5)
165	lfd	f2,8(r5)
166	b	Lfinish
167	nop
168
169/* case FFI_TYPE_UINT8  */
170Lret_type5:
171	lbz	r3,3(r5)
172	b	Lfinish
173	nop
174	nop
175
176/* case FFI_TYPE_SINT8  */
177Lret_type6:
178	lbz	r3,3(r5)
179	extsb	r3,r3
180	b	Lfinish
181	nop
182
183/* case FFI_TYPE_UINT16  */
184Lret_type7:
185	lhz	r3,2(r5)
186	b	Lfinish
187	nop
188	nop
189
190/* case FFI_TYPE_SINT16  */
191Lret_type8:
192	lha	r3,2(r5)
193	b	Lfinish
194	nop
195	nop
196
197/* case FFI_TYPE_UINT32  */
198Lret_type9:
199	lwz	r3,0(r5)
200	b	Lfinish
201	nop
202	nop
203
204/* case FFI_TYPE_SINT32  */
205Lret_type10:
206	lwz	r3,0(r5)
207	b	Lfinish
208	nop
209	nop
210
211/* case FFI_TYPE_UINT64  */
212Lret_type11:
213	lwz	r3,0(r5)
214	lwz	r4,4(r5)
215	b	Lfinish
216	nop
217
218/* case FFI_TYPE_SINT64  */
219Lret_type12:
220	lwz	r3,0(r5)
221	lwz	r4,4(r5)
222	b	Lfinish
223	nop
224
225/* case FFI_TYPE_STRUCT  */
226Lret_type13:
227	b	Lfinish
228	nop
229	nop
230	nop
231
232/* case FFI_TYPE_POINTER  */
233Lret_type14:
234	lwz	r3,0(r5)
235	b	Lfinish
236	nop
237	nop
238
239/* case done  */
240Lfinish:
241	addi	r1,r1,176	/* Restore stack pointer.  */
242	lwz	r0,8(r1)	/* Get return address.  */
243	mtlr	r0		/* Reset link register.  */
244	blr
245
246/* END(ffi_closure_ASM)  */
247
248.data
249.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
250EH_frame1:
251	.set	L$set$0,LECIE1-LSCIE1
252	.long	L$set$0	; Length of Common Information Entry
253LSCIE1:
254	.long	0x0	; CIE Identifier Tag
255	.byte	0x1	; CIE Version
256	.ascii	"zR\0"	; CIE Augmentation
257	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
258	.byte	0x7c	; sleb128 -4; CIE Data Alignment Factor
259	.byte	0x41	; CIE RA Column
260	.byte	0x1	; uleb128 0x1; Augmentation size
261	.byte	0x90	; FDE Encoding (indirect pcrel)
262	.byte	0xc	; DW_CFA_def_cfa
263	.byte	0x1	; uleb128 0x1
264	.byte	0x0	; uleb128 0x0
265	.align	LOG2_GPR_BYTES
266LECIE1:
267.globl _ffi_closure_ASM.eh
268_ffi_closure_ASM.eh:
269LSFDE1:
270	.set	L$set$1,LEFDE1-LASFDE1
271	.long	L$set$1	; FDE Length
272
273LASFDE1:
274	.long	LASFDE1-EH_frame1	; FDE CIE offset
275	.g_long	LLFB1$non_lazy_ptr-.	; FDE initial location
276	.set	L$set$3,LFE1-LFB1
277	.g_long	L$set$3	; FDE address range
278	.byte   0x0     ; uleb128 0x0; Augmentation size
279	.byte	0x4	; DW_CFA_advance_loc4
280	.set	L$set$3,LCFI1-LCFI0
281	.long	L$set$3
282	.byte	0xe	; DW_CFA_def_cfa_offset
283	.byte	176,1	; uleb128 176
284	.byte	0x4	; DW_CFA_advance_loc4
285	.set	L$set$4,LCFI0-LFB1
286	.long	L$set$4
287	.byte   0x11    ; DW_CFA_offset_extended_sf
288	.byte	0x41	; uleb128 0x41
289	.byte   0x7e    ; sleb128 -2
290	.align	LOG2_GPR_BYTES
291LEFDE1:
292.data
293	.align	LOG2_GPR_BYTES
294LDFCM0:
295.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
296	.align	LOG2_GPR_BYTES
297Lffi_closure_helper_DARWIN$stub:
298#if 1
299	.indirect_symbol _ffi_closure_helper_DARWIN
300	mflr	r0
301	bcl	20,31,LO$ffi_closure_helper_DARWIN
302LO$ffi_closure_helper_DARWIN:
303	mflr	r11
304	addis	r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
305	mtlr	r0
306	lgu	r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
307	mtctr	r12
308	bctr
309.lazy_symbol_pointer
310L_ffi_closure_helper_DARWIN$lazy_ptr:
311	.indirect_symbol _ffi_closure_helper_DARWIN
312	.g_long dyld_stub_binding_helper
313#endif
314.data
315	.align LOG2_GPR_BYTES
316LLFB1$non_lazy_ptr:
317	.g_long LFB1
318