1/* -----------------------------------------------------------------------
2   aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc.
3   based on darwin.S by John Hornkvist
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_prep_args
83
84#define LIBFFI_ASM
85#include <fficonfig.h>
86#include <ffi.h>
87#define JUMPTARGET(name) name
88#define L(x) x
89	.file "aix.S"
90	.toc
91
92	/* void ffi_call_AIX(extended_cif *ecif, unsigned long bytes,
93	 *		     unsigned int flags, unsigned int *rvalue,
94	 *		     void (*fn)(),
95	 *		     void (*prep_args)(extended_cif*, unsigned *const));
96	 * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args
97	 */
98
99.csect .text[PR]
100	.align 2
101	.globl ffi_call_AIX
102	.globl .ffi_call_AIX
103.csect ffi_call_AIX[DS]
104ffi_call_AIX:
105#ifdef __64BIT__
106	.llong .ffi_call_AIX, TOC[tc0], 0
107	.csect .text[PR]
108.ffi_call_AIX:
109	/* Save registers we use.  */
110	mflr	r0
111
112	std	r28,-32(r1)
113	std	r29,-24(r1)
114	std	r30,-16(r1)
115	std	r31, -8(r1)
116
117	std	r0, 16(r1)
118	mr	r28, r1		/* our AP.  */
119	stdux	r1, r1, r4
120
121	/* Save arguments over call...  */
122	mr	r31, r5	/* flags, */
123	mr	r30, r6	/* rvalue, */
124	mr	r29, r7	/* function address.  */
125	std	r2, 40(r1)
126
127	/* Call ffi_prep_args.  */
128	mr	r4, r1
129	bl	.ffi_prep_args
130	nop
131
132	/* Now do the call.  */
133	ld	r0, 0(r29)
134	ld	r2, 8(r29)
135	ld	r11, 16(r29)
136	/* Set up cr1 with bits 4-7 of the flags.  */
137	mtcrf	0x40, r31
138	mtctr	r0
139	/* Load all those argument registers.  */
140	/* We have set up a nice stack frame, just load it into registers. */
141	ld	r3, 40+(1*8)(r1)
142	ld	r4, 40+(2*8)(r1)
143	ld	r5, 40+(3*8)(r1)
144	ld	r6, 40+(4*8)(r1)
145	nop
146	ld	r7, 40+(5*8)(r1)
147	ld	r8, 40+(6*8)(r1)
148	ld	r9, 40+(7*8)(r1)
149	ld	r10,40+(8*8)(r1)
150
151L1:
152	/* Load all the FP registers.  */
153	bf	6,L2 /* 2f + 0x18 */
154	lfd	f1,-32-(13*8)(r28)
155	lfd	f2,-32-(12*8)(r28)
156	lfd	f3,-32-(11*8)(r28)
157	lfd	f4,-32-(10*8)(r28)
158	nop
159	lfd	f5,-32-(9*8)(r28)
160	lfd	f6,-32-(8*8)(r28)
161	lfd	f7,-32-(7*8)(r28)
162	lfd	f8,-32-(6*8)(r28)
163	nop
164	lfd	f9,-32-(5*8)(r28)
165	lfd	f10,-32-(4*8)(r28)
166	lfd	f11,-32-(3*8)(r28)
167	lfd	f12,-32-(2*8)(r28)
168	nop
169	lfd	f13,-32-(1*8)(r28)
170
171L2:
172	/* Make the call.  */
173	bctrl
174	ld	r2, 40(r1)
175
176	/* Now, deal with the return value.  */
177	mtcrf	0x01, r31
178
179	bt	30, L(done_return_value)
180	bt	29, L(fp_return_value)
181	std	r3, 0(r30)
182
183	/* Fall through...  */
184
185L(done_return_value):
186	/* Restore the registers we used and return.  */
187	mr	r1, r28
188	ld	r0, 16(r28)
189	ld	r28, -32(r1)
190	mtlr	r0
191	ld	r29, -24(r1)
192	ld	r30, -16(r1)
193	ld	r31, -8(r1)
194	blr
195
196L(fp_return_value):
197	bf	28, L(float_return_value)
198	stfd	f1, 0(r30)
199	bf	31, L(done_return_value)
200	stfd	f2, 8(r30)
201	b	L(done_return_value)
202L(float_return_value):
203	stfs	f1, 0(r30)
204	b	L(done_return_value)
205
206#else /* ! __64BIT__ */
207
208	.long .ffi_call_AIX, TOC[tc0], 0
209	.csect .text[PR]
210.ffi_call_AIX:
211	/* Save registers we use.  */
212	mflr	r0
213
214	stw	r28,-16(r1)
215	stw	r29,-12(r1)
216	stw	r30, -8(r1)
217	stw	r31, -4(r1)
218
219	stw	r0, 8(r1)
220	mr	r28, r1		/* out AP.  */
221	stwux	r1, r1, r4
222
223	/* Save arguments over call...  */
224	mr	r31, r5	/* flags, */
225	mr	r30, r6	/* rvalue, */
226	mr	r29, r7	/* function address, */
227	stw	r2, 20(r1)
228
229	/* Call ffi_prep_args.  */
230	mr	r4, r1
231	bl	.ffi_prep_args
232	nop
233
234	/* Now do the call.  */
235	lwz	r0, 0(r29)
236	lwz	r2, 4(r29)
237	lwz	r11, 8(r29)
238	/* Set up cr1 with bits 4-7 of the flags.  */
239	mtcrf	0x40, r31
240	mtctr	r0
241	/* Load all those argument registers.  */
242	/* We have set up a nice stack frame, just load it into registers. */
243	lwz	r3, 20+(1*4)(r1)
244	lwz	r4, 20+(2*4)(r1)
245	lwz	r5, 20+(3*4)(r1)
246	lwz	r6, 20+(4*4)(r1)
247	nop
248	lwz	r7, 20+(5*4)(r1)
249	lwz	r8, 20+(6*4)(r1)
250	lwz	r9, 20+(7*4)(r1)
251	lwz	r10,20+(8*4)(r1)
252
253L1:
254	/* Load all the FP registers.  */
255	bf	6,L2 /* 2f + 0x18 */
256	lfd	f1,-16-(13*8)(r28)
257	lfd	f2,-16-(12*8)(r28)
258	lfd	f3,-16-(11*8)(r28)
259	lfd	f4,-16-(10*8)(r28)
260	nop
261	lfd	f5,-16-(9*8)(r28)
262	lfd	f6,-16-(8*8)(r28)
263	lfd	f7,-16-(7*8)(r28)
264	lfd	f8,-16-(6*8)(r28)
265	nop
266	lfd	f9,-16-(5*8)(r28)
267	lfd	f10,-16-(4*8)(r28)
268	lfd	f11,-16-(3*8)(r28)
269	lfd	f12,-16-(2*8)(r28)
270	nop
271	lfd	f13,-16-(1*8)(r28)
272
273L2:
274	/* Make the call.  */
275	bctrl
276	lwz	r2, 20(r1)
277
278	/* Now, deal with the return value.  */
279	mtcrf	0x01, r31
280
281	bt	30, L(done_return_value)
282	bt	29, L(fp_return_value)
283	stw	r3, 0(r30)
284	bf	28, L(done_return_value)
285	stw	r4, 4(r30)
286
287	/* Fall through...  */
288
289L(done_return_value):
290	/* Restore the registers we used and return.  */
291	mr	r1, r28
292	lwz	r0, 8(r28)
293	lwz	r28,-16(r1)
294	mtlr	r0
295	lwz	r29,-12(r1)
296	lwz	r30, -8(r1)
297	lwz	r31, -4(r1)
298	blr
299
300L(fp_return_value):
301	bf	28, L(float_return_value)
302	stfd	f1, 0(r30)
303	b	L(done_return_value)
304L(float_return_value):
305	stfs	f1, 0(r30)
306	b	L(done_return_value)
307#endif
308	.long 0
309	.byte 0,0,0,1,128,4,0,0
310/* END(ffi_call_AIX) */
311
312.csect .text[PR]
313	.align 2
314	.globl ffi_call_DARWIN
315	.globl .ffi_call_DARWIN
316.csect ffi_call_DARWIN[DS]
317ffi_call_DARWIN:
318#ifdef __64BIT__
319	.llong .ffi_call_DARWIN, TOC[tc0], 0
320#else
321	.long .ffi_call_DARWIN, TOC[tc0], 0
322#endif
323	.csect .text[PR]
324.ffi_call_DARWIN:
325	blr
326	.long 0
327	.byte 0,0,0,0,0,0,0,0
328/* END(ffi_call_DARWIN) */
329