diff options
Diffstat (limited to 'Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S')
-rw-r--r-- | Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S new file mode 100644 index 0000000000..0a95771342 --- /dev/null +++ b/Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S @@ -0,0 +1,369 @@ +#if defined(__ppc__) || defined(__ppc64__) + +/* ----------------------------------------------------------------------- + darwin.S - Copyright (c) 2000 John Hornkvist + Copyright (c) 2004 Free Software Foundation, Inc. + + PowerPC Assembly glue. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM + +#include <fficonfig.h> +#include <ffi.h> +#include <ppc-darwin.h> +#include <architecture/ppc/mode_independent_asm.h> + +.text + .align 2 +.globl _ffi_prep_args + +.text + .align 2 +.globl _ffi_call_DARWIN + +.text + .align 2 +_ffi_call_DARWIN: +LFB0: + mr r12,r8 /* We only need r12 until the call, + so it doesn't have to be saved. */ + +LFB1: + /* Save the old stack pointer as AP. */ + mr r8,r1 + +LCFI0: +#if defined(__ppc64__) + /* Allocate the stack space we need. + r4 (size of input data) + 48 bytes (linkage area) + 40 bytes (saved registers) + 8 bytes (extra FPR) + r4 + 96 bytes total + */ + + addi r4,r4,-96 // Add our overhead. + li r0,-32 // Align to 32 bytes. + and r4,r4,r0 +#endif + stgux r1,r1,r4 // Grow the stack. + mflr r9 + + /* Save registers we use. */ +#if defined(__ppc64__) + std r27,-40(r8) +#endif + stg r28,MODE_CHOICE(-16,-32)(r8) + stg r29,MODE_CHOICE(-12,-24)(r8) + stg r30,MODE_CHOICE(-8,-16)(r8) + stg r31,MODE_CHOICE(-4,-8)(r8) + stg r9,SF_RETURN(r8) /* return address */ +#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ + stg r2,MODE_CHOICE(20,40)(r1) +#endif + +LCFI1: +#if defined(__ppc64__) + mr r27,r3 // our extended_cif +#endif + /* Save arguments over call. */ + mr r31,r5 /* flags, */ + mr r30,r6 /* rvalue, */ + mr r29,r7 /* function address, */ + mr r28,r8 /* our AP. */ + +LCFI2: + /* Call ffi_prep_args. */ + mr r4,r1 + li r9,0 + mtctr r12 /* r12 holds address of _ffi_prep_args. */ + bctrl +#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ + lg r2,MODE_CHOICE(20,40)(r1) +#endif + + /* Now do the call. + Set up cr1 with bits 4-7 of the flags. */ + mtcrf 0x40,r31 + + /* Load all those argument registers. + We have set up a nice stack frame, just load it into registers. */ + lg r3,SF_ARG1(r1) + lg r4,SF_ARG2(r1) + lg r5,SF_ARG3(r1) + lg r6,SF_ARG4(r1) + nop + lg r7,SF_ARG5(r1) + lg r8,SF_ARG6(r1) + lg r9,SF_ARG7(r1) + lg r10,SF_ARG8(r1) + + /* Load all the FP registers. */ + bf 6,L2 /* No floats to load. */ +#if defined(__ppc64__) + lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) + lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) + lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) + lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) + nop + lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) + lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) + lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) + lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) + nop + lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) + lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) + lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) + lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) + nop + lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) + lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) +#elif defined(__ppc__) + lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) + lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) + lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) + lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) + nop + lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) + lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) + lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) + lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) + nop + lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) + lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) + lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) + lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) + nop + lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) +#else +#error undefined architecture +#endif + +L2: + mr r12,r29 // Put the target address in r12 as specified. + mtctr r12 // Get the address to call into CTR. + nop + nop + bctrl // Make the call. + + // Deal with the return value. +#if defined(__ppc64__) + mtcrf 0x3,r31 // flags in cr6 and cr7 + bt 27,L(st_return_value) +#elif defined(__ppc__) + mtcrf 0x1,r31 // flags in cr7 +#else +#error undefined architecture +#endif + + bt 30,L(done_return_value) + bt 29,L(fp_return_value) + stg r3,0(r30) +#if defined(__ppc__) + bf 28,L(done_return_value) // Store the second long if necessary. + stg r4,4(r30) +#endif + // Fall through + +L(done_return_value): + lg r1,0(r1) // Restore stack pointer. + // Restore the registers we used. + lg r9,SF_RETURN(r1) // return address + lg r31,MODE_CHOICE(-4,-8)(r1) + mtlr r9 + lg r30,MODE_CHOICE(-8,-16)(r1) + lg r29,MODE_CHOICE(-12,-24)(r1) + lg r28,MODE_CHOICE(-16,-32)(r1) +#if defined(__ppc64__) + ld r27,-40(r1) +#endif + blr + +#if defined(__ppc64__) +L(st_return_value): + // Grow the stack enough to fit the registers. Leave room for 8 args + // to trample the 1st 8 slots in param area. + stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 + + // Store GPRs + std r3,SF_ARG9(r1) + std r4,SF_ARG10(r1) + std r5,SF_ARG11(r1) + std r6,SF_ARG12(r1) + nop + std r7,SF_ARG13(r1) + std r8,SF_ARG14(r1) + std r9,SF_ARG15(r1) + std r10,SF_ARG16(r1) + + // Store FPRs + nop + bf 26,L(call_struct_to_ram_form) + stfd f1,SF_ARG17(r1) + stfd f2,SF_ARG18(r1) + stfd f3,SF_ARG19(r1) + stfd f4,SF_ARG20(r1) + nop + stfd f5,SF_ARG21(r1) + stfd f6,SF_ARG22(r1) + stfd f7,SF_ARG23(r1) + stfd f8,SF_ARG24(r1) + nop + stfd f9,SF_ARG25(r1) + stfd f10,SF_ARG26(r1) + stfd f11,SF_ARG27(r1) + stfd f12,SF_ARG28(r1) + nop + stfd f13,SF_ARG29(r1) + +L(call_struct_to_ram_form): + ld r3,0(r27) // extended_cif->cif* + ld r3,16(r3) // ffi_cif->rtype* + addi r4,r1,SF_ARG9 // stored GPRs + addi r6,r1,SF_ARG17 // stored FPRs + li r5,0 // GPR size ptr (NULL) + li r7,0 // FPR size ptr (NULL) + li r8,0 // FPR count ptr (NULL) + li r10,0 // struct offset (NULL) + mr r9,r30 // return area + bl Lffi64_struct_to_ram_form$stub + lg r1,0(r1) // Restore stack pointer. + b L(done_return_value) +#endif + +L(fp_return_value): + /* Do we have long double to store? */ + bf 31,L(fd_return_value) + stfd f1,0(r30) + stfd f2,8(r30) + b L(done_return_value) + +L(fd_return_value): + /* Do we have double to store? */ + bf 28,L(float_return_value) + stfd f1,0(r30) + b L(done_return_value) + +L(float_return_value): + /* We only have a float to store. */ + stfs f1,0(r30) + b L(done_return_value) + +LFE1: +/* END(_ffi_call_DARWIN) */ + +/* Provide a null definition of _ffi_call_AIX. */ +.text + .align 2 +.globl _ffi_call_AIX +.text + .align 2 +_ffi_call_AIX: + blr +/* END(_ffi_call_AIX) */ + +.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms +EH_frame1: + .set L$set$0,LECIE1-LSCIE1 + .long L$set$0 ; Length of Common Information Entry +LSCIE1: + .long 0x0 ; CIE Identifier Tag + .byte 0x1 ; CIE Version + .ascii "zR\0" ; CIE Augmentation + .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor + .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor + .byte 0x41 ; CIE RA Column + .byte 0x1 ; uleb128 0x1; Augmentation size + .byte 0x90 ; FDE Encoding (indirect pcrel) + .byte 0xc ; DW_CFA_def_cfa + .byte 0x1 ; uleb128 0x1 + .byte 0x0 ; uleb128 0x0 + .align LOG2_GPR_BYTES +LECIE1: +.globl _ffi_call_DARWIN.eh +_ffi_call_DARWIN.eh: +LSFDE1: + .set L$set$1,LEFDE1-LASFDE1 + .long L$set$1 ; FDE Length + +LASFDE1: + .long LASFDE1-EH_frame1 ; FDE CIE offset + .g_long LLFB0$non_lazy_ptr-. ; FDE initial location + .set L$set$3,LFE1-LFB0 + .g_long L$set$3 ; FDE address range + .byte 0x0 ; uleb128 0x0; Augmentation size + .byte 0x4 ; DW_CFA_advance_loc4 + .set L$set$4,LCFI0-LFB1 + .long L$set$4 + .byte 0xd ; DW_CFA_def_cfa_register + .byte 0x08 ; uleb128 0x08 + .byte 0x4 ; DW_CFA_advance_loc4 + .set L$set$5,LCFI1-LCFI0 + .long L$set$5 + .byte 0x11 ; DW_CFA_offset_extended_sf + .byte 0x41 ; uleb128 0x41 + .byte 0x7e ; sleb128 -2 + .byte 0x9f ; DW_CFA_offset, column 0x1f + .byte 0x1 ; uleb128 0x1 + .byte 0x9e ; DW_CFA_offset, column 0x1e + .byte 0x2 ; uleb128 0x2 + .byte 0x9d ; DW_CFA_offset, column 0x1d + .byte 0x3 ; uleb128 0x3 + .byte 0x9c ; DW_CFA_offset, column 0x1c + .byte 0x4 ; uleb128 0x4 + .byte 0x4 ; DW_CFA_advance_loc4 + .set L$set$6,LCFI2-LCFI1 + .long L$set$6 + .byte 0xd ; DW_CFA_def_cfa_register + .byte 0x1c ; uleb128 0x1c + .align LOG2_GPR_BYTES +LEFDE1: +.data + .align LOG2_GPR_BYTES +LLFB0$non_lazy_ptr: + .g_long LFB0 + +#if defined(__ppc64__) +.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align LOG2_GPR_BYTES + +Lffi64_struct_to_ram_form$stub: + .indirect_symbol _ffi64_struct_to_ram_form + mflr r0 + bcl 20,31,LO$ffi64_struct_to_ram_form + +LO$ffi64_struct_to_ram_form: + mflr r11 + addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) + mtlr r0 + lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) + mtctr r12 + bctr + +.lazy_symbol_pointer +L_ffi64_struct_to_ram_form$lazy_ptr: + .indirect_symbol _ffi64_struct_to_ram_form + .g_long dyld_stub_binding_helper + +#endif // __ppc64__ +#endif // __ppc__ || __ppc64__ |