326 lines
7.3 KiB
ArmAsm
326 lines
7.3 KiB
ArmAsm
/* -----------------------------------------------------------------------
|
|
sysv.S - Copyright (c) 2000 Software AG
|
|
Copyright (c) 2008 Red Hat, Inc.
|
|
|
|
S390 Foreign Function Interface
|
|
|
|
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 AUTHORS OR COPYRIGHT
|
|
HOLDERS 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>
|
|
|
|
.text
|
|
|
|
#ifndef __s390x__
|
|
|
|
# r2: frame
|
|
# r3: ret_type
|
|
# r4: ret_addr
|
|
# r5: fun
|
|
# r6: closure
|
|
|
|
# This assumes we are using gas.
|
|
.balign 8
|
|
.globl ffi_call_SYSV
|
|
FFI_HIDDEN(ffi_call_SYSV)
|
|
.type ffi_call_SYSV,%function
|
|
ffi_call_SYSV:
|
|
.cfi_startproc
|
|
st %r6,44(%r2) # Save registers
|
|
stm %r12,%r14,48(%r2)
|
|
lr %r13,%r2 # Install frame pointer
|
|
.cfi_rel_offset r6, 44
|
|
.cfi_rel_offset r12, 48
|
|
.cfi_rel_offset r13, 52
|
|
.cfi_rel_offset r14, 56
|
|
.cfi_def_cfa_register r13
|
|
st %r2,0(%r15) # Set up back chain
|
|
sla %r3,3 # ret_type *= 8
|
|
lr %r12,%r4 # Save ret_addr
|
|
lr %r1,%r5 # Save fun
|
|
lr %r0,%r6 # Install static chain
|
|
|
|
# Set return address, so that there is only one indirect jump.
|
|
#ifdef HAVE_AS_S390_ZARCH
|
|
larl %r14,.Ltable
|
|
ar %r14,%r3
|
|
#else
|
|
basr %r14,0
|
|
0: la %r14,.Ltable-0b(%r14,%r3)
|
|
#endif
|
|
|
|
lm %r2,%r6,8(%r13) # Load arguments
|
|
ld %f0,64(%r13)
|
|
ld %f2,72(%r13)
|
|
br %r1 # ... and call function
|
|
|
|
.balign 8
|
|
.Ltable:
|
|
# FFI390_RET_DOUBLE
|
|
std %f0,0(%r12)
|
|
j .Ldone
|
|
|
|
.balign 8
|
|
# FFI390_RET_FLOAT
|
|
ste %f0,0(%r12)
|
|
j .Ldone
|
|
|
|
.balign 8
|
|
# FFI390_RET_INT64
|
|
st %r3,4(%r12)
|
|
nop
|
|
# fallthru
|
|
|
|
.balign 8
|
|
# FFI390_RET_INT32
|
|
st %r2,0(%r12)
|
|
nop
|
|
# fallthru
|
|
|
|
.balign 8
|
|
# FFI390_RET_VOID
|
|
.Ldone:
|
|
l %r14,56(%r13)
|
|
l %r12,48(%r13)
|
|
l %r6,44(%r13)
|
|
l %r13,52(%r13)
|
|
.cfi_restore 14
|
|
.cfi_restore 13
|
|
.cfi_restore 12
|
|
.cfi_restore 6
|
|
.cfi_def_cfa r15, 96
|
|
br %r14
|
|
.cfi_endproc
|
|
.size ffi_call_SYSV,.-ffi_call_SYSV
|
|
|
|
|
|
.balign 8
|
|
.globl ffi_go_closure_SYSV
|
|
FFI_HIDDEN(ffi_go_closure_SYSV)
|
|
.type ffi_go_closure_SYSV,%function
|
|
ffi_go_closure_SYSV:
|
|
.cfi_startproc
|
|
stm %r2,%r6,8(%r15) # Save arguments
|
|
lr %r4,%r0 # Load closure -> user_data
|
|
l %r2,4(%r4) # ->cif
|
|
l %r3,8(%r4) # ->fun
|
|
j .Ldoclosure
|
|
.cfi_endproc
|
|
|
|
.balign 8
|
|
.globl ffi_closure_SYSV
|
|
FFI_HIDDEN(ffi_closure_SYSV)
|
|
.type ffi_closure_SYSV,%function
|
|
ffi_closure_SYSV:
|
|
.cfi_startproc
|
|
stm %r2,%r6,8(%r15) # Save arguments
|
|
lr %r4,%r0 # Closure
|
|
l %r2,16(%r4) # ->cif
|
|
l %r3,20(%r4) # ->fun
|
|
l %r4,24(%r4) # ->user_data
|
|
.Ldoclosure:
|
|
stm %r12,%r15,48(%r15) # Save registers
|
|
lr %r12,%r15
|
|
.cfi_def_cfa_register r12
|
|
.cfi_rel_offset r6, 24
|
|
.cfi_rel_offset r12, 48
|
|
.cfi_rel_offset r13, 52
|
|
.cfi_rel_offset r14, 56
|
|
.cfi_rel_offset r15, 60
|
|
#ifndef HAVE_AS_S390_ZARCH
|
|
basr %r13,0 # Set up base register
|
|
.Lcbase:
|
|
l %r1,.Lchelper-.Lcbase(%r13) # Get helper function
|
|
#endif
|
|
ahi %r15,-96-8 # Set up stack frame
|
|
st %r12,0(%r15) # Set up back chain
|
|
|
|
std %f0,64(%r12) # Save fp arguments
|
|
std %f2,72(%r12)
|
|
|
|
la %r5,96(%r12) # Overflow
|
|
st %r5,96(%r15)
|
|
la %r6,64(%r12) # FPRs
|
|
la %r5,8(%r12) # GPRs
|
|
#ifdef HAVE_AS_S390_ZARCH
|
|
brasl %r14,ffi_closure_helper_SYSV
|
|
#else
|
|
bas %r14,0(%r1,%r13) # Call helper
|
|
#endif
|
|
|
|
lr %r15,%r12
|
|
.cfi_def_cfa_register r15
|
|
lm %r12,%r14,48(%r12) # Restore saved registers
|
|
l %r6,24(%r15)
|
|
ld %f0,64(%r15) # Load return registers
|
|
lm %r2,%r3,8(%r15)
|
|
br %r14
|
|
.cfi_endproc
|
|
|
|
#ifndef HAVE_AS_S390_ZARCH
|
|
.align 4
|
|
.Lchelper:
|
|
.long ffi_closure_helper_SYSV-.Lcbase
|
|
#endif
|
|
|
|
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
|
|
|
#else
|
|
|
|
# r2: frame
|
|
# r3: ret_type
|
|
# r4: ret_addr
|
|
# r5: fun
|
|
# r6: closure
|
|
|
|
# This assumes we are using gas.
|
|
.balign 8
|
|
.globl ffi_call_SYSV
|
|
FFI_HIDDEN(ffi_call_SYSV)
|
|
.type ffi_call_SYSV,%function
|
|
ffi_call_SYSV:
|
|
.cfi_startproc
|
|
stg %r6,88(%r2) # Save registers
|
|
stmg %r12,%r14,96(%r2)
|
|
lgr %r13,%r2 # Install frame pointer
|
|
.cfi_rel_offset r6, 88
|
|
.cfi_rel_offset r12, 96
|
|
.cfi_rel_offset r13, 104
|
|
.cfi_rel_offset r14, 112
|
|
.cfi_def_cfa_register r13
|
|
stg %r2,0(%r15) # Set up back chain
|
|
larl %r14,.Ltable # Set up return address
|
|
slag %r3,%r3,3 # ret_type *= 8
|
|
lgr %r12,%r4 # Save ret_addr
|
|
lgr %r1,%r5 # Save fun
|
|
lgr %r0,%r6 # Install static chain
|
|
agr %r14,%r3
|
|
lmg %r2,%r6,16(%r13) # Load arguments
|
|
ld %f0,128(%r13)
|
|
ld %f2,136(%r13)
|
|
ld %f4,144(%r13)
|
|
ld %f6,152(%r13)
|
|
br %r1 # ... and call function
|
|
|
|
.balign 8
|
|
.Ltable:
|
|
# FFI390_RET_DOUBLE
|
|
std %f0,0(%r12)
|
|
j .Ldone
|
|
|
|
.balign 8
|
|
# FFI390_RET_DOUBLE
|
|
ste %f0,0(%r12)
|
|
j .Ldone
|
|
|
|
.balign 8
|
|
# FFI390_RET_INT64
|
|
stg %r2,0(%r12)
|
|
|
|
.balign 8
|
|
# FFI390_RET_INT32
|
|
# Never used, as we always store type ffi_arg.
|
|
# But the stg above is 6 bytes and we cannot
|
|
# jump around this case, so fall through.
|
|
nop
|
|
nop
|
|
|
|
.balign 8
|
|
# FFI390_RET_VOID
|
|
.Ldone:
|
|
lg %r14,112(%r13)
|
|
lg %r12,96(%r13)
|
|
lg %r6,88(%r13)
|
|
lg %r13,104(%r13)
|
|
.cfi_restore r14
|
|
.cfi_restore r13
|
|
.cfi_restore r12
|
|
.cfi_restore r6
|
|
.cfi_def_cfa r15, 160
|
|
br %r14
|
|
.cfi_endproc
|
|
.size ffi_call_SYSV,.-ffi_call_SYSV
|
|
|
|
|
|
.balign 8
|
|
.globl ffi_go_closure_SYSV
|
|
FFI_HIDDEN(ffi_go_closure_SYSV)
|
|
.type ffi_go_closure_SYSV,%function
|
|
ffi_go_closure_SYSV:
|
|
.cfi_startproc
|
|
stmg %r2,%r6,16(%r15) # Save arguments
|
|
lgr %r4,%r0 # Load closure -> user_data
|
|
lg %r2,8(%r4) # ->cif
|
|
lg %r3,16(%r4) # ->fun
|
|
j .Ldoclosure
|
|
.cfi_endproc
|
|
.size ffi_go_closure_SYSV,.-ffi_go_closure_SYSV
|
|
|
|
|
|
.balign 8
|
|
.globl ffi_closure_SYSV
|
|
FFI_HIDDEN(ffi_closure_SYSV)
|
|
.type ffi_closure_SYSV,%function
|
|
ffi_closure_SYSV:
|
|
.cfi_startproc
|
|
stmg %r2,%r6,16(%r15) # Save arguments
|
|
lgr %r4,%r0 # Load closure
|
|
lg %r2,32(%r4) # ->cif
|
|
lg %r3,40(%r4) # ->fun
|
|
lg %r4,48(%r4) # ->user_data
|
|
.Ldoclosure:
|
|
stmg %r13,%r15,104(%r15) # Save registers
|
|
lgr %r13,%r15
|
|
.cfi_def_cfa_register r13
|
|
.cfi_rel_offset r6, 48
|
|
.cfi_rel_offset r13, 104
|
|
.cfi_rel_offset r14, 112
|
|
.cfi_rel_offset r15, 120
|
|
aghi %r15,-160-16 # Set up stack frame
|
|
stg %r13,0(%r15) # Set up back chain
|
|
|
|
std %f0,128(%r13) # Save fp arguments
|
|
std %f2,136(%r13)
|
|
std %f4,144(%r13)
|
|
std %f6,152(%r13)
|
|
la %r5,160(%r13) # Overflow
|
|
stg %r5,160(%r15)
|
|
la %r6,128(%r13) # FPRs
|
|
la %r5,16(%r13) # GPRs
|
|
brasl %r14,ffi_closure_helper_SYSV # Call helper
|
|
|
|
lgr %r15,%r13
|
|
.cfi_def_cfa_register r15
|
|
lmg %r13,%r14,104(%r13) # Restore saved registers
|
|
lg %r6,48(%r15)
|
|
ld %f0,128(%r15) # Load return registers
|
|
lg %r2,16(%r15)
|
|
br %r14
|
|
.cfi_endproc
|
|
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
|
#endif /* !s390x */
|
|
|
|
#if defined __ELF__ && defined __linux__
|
|
.section .note.GNU-stack,"",@progbits
|
|
#endif
|