1 /* -----------------------------------------------------------------------
2 aix_closure.S - Copyright (c) 2002, 2003, 2009 Free Software Foundation, Inc.
3 based on darwin_closure.S
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:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
82 .extern .ffi_closure_helper_DARWIN
83 .extern .ffi_go_closure_helper_DARWIN
86 #define JUMPTARGET(name) name
97 .globl ffi_closure_ASM
98 .globl .ffi_closure_ASM
99 .csect ffi_closure_ASM[DS]
102 .llong .ffi_closure_ASM, TOC[tc0], 0
105 .function .ffi_closure_ASM,.ffi_closure_ASM,16,044,LFE..0-LFB..0
109 /* we want to build up an area for the parameters passed */
110 /* in registers (both floating point and integer) */
112 /* we store gpr 3 to gpr 10 (aligned to 4)
113 in the parents outgoing area */
123 std r10, 48+(7*8)(r1)
124 std r0, 16(r1) /* save the return address */
126 /* 48 Bytes (Linkage Area) */
127 /* 64 Bytes (params) */
128 /* 16 Bytes (result) */
129 /* 104 Bytes (13*8 from FPR) */
130 /* 8 Bytes (alignment) */
133 stdu r1, -240(r1) /* skip over caller save area
134 keep stack aligned to 16 */
137 /* next save fpr 1 to fpr 13 (aligned to 8) */
138 stfd f1, 128+(0*8)(r1)
139 stfd f2, 128+(1*8)(r1)
140 stfd f3, 128+(2*8)(r1)
141 stfd f4, 128+(3*8)(r1)
142 stfd f5, 128+(4*8)(r1)
143 stfd f6, 128+(5*8)(r1)
144 stfd f7, 128+(6*8)(r1)
145 stfd f8, 128+(7*8)(r1)
146 stfd f9, 128+(8*8)(r1)
147 stfd f10, 128+(9*8)(r1)
148 stfd f11, 128+(10*8)(r1)
149 stfd f12, 128+(11*8)(r1)
150 stfd f13, 128+(12*8)(r1)
152 /* set up registers for the routine that actually does the work */
153 /* get the context pointer from the trampoline */
156 /* now load up the pointer to the result storage */
159 /* now load up the pointer to the saved gpr registers */
162 /* now load up the pointer to the saved fpr registers */
166 bl .ffi_closure_helper_DARWIN
171 /* now r3 contains the return type */
172 /* so use it to look up in a table */
173 /* so we know how to deal with each type */
175 /* look up the proper starting point in table */
176 /* by using return type as offset */
177 lhz r3, 10(r3) /* load type from return type */
178 ld r4, LC..60(2) /* get address of jump table */
179 sldi r3, r3, 4 /* now multiply return type by 16 */
180 ld r0, 240+16(r1) /* load return address */
181 add r3, r3, r4 /* add contents of table to table address */
183 bctr /* jump to it */
185 /* Each fragment must be exactly 16 bytes long (4 instructions).
186 Align to 16 byte boundary for cache and dispatch efficiency. */
190 /* case FFI_TYPE_VOID */
196 /* case FFI_TYPE_INT */
202 /* case FFI_TYPE_FLOAT */
208 /* case FFI_TYPE_DOUBLE */
214 /* case FFI_TYPE_LONGDOUBLE */
220 /* case FFI_TYPE_UINT8 */
226 /* case FFI_TYPE_SINT8 */
232 /* case FFI_TYPE_UINT16 */
239 /* case FFI_TYPE_SINT16 */
245 /* case FFI_TYPE_UINT32 */
251 /* case FFI_TYPE_SINT32 */
257 /* case FFI_TYPE_UINT64 */
263 /* case FFI_TYPE_SINT64 */
269 /* case FFI_TYPE_STRUCT */
275 /* case FFI_TYPE_POINTER */
282 #else /* ! __64BIT__ */
284 .long .ffi_closure_ASM, TOC[tc0], 0
287 .function .ffi_closure_ASM,.ffi_closure_ASM,16,044,LFE..0-LFB..0
291 /* we want to build up an area for the parameters passed */
292 /* in registers (both floating point and integer) */
294 /* we store gpr 3 to gpr 10 (aligned to 4)
295 in the parents outgoing area */
305 stw r10, 24+(7*4)(r1)
308 /* 24 Bytes (Linkage Area) */
309 /* 32 Bytes (params) */
310 /* 16 Bytes (result) */
311 /* 104 Bytes (13*8 from FPR) */
314 stwu r1, -176(r1) /* skip over caller save area
315 keep stack aligned to 16 */
318 /* next save fpr 1 to fpr 13 (aligned to 8) */
319 stfd f1, 72+(0*8)(r1)
320 stfd f2, 72+(1*8)(r1)
321 stfd f3, 72+(2*8)(r1)
322 stfd f4, 72+(3*8)(r1)
323 stfd f5, 72+(4*8)(r1)
324 stfd f6, 72+(5*8)(r1)
325 stfd f7, 72+(6*8)(r1)
326 stfd f8, 72+(7*8)(r1)
327 stfd f9, 72+(8*8)(r1)
328 stfd f10, 72+(9*8)(r1)
329 stfd f11, 72+(10*8)(r1)
330 stfd f12, 72+(11*8)(r1)
331 stfd f13, 72+(12*8)(r1)
333 /* set up registers for the routine that actually does the work */
334 /* get the context pointer from the trampoline */
337 /* now load up the pointer to the result storage */
340 /* now load up the pointer to the saved gpr registers */
343 /* now load up the pointer to the saved fpr registers */
347 bl .ffi_closure_helper_DARWIN
352 /* now r3 contains the return type */
353 /* so use it to look up in a table */
354 /* so we know how to deal with each type */
356 /* look up the proper starting point in table */
357 /* by using return type as offset */
358 lhz r3, 6(r3) /* load type from return type */
359 lwz r4, LC..60(2) /* get address of jump table */
360 slwi r3, r3, 4 /* now multiply return type by 16 */
361 lwz r0, 176+8(r1) /* load return address */
362 add r3, r3, r4 /* add contents of table to table address */
364 bctr /* jump to it */
366 /* Each fragment must be exactly 16 bytes long (4 instructions).
367 Align to 16 byte boundary for cache and dispatch efficiency. */
371 /* case FFI_TYPE_VOID */
377 /* case FFI_TYPE_INT */
383 /* case FFI_TYPE_FLOAT */
389 /* case FFI_TYPE_DOUBLE */
395 /* case FFI_TYPE_LONGDOUBLE */
401 /* case FFI_TYPE_UINT8 */
407 /* case FFI_TYPE_SINT8 */
413 /* case FFI_TYPE_UINT16 */
419 /* case FFI_TYPE_SINT16 */
425 /* case FFI_TYPE_UINT32 */
431 /* case FFI_TYPE_SINT32 */
437 /* case FFI_TYPE_UINT64 */
443 /* case FFI_TYPE_SINT64 */
449 /* case FFI_TYPE_STRUCT */
455 /* case FFI_TYPE_POINTER */
464 /* END(ffi_closure_ASM) */
469 .globl ffi_go_closure_ASM
470 .globl .ffi_go_closure_ASM
471 .csect ffi_go_closure_ASM[DS]
474 .llong .ffi_go_closure_ASM, TOC[tc0], 0
477 .function .ffi_go_closure_ASM,.ffi_go_closure_ASM,16,044,LFE..1-LFB..1
481 /* we want to build up an area for the parameters passed */
482 /* in registers (both floating point and integer) */
484 /* we store gpr 3 to gpr 10 (aligned to 4)
485 in the parents outgoing area */
495 std r10, 48+(7*8)(r1)
496 std r0, 16(r1) /* save the return address */
498 /* 48 Bytes (Linkage Area) */
499 /* 64 Bytes (params) */
500 /* 16 Bytes (result) */
501 /* 104 Bytes (13*8 from FPR) */
502 /* 8 Bytes (alignment) */
505 stdu r1, -240(r1) /* skip over caller save area
506 keep stack aligned to 16 */
509 /* next save fpr 1 to fpr 13 (aligned to 8) */
510 stfd f1, 128+(0*8)(r1)
511 stfd f2, 128+(1*8)(r1)
512 stfd f3, 128+(2*8)(r1)
513 stfd f4, 128+(3*8)(r1)
514 stfd f5, 128+(4*8)(r1)
515 stfd f6, 128+(5*8)(r1)
516 stfd f7, 128+(6*8)(r1)
517 stfd f8, 128+(7*8)(r1)
518 stfd f9, 128+(8*8)(r1)
519 stfd f10, 128+(9*8)(r1)
520 stfd f11, 128+(10*8)(r1)
521 stfd f12, 128+(11*8)(r1)
522 stfd f13, 128+(12*8)(r1)
524 /* set up registers for the routine that actually does the work */
525 mr r3, r11 /* go closure */
527 /* now load up the pointer to the result storage */
530 /* now load up the pointer to the saved gpr registers */
533 /* now load up the pointer to the saved fpr registers */
537 bl .ffi_go_closure_helper_DARWIN
543 #else /* ! __64BIT__ */
545 .long .ffi_go_closure_ASM, TOC[tc0], 0
548 .function .ffi_go_closure_ASM,.ffi_go_closure_ASM,16,044,LFE..1-LFB..1
552 /* we want to build up an area for the parameters passed */
553 /* in registers (both floating point and integer) */
555 /* we store gpr 3 to gpr 10 (aligned to 4)
556 in the parents outgoing area */
566 stw r10, 24+(7*4)(r1)
569 /* 24 Bytes (Linkage Area) */
570 /* 32 Bytes (params) */
571 /* 16 Bytes (result) */
572 /* 104 Bytes (13*8 from FPR) */
575 stwu r1, -176(r1) /* skip over caller save area
576 keep stack aligned to 16 */
579 /* next save fpr 1 to fpr 13 (aligned to 8) */
580 stfd f1, 72+(0*8)(r1)
581 stfd f2, 72+(1*8)(r1)
582 stfd f3, 72+(2*8)(r1)
583 stfd f4, 72+(3*8)(r1)
584 stfd f5, 72+(4*8)(r1)
585 stfd f6, 72+(5*8)(r1)
586 stfd f7, 72+(6*8)(r1)
587 stfd f8, 72+(7*8)(r1)
588 stfd f9, 72+(8*8)(r1)
589 stfd f10, 72+(9*8)(r1)
590 stfd f11, 72+(10*8)(r1)
591 stfd f12, 72+(11*8)(r1)
592 stfd f13, 72+(12*8)(r1)
594 /* set up registers for the routine that actually does the work */
595 mr r3, 11 /* go closure */
597 /* now load up the pointer to the result storage */
600 /* now load up the pointer to the saved gpr registers */
603 /* now load up the pointer to the saved fpr registers */
607 bl .ffi_go_closure_helper_DARWIN
614 /* END(ffi_go_closure_ASM) */
616 /* EH frame stuff. */
618 #define LR_REGNO 0x41 /* Link Register (65), see rs6000.md */
621 #define LOG2_PTRSIZE 3
622 #define CFA_OFFSET 0xf0,0x01 /* LEB128 240 */
623 #define FDE_ENCODING 0x1c /* DW_EH_PE_pcrel|DW_EH_PE_sdata8 */
624 #define EH_DATA_ALIGN_FACT 0x78 /* LEB128 -8 */
627 #define LOG2_PTRSIZE 2
628 #define CFA_OFFSET 0xb0,0x01 /* LEB128 176 */
629 #define FDE_ENCODING 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4 */
630 #define EH_DATA_ALIGN_FACT 0x7c /* LEB128 -4 */
633 .csect _unwind.ro_[RO],4
635 .globl _GLOBAL__F_libffi_src_powerpc_aix_closure
636 _GLOBAL__F_libffi_src_powerpc_aix_closure:
638 .vbyte 4,LECIE..1-LSCIE..1 /* CIE Length */
640 .vbyte 4,0 /* CIE Identifier Tag */
641 .byte 0x3 /* CIE Version */
642 .byte "zR" /* CIE Augmentation */
644 .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
645 .byte EH_DATA_ALIGN_FACT /* leb128 -4/-8; CIE Data Alignment Factor */
646 .byte LR_REGNO /* CIE RA Column */
647 .byte 0x1 /* uleb128 0x1; Augmentation size */
648 .byte FDE_ENCODING /* FDE Encoding (pcrel|sdata4/8) */
649 .byte 0xc /* DW_CFA_def_cfa */
650 .byte 0x1 /* uleb128 0x1; Register r1 */
651 .byte 0 /* uleb128 0x0; Offset 0 */
655 .vbyte 4,LEFDE..1-LASFDE..1 /* FDE Length */
657 .vbyte 4,LASFDE..1-Lframe..1 /* FDE CIE offset */
658 .vbyte PTRSIZE,LFB..0-$ /* FDE initial location */
659 .vbyte PTRSIZE,LFE..0-LFB..0 /* FDE address range */
660 .byte 0 /* uleb128 0x0; Augmentation size */
661 .byte 0x4 /* DW_CFA_advance_loc4 */
662 .vbyte 4,LCFI..1-LCFI..0
663 .byte 0xe /* DW_CFA_def_cfa_offset */
664 .byte CFA_OFFSET /* uleb128 176/240 */
665 .byte 0x4 /* DW_CFA_advance_loc4 */
666 .vbyte 4,LCFI..0-LFB..0
667 .byte 0x11 /* DW_CFA_offset_extended_sf */
668 .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */
669 .byte 0x7e /* leb128 -2; Offset -2 (8/16) */
673 .vbyte 4,LEFDE..2-LASFDE..2 /* FDE Length */
675 .vbyte 4,LASFDE..2-Lframe..1 /* FDE CIE offset */
676 .vbyte PTRSIZE,LFB..1-$ /* FDE initial location */
677 .vbyte PTRSIZE,LFE..1-LFB..1 /* FDE address range */
678 .byte 0 /* uleb128 0x0; Augmentation size */
679 .byte 0x4 /* DW_CFA_advance_loc4 */
680 .vbyte 4,LCFI..3-LCFI..2
681 .byte 0xe /* DW_CFA_def_cfa_offset */
682 .byte CFA_OFFSET /* uleb128 176/240 */
683 .byte 0x4 /* DW_CFA_advance_loc4 */
684 .vbyte 4,LCFI..2-LFB..1
685 .byte 0x11 /* DW_CFA_offset_extended_sf */
686 .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */
687 .byte 0x7e /* leb128 -2; Offset -2 (8/16) */
690 .vbyte 4,0 /* End of FDEs */
693 .ref _GLOBAL__F_libffi_src_powerpc_aix_closure /* Prevents garbage collection by AIX linker */