]> git.ipfire.org Git - thirdparty/gcc.git/blame - libffi/src/powerpc/aix_closure.S
aix_closure.S: Reorganize 64-bit code to match linux64_closure.S.
[thirdparty/gcc.git] / libffi / src / powerpc / aix_closure.S
CommitLineData
073ae293 1/* -----------------------------------------------------------------------
5751cf6f 2 aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc.
16070e45 3 based on darwin_closure.S
3e86b595 4
073ae293
AT
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
87LC..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]
073ae293 97ffi_closure_ASM:
5751cf6f
DE
98#ifdef __64BIT__
99 .llong .ffi_closure_ASM, TOC[tc0], 0
100 .csect .text[PR]
101.ffi_closure_ASM:
2f2d7386
DE
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 */
5751cf6f 118
5751cf6f
DE
119
120 /* 48 Bytes (Linkage Area) */
121 /* 64 Bytes (params) */
6d518d3b 122 /* 16 Bytes (result) */
5751cf6f 123 /* 104 Bytes (13*8 from FPR) */
6d518d3b
DE
124 /* 8 Bytes (alignment) */
125 /* 240 Bytes */
5751cf6f 126
2f2d7386 127 stdu r1, -240(r1) /* skip over caller save area
5751cf6f
DE
128 keep stack aligned to 16 */
129
5751cf6f 130 /* next save fpr 1 to fpr 13 (aligned to 8) */
6d518d3b
DE
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)
5751cf6f
DE
144
145 /* set up registers for the routine that actually does the work */
146 /* get the context pointer from the trampoline */
2f2d7386 147 mr r3, r11
5751cf6f
DE
148
149 /* now load up the pointer to the result storage */
2f2d7386 150 addi r4, r1, 112
5751cf6f
DE
151
152 /* now load up the pointer to the saved gpr registers */
2f2d7386 153 addi r5, r1, 288
5751cf6f
DE
154
155 /* now load up the pointer to the saved fpr registers */
2f2d7386 156 addi r6, r1, 128
5751cf6f
DE
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 */
2f2d7386
DE
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 */
5751cf6f
DE
171 add r3,r3,r4 /* add contents of table to table address */
172 mtctr r3
173 bctr /* jump to it */
174
2f2d7386
DE
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
5751cf6f 179L..60:
2f2d7386
DE
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
225L..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
5751cf6f
DE
269 blr
270
271#else /* ! __64BIT__ */
272
073ae293
AT
273 .long .ffi_closure_ASM, TOC[tc0], 0
274 .csect .text[PR]
275.ffi_closure_ASM:
276
277 mflr r0 /* extract return address */
278 stw r0, 8(r1) /* save the return address */
3e86b595 279
073ae293
AT
280 /* 24 Bytes (Linkage Area) */
281 /* 32 Bytes (params) */
69b182fd 282 /* 104 Bytes (13*8 from FPR) */
5751cf6f
DE
283 /* 16 Bytes (result) */
284 /* 176 Bytes */
3e86b595 285
79e43f89
AT
286 stwu r1,-176(r1) /* skip over caller save area
287 keep stack aligned to 16 */
073ae293
AT
288
289/* we want to build up an area for the parameters passed */
290/* in registers (both floating point and integer) */
3e86b595 291
79e43f89
AT
292 /* we store gpr 3 to gpr 10 (aligned to 4)
293 in the parents outgoing area */
294 stw r3, 200(r1)
295 stw r4, 204(r1)
16070e45 296 stw r5, 208(r1)
79e43f89
AT
297 stw r6, 212(r1)
298 stw r7, 216(r1)
16070e45 299 stw r8, 220(r1)
79e43f89
AT
300 stw r9, 224(r1)
301 stw r10, 228(r1)
073ae293
AT
302
303 /* next save fpr 1 to fpr 13 (aligned to 8) */
304 stfd f1, 56(r1)
305 stfd f2, 64(r1)
306 stfd f3, 72(r1)
307 stfd f4, 80(r1)
308 stfd f5, 88(r1)
309 stfd f6, 96(r1)
310 stfd f7, 104(r1)
311 stfd f8, 112(r1)
16070e45
AT
312 stfd f9, 120(r1)
313 stfd f10, 128(r1)
314 stfd f11, 136(r1)
315 stfd f12, 144(r1)
316 stfd f13, 152(r1)
073ae293
AT
317
318 /* set up registers for the routine that actually does the work */
319 /* get the context pointer from the trampoline */
320 mr r3,r11
69b182fd 321
073ae293
AT
322 /* now load up the pointer to the result storage */
323 addi r4,r1,160
69b182fd 324
073ae293 325 /* now load up the pointer to the saved gpr registers */
79e43f89 326 addi r5,r1,200
073ae293
AT
327
328 /* now load up the pointer to the saved fpr registers */
329 addi r6,r1,56
330
073ae293
AT
331 /* make the call */
332 bl .ffi_closure_helper_DARWIN
333 nop
334
335 /* now r3 contains the return type */
336 /* so use it to look up in a table */
337 /* so we know how to deal with each type */
338
339 /* look up the proper starting point in table */
340 /* by using return type as offset */
341 addi r5,r1,160 /* get pointer to results area */
342 lwz r4,LC..60(2) /* get address of jump table */
343 slwi r3,r3,2 /* now multiply return type by 4 */
344 lwzx r3,r4,r3 /* get the contents of that table value */
345 add r3,r3,r4 /* add contents of table to table address */
346 mtctr r3
347 bctr /* jump to it */
348
349L..60:
350 .long L..44-L..60 /* FFI_TYPE_VOID */
351 .long L..50-L..60 /* FFI_TYPE_INT */
352 .long L..47-L..60 /* FFI_TYPE_FLOAT */
353 .long L..46-L..60 /* FFI_TYPE_DOUBLE */
5751cf6f 354 .long L..45-L..60 /* FFI_TYPE_LONGDOUBLE */
073ae293
AT
355 .long L..56-L..60 /* FFI_TYPE_UINT8 */
356 .long L..55-L..60 /* FFI_TYPE_SINT8 */
357 .long L..58-L..60 /* FFI_TYPE_UINT16 */
358 .long L..57-L..60 /* FFI_TYPE_SINT16 */
359 .long L..50-L..60 /* FFI_TYPE_UINT32 */
360 .long L..50-L..60 /* FFI_TYPE_SINT32 */
361 .long L..48-L..60 /* FFI_TYPE_UINT64 */
362 .long L..48-L..60 /* FFI_TYPE_SINT64 */
363 .long L..44-L..60 /* FFI_TYPE_STRUCT */
364 .long L..50-L..60 /* FFI_TYPE_POINTER */
365
366
5751cf6f
DE
367/* case long double */
368L..45:
369 lfd f1,0(r5)
370 lfd f2,8(r5)
371 b L..44
372
073ae293 373/* case double */
16070e45 374L..46:
073ae293
AT
375 lfd f1,0(r5)
376 b L..44
377
378/* case float */
379L..47:
380 lfs f1,0(r5)
381 b L..44
3e86b595 382
073ae293
AT
383/* case long long */
384L..48:
385 lwz r3,0(r5)
386 lwz r4,4(r5)
387 b L..44
3e86b595 388
073ae293
AT
389/* case default / int32 / pointer */
390L..50:
391 lwz r3,0(r5)
392 b L..44
3e86b595 393
5751cf6f 394/* case signed int8 */
073ae293 395L..55:
5751cf6f
DE
396 lbz r3,3(r5)
397 extsb r3,r3
073ae293
AT
398 b L..44
399
5751cf6f 400/* case unsigned int8 */
073ae293 401L..56:
5751cf6f 402 lbz r3,3(r5)
073ae293
AT
403 b L..44
404
405/* case signed int16 */
406L..57:
5751cf6f 407 lha r3,2(r5)
073ae293
AT
408 b L..44
409
410/* case unsigned int16 */
16070e45 411L..58:
5751cf6f 412 lhz r3,2(r5)
073ae293
AT
413
414/* case void / done */
415L..44:
79e43f89 416 addi r1,r1,176 /* restore stack pointer */
073ae293
AT
417 lwz r0,8(r1) /* get return address */
418 mtlr r0 /* reset link register */
419 blr
5751cf6f 420#endif
073ae293 421/* END(ffi_closure_ASM) */