1/* -----------------------------------------------------------------------
2   aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc.
3   based on darwin_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	.set r0,0
28	.set r1,1
29	.set r2,2
30	.set r3,3
31	.set r4,4
32	.set r5,5
33	.set r6,6
34	.set r7,7
35	.set r8,8
36	.set r9,9
37	.set r10,10
38	.set r11,11
39	.set r12,12
40	.set r13,13
41	.set r14,14
42	.set r15,15
43	.set r16,16
44	.set r17,17
45	.set r18,18
46	.set r19,19
47	.set r20,20
48	.set r21,21
49	.set r22,22
50	.set r23,23
51	.set r24,24
52	.set r25,25
53	.set r26,26
54	.set r27,27
55	.set r28,28
56	.set r29,29
57	.set r30,30
58	.set r31,31
59	.set f0,0
60	.set f1,1
61	.set f2,2
62	.set f3,3
63	.set f4,4
64	.set f5,5
65	.set f6,6
66	.set f7,7
67	.set f8,8
68	.set f9,9
69	.set f10,10
70	.set f11,11
71	.set f12,12
72	.set f13,13
73	.set f14,14
74	.set f15,15
75	.set f16,16
76	.set f17,17
77	.set f18,18
78	.set f19,19
79	.set f20,20
80	.set f21,21
81
82	.extern .ffi_closure_helper_DARWIN
83
84#define LIBFFI_ASM
85#define JUMPTARGET(name) name
86#define L(x) x
87	.file "aix_closure.S"
88	.toc
89LC..60:
90	.tc L..60[TC],L..60
91	.csect .text[PR]
92	.align 2
93
94.csect .text[PR]
95	.align 2
96	.globl ffi_closure_ASM
97	.globl .ffi_closure_ASM
98.csect ffi_closure_ASM[DS]
99ffi_closure_ASM:
100#ifdef __64BIT__
101	.llong .ffi_closure_ASM, TOC[tc0], 0
102	.csect .text[PR]
103.ffi_closure_ASM:
104/* we want to build up an area for the parameters passed */
105/* in registers (both floating point and integer) */
106
107	/* we store gpr 3 to gpr 10 (aligned to 4)
108	in the parents outgoing area  */
109	std   r3, 48+(0*8)(r1)
110	std   r4, 48+(1*8)(r1)
111	std   r5, 48+(2*8)(r1)
112	std   r6, 48+(3*8)(r1)
113	mflr  r0
114
115	std   r7, 48+(4*8)(r1)
116	std   r8, 48+(5*8)(r1)
117	std   r9, 48+(6*8)(r1)
118	std   r10, 48+(7*8)(r1)
119	std   r0, 16(r1)	/* save the return address */
120
121
122	/* 48  Bytes (Linkage Area) */
123	/* 64  Bytes (params) */
124	/* 16  Bytes (result) */
125	/* 104 Bytes (13*8 from FPR) */
126	/* 8   Bytes (alignment) */
127	/* 240 Bytes */
128
129	stdu  r1, -240(r1)	/* skip over caller save area
130				   keep stack aligned to 16  */
131
132	/* next save fpr 1 to fpr 13 (aligned to 8) */
133	stfd  f1, 128+(0*8)(r1)
134	stfd  f2, 128+(1*8)(r1)
135	stfd  f3, 128+(2*8)(r1)
136	stfd  f4, 128+(3*8)(r1)
137	stfd  f5, 128+(4*8)(r1)
138	stfd  f6, 128+(5*8)(r1)
139	stfd  f7, 128+(6*8)(r1)
140	stfd  f8, 128+(7*8)(r1)
141	stfd  f9, 128+(8*8)(r1)
142	stfd  f10, 128+(9*8)(r1)
143	stfd  f11, 128+(10*8)(r1)
144	stfd  f12, 128+(11*8)(r1)
145	stfd  f13, 128+(12*8)(r1)
146
147	/* set up registers for the routine that actually does the work */
148	/* get the context pointer from the trampoline */
149	mr r3, r11
150
151	/* now load up the pointer to the result storage */
152	addi r4, r1, 112
153
154	/* now load up the pointer to the saved gpr registers */
155	addi r5, r1, 288
156
157	/* now load up the pointer to the saved fpr registers */
158	addi r6, r1, 128
159
160	/* make the call */
161	bl .ffi_closure_helper_DARWIN
162	nop
163
164	/* now r3 contains the return type */
165	/* so use it to look up in a table */
166	/* so we know how to deal with each type */
167
168	/* look up the proper starting point in table  */
169	/* by using return type as offset */
170	lhz	r3, 10(r3)	/* load type from return type */
171	ld	r4, LC..60(2)	/* get address of jump table */
172	sldi	r3, r3, 4	/* now multiply return type by 16 */
173	ld	r0, 240+16(r1)	/* load return address */
174	add	r3, r3, r4	/* add contents of table to table address */
175	mtctr	r3
176	bctr			/* jump to it */
177
178/* Each fragment must be exactly 16 bytes long (4 instructions).
179   Align to 16 byte boundary for cache and dispatch efficiency.  */
180	.align 4
181
182L..60:
183/* case FFI_TYPE_VOID */
184	mtlr r0
185	addi r1, r1, 240
186	blr
187	nop
188
189/* case FFI_TYPE_INT */
190	lwa r3, 112+4(r1)
191	mtlr r0
192	addi r1, r1, 240
193	blr
194
195/* case FFI_TYPE_FLOAT */
196	lfs f1, 112+0(r1)
197	mtlr r0
198	addi r1, r1, 240
199	blr
200
201/* case FFI_TYPE_DOUBLE */
202	lfd f1, 112+0(r1)
203	mtlr r0
204	addi r1, r1, 240
205	blr
206
207/* case FFI_TYPE_LONGDOUBLE */
208	lfd f1, 112+0(r1)
209	mtlr r0
210	lfd f2, 112+8(r1)
211	b L..finish
212
213/* case FFI_TYPE_UINT8 */
214	lbz r3, 112+7(r1)
215	mtlr r0
216	addi r1, r1, 240
217	blr
218
219/* case FFI_TYPE_SINT8 */
220	lbz r3, 112+7(r1)
221	mtlr r0
222	extsb r3, r3
223	b L..finish
224
225/* case FFI_TYPE_UINT16 */
226	lhz r3, 112+6(r1)
227	mtlr r0
228L..finish:
229	addi r1, r1, 240
230	blr
231
232/* case FFI_TYPE_SINT16 */
233	lha r3, 112+6(r1)
234	mtlr r0
235	addi r1, r1, 240
236	blr
237
238/* case FFI_TYPE_UINT32 */
239	lwz r3, 112+4(r1)
240	mtlr r0
241	addi r1, r1, 240
242	blr
243
244/* case FFI_TYPE_SINT32 */
245	lwa r3, 112+4(r1)
246	mtlr r0
247	addi r1, r1, 240
248	blr
249
250/* case FFI_TYPE_UINT64 */
251	ld r3, 112+0(r1)
252	mtlr r0
253	addi r1, r1, 240
254	blr
255
256/* case FFI_TYPE_SINT64 */
257	ld r3, 112+0(r1)
258	mtlr r0
259	addi r1, r1, 240
260	blr
261
262/* case FFI_TYPE_STRUCT */
263	mtlr r0
264	addi r1, r1, 240
265	blr
266	nop
267
268/* case FFI_TYPE_POINTER */
269	ld r3, 112+0(r1)
270	mtlr r0
271	addi r1, r1, 240
272	blr
273
274#else /* ! __64BIT__ */
275
276	.long .ffi_closure_ASM, TOC[tc0], 0
277	.csect .text[PR]
278.ffi_closure_ASM:
279/* we want to build up an area for the parameters passed */
280/* in registers (both floating point and integer) */
281
282	/* we store gpr 3 to gpr 10 (aligned to 4)
283	in the parents outgoing area  */
284	stw   r3, 24+(0*4)(r1)
285	stw   r4, 24+(1*4)(r1)
286	stw   r5, 24+(2*4)(r1)
287	stw   r6, 24+(3*4)(r1)
288	mflr  r0
289
290	stw   r7, 24+(4*4)(r1)
291	stw   r8, 24+(5*4)(r1)
292	stw   r9, 24+(6*4)(r1)
293	stw   r10, 24+(7*4)(r1)
294	stw   r0, 8(r1)
295
296	/* 24 Bytes (Linkage Area) */
297	/* 32 Bytes (params) */
298	/* 16  Bytes (result) */
299	/* 104 Bytes (13*8 from FPR) */
300	/* 176 Bytes */
301
302	stwu  r1, -176(r1)	/* skip over caller save area
303				   keep stack aligned to 16  */
304
305	/* next save fpr 1 to fpr 13 (aligned to 8) */
306	stfd  f1, 72+(0*8)(r1)
307	stfd  f2, 72+(1*8)(r1)
308	stfd  f3, 72+(2*8)(r1)
309	stfd  f4, 72+(3*8)(r1)
310	stfd  f5, 72+(4*8)(r1)
311	stfd  f6, 72+(5*8)(r1)
312	stfd  f7, 72+(6*8)(r1)
313	stfd  f8, 72+(7*8)(r1)
314	stfd  f9, 72+(8*8)(r1)
315	stfd  f10, 72+(9*8)(r1)
316	stfd  f11, 72+(10*8)(r1)
317	stfd  f12, 72+(11*8)(r1)
318	stfd  f13, 72+(12*8)(r1)
319
320	/* set up registers for the routine that actually does the work */
321	/* get the context pointer from the trampoline */
322	mr r3, r11
323
324	/* now load up the pointer to the result storage */
325	addi r4, r1, 56
326
327	/* now load up the pointer to the saved gpr registers */
328	addi r5, r1, 200
329
330	/* now load up the pointer to the saved fpr registers */
331	addi r6, r1, 72
332
333	/* make the call */
334	bl .ffi_closure_helper_DARWIN
335	nop
336
337	/* now r3 contains the return type */
338	/* so use it to look up in a table */
339	/* so we know how to deal with each type */
340
341	/* look up the proper starting point in table  */
342	/* by using return type as offset */
343	lhz	r3, 6(r3)	/* load type from return type */
344	lwz	r4, LC..60(2)	/* get address of jump table */
345	slwi	r3, r3, 4	/* now multiply return type by 16 */
346	lwz	r0, 176+8(r1)	/* load return address */
347	add	r3, r3, r4	/* add contents of table to table address */
348	mtctr	r3
349	bctr			/* jump to it */
350
351/* Each fragment must be exactly 16 bytes long (4 instructions).
352   Align to 16 byte boundary for cache and dispatch efficiency.  */
353	.align 4
354
355L..60:
356/* case FFI_TYPE_VOID */
357	mtlr r0
358	addi r1, r1, 176
359	blr
360	nop
361
362/* case FFI_TYPE_INT */
363	lwz r3, 56+0(r1)
364	mtlr r0
365	addi r1, r1, 176
366	blr
367
368/* case FFI_TYPE_FLOAT */
369	lfs f1, 56+0(r1)
370	mtlr r0
371	addi r1, r1, 176
372	blr
373
374/* case FFI_TYPE_DOUBLE */
375	lfd f1, 56+0(r1)
376	mtlr r0
377	addi r1, r1, 176
378	blr
379
380/* case FFI_TYPE_LONGDOUBLE */
381	lfd f1, 56+0(r1)
382	mtlr r0
383	lfd f2, 56+8(r1)
384	b L..finish
385
386/* case FFI_TYPE_UINT8 */
387	lbz r3, 56+3(r1)
388	mtlr r0
389	addi r1, r1, 176
390	blr
391
392/* case FFI_TYPE_SINT8 */
393	lbz r3, 56+3(r1)
394	mtlr r0
395	extsb r3, r3
396	b L..finish
397
398/* case FFI_TYPE_UINT16 */
399	lhz r3, 56+2(r1)
400	mtlr r0
401	addi r1, r1, 176
402	blr
403
404/* case FFI_TYPE_SINT16 */
405	lha r3, 56+2(r1)
406	mtlr r0
407	addi r1, r1, 176
408	blr
409
410/* case FFI_TYPE_UINT32 */
411	lwz r3, 56+0(r1)
412	mtlr r0
413	addi r1, r1, 176
414	blr
415
416/* case FFI_TYPE_SINT32 */
417	lwz r3, 56+0(r1)
418	mtlr r0
419	addi r1, r1, 176
420	blr
421
422/* case FFI_TYPE_UINT64 */
423	lwz r3, 56+0(r1)
424	mtlr r0
425	lwz r4, 56+4(r1)
426	b L..finish
427
428/* case FFI_TYPE_SINT64 */
429	lwz r3, 56+0(r1)
430	mtlr r0
431	lwz r4, 56+4(r1)
432	b L..finish
433
434/* case FFI_TYPE_STRUCT */
435	mtlr r0
436	addi r1, r1, 176
437	blr
438	nop
439
440/* case FFI_TYPE_POINTER */
441	lwz r3, 56+0(r1)
442	mtlr r0
443L..finish:
444	addi r1, r1, 176
445	blr
446#endif
447/* END(ffi_closure_ASM) */
448