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