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