OSDN Git Service

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