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