diff options
Diffstat (limited to 'ext/ffi_c/libffi/src/powerpc/linux64_closure.S')
-rw-r--r-- | ext/ffi_c/libffi/src/powerpc/linux64_closure.S | 298 |
1 files changed, 227 insertions, 71 deletions
diff --git a/ext/ffi_c/libffi/src/powerpc/linux64_closure.S b/ext/ffi_c/libffi/src/powerpc/linux64_closure.S index f7aa2c9..97421a4 100644 --- a/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +++ b/ext/ffi_c/libffi/src/powerpc/linux64_closure.S @@ -30,68 +30,131 @@ .file "linux64_closure.S" -#ifdef __powerpc64__ +#ifdef POWERPC64 FFI_HIDDEN (ffi_closure_LINUX64) - FFI_HIDDEN (.ffi_closure_LINUX64) - .globl ffi_closure_LINUX64, .ffi_closure_LINUX64 + .globl ffi_closure_LINUX64 +# if _CALL_ELF == 2 + .text +ffi_closure_LINUX64: + addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha + addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l + .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64 +# else .section ".opd","aw" .align 3 ffi_closure_LINUX64: +# ifdef _CALL_LINUX + .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0 + .type ffi_closure_LINUX64,@function + .text +.L.ffi_closure_LINUX64: +# else + FFI_HIDDEN (.ffi_closure_LINUX64) + .globl .ffi_closure_LINUX64 .quad .ffi_closure_LINUX64,.TOC.@tocbase,0 .size ffi_closure_LINUX64,24 .type .ffi_closure_LINUX64,@function .text .ffi_closure_LINUX64: +# endif +# endif + +# if _CALL_ELF == 2 +# 32 byte special reg save area + 64 byte parm save area +# + 64 byte retval area + 13*8 fpr save area + round to 16 +# define STACKFRAME 272 +# define PARMSAVE 32 +# define RETVAL PARMSAVE+64 +# else +# 48 bytes special reg save area + 64 bytes parm save area +# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 +# define STACKFRAME 240 +# define PARMSAVE 48 +# define RETVAL PARMSAVE+64 +# endif + .LFB1: - # save general regs into parm save area - std %r3, 48(%r1) - std %r4, 56(%r1) - std %r5, 64(%r1) - std %r6, 72(%r1) +# if _CALL_ELF == 2 + ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif mflr %r0 + lwz %r12, 28(%r12) # cif->flags + mtcrf 0x40, %r12 + addi %r12, %r1, PARMSAVE + bt 7, .Lparmsave + # Our caller has not allocated a parameter save area. + # We need to allocate one here and use it to pass gprs to + # ffi_closure_helper_LINUX64. + addi %r12, %r1, -STACKFRAME+PARMSAVE +.Lparmsave: + std %r0, 16(%r1) + # Save general regs into parm save area + std %r3, 0(%r12) + std %r4, 8(%r12) + std %r5, 16(%r12) + std %r6, 24(%r12) + std %r7, 32(%r12) + std %r8, 40(%r12) + std %r9, 48(%r12) + std %r10, 56(%r12) + + # load up the pointer to the parm save area + mr %r5, %r12 +# else + # copy r2 to r11 and load TOC into r2 + mr %r11, %r2 + ld %r2, 16(%r11) + + mflr %r0 + # Save general regs into parm save area + # This is the parameter save area set up by our caller. + std %r3, PARMSAVE+0(%r1) + std %r4, PARMSAVE+8(%r1) + std %r5, PARMSAVE+16(%r1) + std %r6, PARMSAVE+24(%r1) + std %r7, PARMSAVE+32(%r1) + std %r8, PARMSAVE+40(%r1) + std %r9, PARMSAVE+48(%r1) + std %r10, PARMSAVE+56(%r1) - std %r7, 80(%r1) - std %r8, 88(%r1) - std %r9, 96(%r1) - std %r10, 104(%r1) std %r0, 16(%r1) - # mandatory 48 bytes special reg save area + 64 bytes parm save area - # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 - stdu %r1, -240(%r1) -.LCFI0: + # load up the pointer to the parm save area + addi %r5, %r1, PARMSAVE +# endif # next save fpr 1 to fpr 13 - stfd %f1, 128+(0*8)(%r1) - stfd %f2, 128+(1*8)(%r1) - stfd %f3, 128+(2*8)(%r1) - stfd %f4, 128+(3*8)(%r1) - stfd %f5, 128+(4*8)(%r1) - stfd %f6, 128+(5*8)(%r1) - stfd %f7, 128+(6*8)(%r1) - stfd %f8, 128+(7*8)(%r1) - stfd %f9, 128+(8*8)(%r1) - stfd %f10, 128+(9*8)(%r1) - stfd %f11, 128+(10*8)(%r1) - stfd %f12, 128+(11*8)(%r1) - stfd %f13, 128+(12*8)(%r1) - - # set up registers for the routine that actually does the work - # get the context pointer from the trampoline - mr %r3, %r11 + stfd %f1, -104+(0*8)(%r1) + stfd %f2, -104+(1*8)(%r1) + stfd %f3, -104+(2*8)(%r1) + stfd %f4, -104+(3*8)(%r1) + stfd %f5, -104+(4*8)(%r1) + stfd %f6, -104+(5*8)(%r1) + stfd %f7, -104+(6*8)(%r1) + stfd %f8, -104+(7*8)(%r1) + stfd %f9, -104+(8*8)(%r1) + stfd %f10, -104+(9*8)(%r1) + stfd %f11, -104+(10*8)(%r1) + stfd %f12, -104+(11*8)(%r1) + stfd %f13, -104+(12*8)(%r1) + + # load up the pointer to the saved fpr registers */ + addi %r6, %r1, -104 - # now load up the pointer to the result storage - addi %r4, %r1, 112 + # load up the pointer to the result storage + addi %r4, %r1, -STACKFRAME+RETVAL - # now load up the pointer to the parameter save area - # in the previous frame - addi %r5, %r1, 240 + 48 + stdu %r1, -STACKFRAME(%r1) +.LCFI0: - # now load up the pointer to the saved fpr registers */ - addi %r6, %r1, 128 + # get the context pointer from the trampoline + mr %r3, %r11 # make the call +# if defined _CALL_LINUX || _CALL_ELF == 2 + bl ffi_closure_helper_LINUX64 +# else bl .ffi_closure_helper_LINUX64 +# endif .Lret: # now r3 contains the return type @@ -100,10 +163,12 @@ ffi_closure_LINUX64: # look up the proper starting point in table # by using return type as offset + ld %r0, STACKFRAME+16(%r1) + cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + bge .Lsmall mflr %r4 # move address of .Lret to r4 sldi %r3, %r3, 4 # now multiply return type by 16 addi %r4, %r4, .Lret_type0 - .Lret - ld %r0, 240+16(%r1) add %r3, %r3, %r4 # add contents of table to table address mtctr %r3 bctr # jump to it @@ -116,85 +181,175 @@ ffi_closure_LINUX64: .Lret_type0: # case FFI_TYPE_VOID mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr nop # case FFI_TYPE_INT - lwa %r3, 112+4(%r1) +# ifdef __LITTLE_ENDIAN__ + lwa %r3, RETVAL+0(%r1) +# else + lwa %r3, RETVAL+4(%r1) +# endif mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_FLOAT - lfs %f1, 112+0(%r1) + lfs %f1, RETVAL+0(%r1) mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_DOUBLE - lfd %f1, 112+0(%r1) + lfd %f1, RETVAL+0(%r1) mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_LONGDOUBLE - lfd %f1, 112+0(%r1) + lfd %f1, RETVAL+0(%r1) mtlr %r0 - lfd %f2, 112+8(%r1) + lfd %f2, RETVAL+8(%r1) b .Lfinish # case FFI_TYPE_UINT8 - lbz %r3, 112+7(%r1) +# ifdef __LITTLE_ENDIAN__ + lbz %r3, RETVAL+0(%r1) +# else + lbz %r3, RETVAL+7(%r1) +# endif mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_SINT8 - lbz %r3, 112+7(%r1) +# ifdef __LITTLE_ENDIAN__ + lbz %r3, RETVAL+0(%r1) +# else + lbz %r3, RETVAL+7(%r1) +# endif extsb %r3,%r3 mtlr %r0 b .Lfinish # case FFI_TYPE_UINT16 - lhz %r3, 112+6(%r1) +# ifdef __LITTLE_ENDIAN__ + lhz %r3, RETVAL+0(%r1) +# else + lhz %r3, RETVAL+6(%r1) +# endif mtlr %r0 .Lfinish: - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_SINT16 - lha %r3, 112+6(%r1) +# ifdef __LITTLE_ENDIAN__ + lha %r3, RETVAL+0(%r1) +# else + lha %r3, RETVAL+6(%r1) +# endif mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_UINT32 - lwz %r3, 112+4(%r1) +# ifdef __LITTLE_ENDIAN__ + lwz %r3, RETVAL+0(%r1) +# else + lwz %r3, RETVAL+4(%r1) +# endif mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_SINT32 - lwa %r3, 112+4(%r1) +# ifdef __LITTLE_ENDIAN__ + lwa %r3, RETVAL+0(%r1) +# else + lwa %r3, RETVAL+4(%r1) +# endif mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_UINT64 - ld %r3, 112+0(%r1) + ld %r3, RETVAL+0(%r1) mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_SINT64 - ld %r3, 112+0(%r1) + ld %r3, RETVAL+0(%r1) mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr # case FFI_TYPE_STRUCT mtlr %r0 - addi %r1, %r1, 240 + addi %r1, %r1, STACKFRAME blr nop # case FFI_TYPE_POINTER - ld %r3, 112+0(%r1) + ld %r3, RETVAL+0(%r1) + mtlr %r0 + addi %r1, %r1, STACKFRAME + blr +# case FFI_V2_TYPE_FLOAT_HOMOG + lfs %f1, RETVAL+0(%r1) + lfs %f2, RETVAL+4(%r1) + lfs %f3, RETVAL+8(%r1) + b .Lmorefloat +# case FFI_V2_TYPE_DOUBLE_HOMOG + lfd %f1, RETVAL+0(%r1) + lfd %f2, RETVAL+8(%r1) + lfd %f3, RETVAL+16(%r1) + lfd %f4, RETVAL+24(%r1) + mtlr %r0 + lfd %f5, RETVAL+32(%r1) + lfd %f6, RETVAL+40(%r1) + lfd %f7, RETVAL+48(%r1) + lfd %f8, RETVAL+56(%r1) + addi %r1, %r1, STACKFRAME + blr +.Lmorefloat: + lfs %f4, RETVAL+12(%r1) + mtlr %r0 + lfs %f5, RETVAL+16(%r1) + lfs %f6, RETVAL+20(%r1) + lfs %f7, RETVAL+24(%r1) + lfs %f8, RETVAL+28(%r1) + addi %r1, %r1, STACKFRAME + blr +.Lsmall: +# ifdef __LITTLE_ENDIAN__ + ld %r3,RETVAL+0(%r1) + mtlr %r0 + ld %r4,RETVAL+8(%r1) + addi %r1, %r1, STACKFRAME + blr +# else + # A struct smaller than a dword is returned in the low bits of r3 + # ie. right justified. Larger structs are passed left justified + # in r3 and r4. The return value area on the stack will have + # the structs as they are usually stored in memory. + cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes? + neg %r5, %r3 + ld %r3,RETVAL+0(%r1) + blt .Lsmalldown mtlr %r0 - addi %r1, %r1, 240 + ld %r4,RETVAL+8(%r1) + addi %r1, %r1, STACKFRAME blr -# esac +.Lsmalldown: + addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7 + mtlr %r0 + sldi %r5, %r5, 3 + addi %r1, %r1, STACKFRAME + srd %r3, %r3, %r5 + blr +# endif + .LFE1: .long 0 .byte 0,12,0,1,128,0,0,0 +# if _CALL_ELF == 2 + .size ffi_closure_LINUX64,.-ffi_closure_LINUX64 +# else +# ifdef _CALL_LINUX + .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64 +# else .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 +# endif +# endif .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: @@ -223,14 +378,15 @@ ffi_closure_LINUX64: .byte 0x2 # DW_CFA_advance_loc1 .byte .LCFI0-.LFB1 .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 240 + .uleb128 STACKFRAME .byte 0x11 # DW_CFA_offset_extended_sf .uleb128 0x41 .sleb128 -2 .align 3 .LEFDE1: + #endif -#if defined __ELF__ && defined __linux__ +#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 .section .note.GNU-stack,"",@progbits #endif |