308 lines
7.2 KiB
ArmAsm
308 lines
7.2 KiB
ArmAsm
/* -----------------------------------------------------------------------
|
|
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
|
|
|
|
SPARC 64-bit 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>
|
|
|
|
#ifdef SPARC64
|
|
/* Only compile this in for 64bit builds, because otherwise the object file
|
|
will have inproper architecture due to used instructions. */
|
|
|
|
#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
|
|
#define STACK_BIAS 2047
|
|
#define ARGS (128) /* Offset of register area in frame */
|
|
|
|
.text
|
|
.align 8
|
|
.globl ffi_call_v9
|
|
.globl _ffi_call_v9
|
|
|
|
ffi_call_v9:
|
|
_ffi_call_v9:
|
|
.LLFB1:
|
|
save %sp, -STACKFRAME, %sp
|
|
.LLCFI0:
|
|
|
|
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
|
|
add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
|
|
! frame to set up
|
|
|
|
mov %l0, %o0 ! call routine to set up frame
|
|
call %i0
|
|
mov %i1, %o1 ! (delay)
|
|
brz,pt %o0, 1f
|
|
ldx [%l0+ARGS], %o0 ! call foreign function
|
|
|
|
ldd [%l0+ARGS], %f0
|
|
ldd [%l0+ARGS+8], %f2
|
|
ldd [%l0+ARGS+16], %f4
|
|
ldd [%l0+ARGS+24], %f6
|
|
ldd [%l0+ARGS+32], %f8
|
|
ldd [%l0+ARGS+40], %f10
|
|
ldd [%l0+ARGS+48], %f12
|
|
ldd [%l0+ARGS+56], %f14
|
|
ldd [%l0+ARGS+64], %f16
|
|
ldd [%l0+ARGS+72], %f18
|
|
ldd [%l0+ARGS+80], %f20
|
|
ldd [%l0+ARGS+88], %f22
|
|
ldd [%l0+ARGS+96], %f24
|
|
ldd [%l0+ARGS+104], %f26
|
|
ldd [%l0+ARGS+112], %f28
|
|
ldd [%l0+ARGS+120], %f30
|
|
|
|
1: ldx [%l0+ARGS+8], %o1
|
|
ldx [%l0+ARGS+16], %o2
|
|
ldx [%l0+ARGS+24], %o3
|
|
ldx [%l0+ARGS+32], %o4
|
|
ldx [%l0+ARGS+40], %o5
|
|
call %i5
|
|
sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
|
|
|
|
! If the return value pointer is NULL, assume no return value.
|
|
brz,pn %i4, done
|
|
nop
|
|
|
|
cmp %i3, FFI_TYPE_INT
|
|
be,a,pt %icc, done
|
|
stx %o0, [%i4+0] ! (delay)
|
|
|
|
cmp %i3, FFI_TYPE_FLOAT
|
|
be,a,pn %icc, done
|
|
st %f0, [%i4+0] ! (delay)
|
|
|
|
cmp %i3, FFI_TYPE_DOUBLE
|
|
be,a,pn %icc, done
|
|
std %f0, [%i4+0] ! (delay)
|
|
|
|
cmp %i3, FFI_TYPE_STRUCT
|
|
be,pn %icc, dostruct
|
|
|
|
cmp %i3, FFI_TYPE_LONGDOUBLE
|
|
bne,pt %icc, done
|
|
nop
|
|
std %f0, [%i4+0]
|
|
std %f2, [%i4+8]
|
|
|
|
done: ret
|
|
restore
|
|
|
|
dostruct:
|
|
/* This will not work correctly for unions. */
|
|
stx %o0, [%i4+0]
|
|
stx %o1, [%i4+8]
|
|
stx %o2, [%i4+16]
|
|
stx %o3, [%i4+24]
|
|
std %f0, [%i4+32]
|
|
std %f2, [%i4+40]
|
|
std %f4, [%i4+48]
|
|
std %f6, [%i4+56]
|
|
ret
|
|
restore
|
|
.LLFE1:
|
|
|
|
.ffi_call_v9_end:
|
|
.size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
|
|
|
|
|
|
#undef STACKFRAME
|
|
#define STACKFRAME 336 /* 16*8 register window +
|
|
6*8 args backing store +
|
|
20*8 locals */
|
|
#define FP %fp+STACK_BIAS
|
|
|
|
/* ffi_closure_v9(...)
|
|
|
|
Receives the closure argument in %g1. */
|
|
|
|
.text
|
|
.align 8
|
|
.globl ffi_closure_v9
|
|
|
|
ffi_closure_v9:
|
|
.LLFB2:
|
|
save %sp, -STACKFRAME, %sp
|
|
.LLCFI1:
|
|
|
|
! Store all of the potential argument registers in va_list format.
|
|
stx %i0, [FP+128+0]
|
|
stx %i1, [FP+128+8]
|
|
stx %i2, [FP+128+16]
|
|
stx %i3, [FP+128+24]
|
|
stx %i4, [FP+128+32]
|
|
stx %i5, [FP+128+40]
|
|
|
|
! Store possible floating point argument registers too.
|
|
std %f0, [FP-128]
|
|
std %f2, [FP-120]
|
|
std %f4, [FP-112]
|
|
std %f6, [FP-104]
|
|
std %f8, [FP-96]
|
|
std %f10, [FP-88]
|
|
std %f12, [FP-80]
|
|
std %f14, [FP-72]
|
|
std %f16, [FP-64]
|
|
std %f18, [FP-56]
|
|
std %f20, [FP-48]
|
|
std %f22, [FP-40]
|
|
std %f24, [FP-32]
|
|
std %f26, [FP-24]
|
|
std %f28, [FP-16]
|
|
std %f30, [FP-8]
|
|
|
|
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
|
mov %g1, %o0
|
|
add %fp, STACK_BIAS-160, %o1
|
|
add %fp, STACK_BIAS+128, %o2
|
|
call ffi_closure_sparc_inner_v9
|
|
add %fp, STACK_BIAS-128, %o3
|
|
|
|
! Load up the return value in the proper type.
|
|
! See ffi_prep_cif_machdep for the list of cases.
|
|
cmp %o0, FFI_TYPE_VOID
|
|
be,pn %icc, done1
|
|
|
|
cmp %o0, FFI_TYPE_INT
|
|
be,pn %icc, integer
|
|
|
|
cmp %o0, FFI_TYPE_FLOAT
|
|
be,a,pn %icc, done1
|
|
ld [FP-160], %f0
|
|
|
|
cmp %o0, FFI_TYPE_DOUBLE
|
|
be,a,pn %icc, done1
|
|
ldd [FP-160], %f0
|
|
|
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
cmp %o0, FFI_TYPE_LONGDOUBLE
|
|
be,a,pn %icc, longdouble1
|
|
ldd [FP-160], %f0
|
|
#endif
|
|
|
|
! FFI_TYPE_STRUCT
|
|
ldx [FP-152], %i1
|
|
ldx [FP-144], %i2
|
|
ldx [FP-136], %i3
|
|
ldd [FP-160], %f0
|
|
ldd [FP-152], %f2
|
|
ldd [FP-144], %f4
|
|
ldd [FP-136], %f6
|
|
|
|
integer:
|
|
ldx [FP-160], %i0
|
|
|
|
done1:
|
|
ret
|
|
restore
|
|
|
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
longdouble1:
|
|
ldd [FP-152], %f2
|
|
ret
|
|
restore
|
|
#endif
|
|
.LLFE2:
|
|
|
|
.ffi_closure_v9_end:
|
|
.size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
|
|
|
|
#ifdef HAVE_RO_EH_FRAME
|
|
.section ".eh_frame",#alloc
|
|
#else
|
|
.section ".eh_frame",#alloc,#write
|
|
#endif
|
|
.LLframe1:
|
|
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
|
|
.LLSCIE1:
|
|
.uaword 0x0 ! CIE Identifier Tag
|
|
.byte 0x1 ! CIE Version
|
|
.ascii "zR\0" ! CIE Augmentation
|
|
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
|
|
.byte 0x78 ! sleb128 -8; CIE Data Alignment Factor
|
|
.byte 0xf ! CIE RA Column
|
|
.byte 0x1 ! uleb128 0x1; Augmentation size
|
|
#ifdef HAVE_AS_SPARC_UA_PCREL
|
|
.byte 0x1b ! FDE Encoding (pcrel sdata4)
|
|
#else
|
|
.byte 0x50 ! FDE Encoding (aligned absolute)
|
|
#endif
|
|
.byte 0xc ! DW_CFA_def_cfa
|
|
.byte 0xe ! uleb128 0xe
|
|
.byte 0xff,0xf ! uleb128 0x7ff
|
|
.align 8
|
|
.LLECIE1:
|
|
.LLSFDE1:
|
|
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
|
|
.LLASFDE1:
|
|
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
|
|
#ifdef HAVE_AS_SPARC_UA_PCREL
|
|
.uaword %r_disp32(.LLFB1)
|
|
.uaword .LLFE1-.LLFB1 ! FDE address range
|
|
#else
|
|
.align 8
|
|
.xword .LLFB1
|
|
.uaxword .LLFE1-.LLFB1 ! FDE address range
|
|
#endif
|
|
.byte 0x0 ! uleb128 0x0; Augmentation size
|
|
.byte 0x4 ! DW_CFA_advance_loc4
|
|
.uaword .LLCFI0-.LLFB1
|
|
.byte 0xd ! DW_CFA_def_cfa_register
|
|
.byte 0x1e ! uleb128 0x1e
|
|
.byte 0x2d ! DW_CFA_GNU_window_save
|
|
.byte 0x9 ! DW_CFA_register
|
|
.byte 0xf ! uleb128 0xf
|
|
.byte 0x1f ! uleb128 0x1f
|
|
.align 8
|
|
.LLEFDE1:
|
|
.LLSFDE2:
|
|
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
|
|
.LLASFDE2:
|
|
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
|
|
#ifdef HAVE_AS_SPARC_UA_PCREL
|
|
.uaword %r_disp32(.LLFB2)
|
|
.uaword .LLFE2-.LLFB2 ! FDE address range
|
|
#else
|
|
.align 8
|
|
.xword .LLFB2
|
|
.uaxword .LLFE2-.LLFB2 ! FDE address range
|
|
#endif
|
|
.byte 0x0 ! uleb128 0x0; Augmentation size
|
|
.byte 0x4 ! DW_CFA_advance_loc4
|
|
.uaword .LLCFI1-.LLFB2
|
|
.byte 0xd ! DW_CFA_def_cfa_register
|
|
.byte 0x1e ! uleb128 0x1e
|
|
.byte 0x2d ! DW_CFA_GNU_window_save
|
|
.byte 0x9 ! DW_CFA_register
|
|
.byte 0xf ! uleb128 0xf
|
|
.byte 0x1f ! uleb128 0x1f
|
|
.align 8
|
|
.LLEFDE2:
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
.section .note.GNU-stack,"",@progbits
|
|
#endif
|