gcc/libffi/src/powerpc/linux64_closure.S

211 lines
4.2 KiB
ArmAsm

.file "linux64_closure.S"
#ifdef __powerpc64__
.hidden ffi_closure_LINUX64, .ffi_closure_LINUX64
.globl ffi_closure_LINUX64, .ffi_closure_LINUX64
.section ".opd","aw"
.align 3
ffi_closure_LINUX64:
.quad .ffi_closure_LINUX64,.TOC.@tocbase,0
.size ffi_closure_LINUX64,24
.type .ffi_closure_LINUX64,@function
.text
.ffi_closure_LINUX64:
.LFB1:
# save general regs into parm save area
std %r3, 48(%r1)
std %r4, 56(%r1)
std %r5, 64(%r1)
std %r6, 72(%r1)
mflr %r0
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
# + 8 bytes retval area + 13*8 bytes fpr save area
stdu %r1, -224(%r1)
.LCFI0:
# next save fpr 1 to fpr 13
stfd %f1, 120+(0*8)(%r1)
stfd %f2, 120+(1*8)(%r1)
stfd %f3, 120+(2*8)(%r1)
stfd %f4, 120+(3*8)(%r1)
stfd %f5, 120+(4*8)(%r1)
stfd %f6, 120+(5*8)(%r1)
stfd %f7, 120+(6*8)(%r1)
stfd %f8, 120+(7*8)(%r1)
stfd %f9, 120+(8*8)(%r1)
stfd %f10, 120+(9*8)(%r1)
stfd %f11, 120+(10*8)(%r1)
stfd %f12, 120+(11*8)(%r1)
stfd %f13, 120+(12*8)(%r1)
# set up registers for the routine that actually does the work
# get the context pointer from the trampoline
mr %r3, %r11
# now load up the pointer to the result storage
addi %r4, %r1, 112
# now load up the pointer to the parameter save area
# in the previous frame
addi %r5, %r1, 224 + 48
# now load up the pointer to the saved fpr registers */
addi %r6, %r1, 120
# make the call
bl .ffi_closure_helper_LINUX64
# now r3 contains the return type
# so use it to look up in a table
# so we know how to deal with each type
# look up the proper starting point in table
# by using return type as offset
addi %r5, %r1, 112 # get pointer to results area
bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
mflr %r4 # move to r4
sldi %r3, %r3, 4 # now multiply return type by 16
add %r3, %r3, %r4 # add contents of table to table address
mtctr %r3
bctr # jump to it
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
# first.
.align 4
nop
nop
nop
.Lget_ret_type0_addr:
blrl
.Lret_type0:
# case FFI_TYPE_VOID
b .Lfinish
nop
nop
nop
# case FFI_TYPE_INT
lwa %r3, 4(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_FLOAT
lfs %f1, 4(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_DOUBLE
lfd %f1, 0(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_LONGDOUBLE
lfd %f1, 0(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT8
lbz %r3, 7(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT8
lbz %r3, 7(%r5)
extsb %r3,%r3
b .Lfinish
nop
# case FFI_TYPE_UINT16
lhz %r3, 6(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT16
lha %r3, 6(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT32
lwz %r3, 4(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT32
lwa %r3, 4(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT64
ld %r3, 0(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT64
ld %r3, 0(%r5)
b .Lfinish
nop
nop
# case FFI_TYPE_STRUCT
b .Lfinish
nop
nop
nop
# case FFI_TYPE_POINTER
ld %r3, 0(%r5)
b .Lfinish
nop
nop
# esac
.Lfinish:
ld %r0, 224+16(%r1)
mtlr %r0
addi %r1, %r1, 224
blr
.LFE1:
.long 0
.byte 0,12,0,1,128,0,0,0
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
.section .eh_frame,"aw",@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0x41 # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x14 # FDE Encoding (pcrel udata8)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1
.uleb128 0x0
.align 3
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.8byte .LFB1-. # FDE initial location
.8byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x2 # DW_CFA_advance_loc1
.byte .LCFI0-.LFB1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 224
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -2
.align 3
.LEFDE1:
#endif