441 lines
9.7 KiB
ArmAsm
441 lines
9.7 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>
|
|
#include "internal.h"
|
|
|
|
#ifdef SPARC64
|
|
|
|
#define C2(X, Y) X ## Y
|
|
#define C1(X, Y) C2(X, Y)
|
|
|
|
#ifdef __USER_LABEL_PREFIX__
|
|
# define C(Y) C1(__USER_LABEL_PREFIX__, Y)
|
|
#else
|
|
# define C(Y) Y
|
|
#endif
|
|
#define L(Y) C1(.L, Y)
|
|
|
|
#if defined(__sun__) && defined(__svr4__)
|
|
# define E(INDEX) .align 16
|
|
#else
|
|
# define E(INDEX) .align 16; .org 2b + INDEX * 16
|
|
#endif
|
|
|
|
#define STACK_BIAS 2047
|
|
|
|
.text
|
|
.align 8
|
|
.globl C(ffi_call_v9)
|
|
.type C(ffi_call_v9),#function
|
|
FFI_HIDDEN(C(ffi_call_v9))
|
|
|
|
C(ffi_call_v9):
|
|
.LUW0:
|
|
save %sp, %o4, %sp
|
|
.LUW1:
|
|
mov %i0, %o0 ! copy cif
|
|
add %sp, STACK_BIAS+128+48, %o1 ! load args area
|
|
mov %i2, %o2 ! copy rvalue
|
|
call C(ffi_prep_args_v9)
|
|
mov %i3, %o3 ! copy avalue
|
|
|
|
andcc %o0, SPARC_FLAG_FP_ARGS, %g0 ! need fp regs?
|
|
add %sp, 48, %sp ! deallocate prep frame
|
|
be,pt %xcc, 1f
|
|
mov %o0, %l0 ! save flags
|
|
|
|
ldd [%sp+STACK_BIAS+128], %f0 ! load all fp arg regs
|
|
ldd [%sp+STACK_BIAS+128+8], %f2
|
|
ldd [%sp+STACK_BIAS+128+16], %f4
|
|
ldd [%sp+STACK_BIAS+128+24], %f6
|
|
ldd [%sp+STACK_BIAS+128+32], %f8
|
|
ldd [%sp+STACK_BIAS+128+40], %f10
|
|
ldd [%sp+STACK_BIAS+128+48], %f12
|
|
ldd [%sp+STACK_BIAS+128+56], %f14
|
|
ldd [%sp+STACK_BIAS+128+64], %f16
|
|
ldd [%sp+STACK_BIAS+128+72], %f18
|
|
ldd [%sp+STACK_BIAS+128+80], %f20
|
|
ldd [%sp+STACK_BIAS+128+88], %f22
|
|
ldd [%sp+STACK_BIAS+128+96], %f24
|
|
ldd [%sp+STACK_BIAS+128+104], %f26
|
|
ldd [%sp+STACK_BIAS+128+112], %f28
|
|
ldd [%sp+STACK_BIAS+128+120], %f30
|
|
|
|
1: ldx [%sp+STACK_BIAS+128], %o0 ! load all int arg regs
|
|
ldx [%sp+STACK_BIAS+128+8], %o1
|
|
ldx [%sp+STACK_BIAS+128+16], %o2
|
|
ldx [%sp+STACK_BIAS+128+24], %o3
|
|
ldx [%sp+STACK_BIAS+128+32], %o4
|
|
ldx [%sp+STACK_BIAS+128+40], %o5
|
|
call %i1
|
|
mov %i5, %g5 ! load static chain
|
|
|
|
0: call 1f ! load pc in %o7
|
|
and %l0, SPARC_FLAG_RET_MASK, %l1
|
|
1: sll %l1, 4, %l1
|
|
add %o7, %l1, %o7 ! o7 = 0b + ret_type*16
|
|
jmp %o7+(2f-0b)
|
|
nop
|
|
|
|
.align 16
|
|
2:
|
|
E(SPARC_RET_VOID)
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_STRUCT)
|
|
add %sp, STACK_BIAS-64+128+48, %l2
|
|
sub %sp, 64, %sp
|
|
b 8f
|
|
stx %o0, [%l2]
|
|
E(SPARC_RET_UINT8)
|
|
and %o0, 0xff, %i0
|
|
return %i7+8
|
|
stx %o0, [%o2]
|
|
E(SPARC_RET_SINT8)
|
|
sll %o0, 24, %o0
|
|
sra %o0, 24, %i0
|
|
return %i7+8
|
|
stx %o0, [%o2]
|
|
E(SPARC_RET_UINT16)
|
|
sll %o0, 16, %o0
|
|
srl %o0, 16, %i0
|
|
return %i7+8
|
|
stx %o0, [%o2]
|
|
E(SPARC_RET_SINT16)
|
|
sll %o0, 16, %o0
|
|
sra %o0, 16, %i0
|
|
return %i7+8
|
|
stx %o0, [%o2]
|
|
E(SPARC_RET_UINT32)
|
|
srl %o0, 0, %i0
|
|
return %i7+8
|
|
stx %o0, [%o2]
|
|
E(SP_V9_RET_SINT32)
|
|
sra %o0, 0, %i0
|
|
return %i7+8
|
|
stx %o0, [%o2]
|
|
E(SPARC_RET_INT64)
|
|
stx %o0, [%i2]
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_INT128)
|
|
stx %o0, [%i2]
|
|
stx %o1, [%i2+8]
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_F_8)
|
|
st %f7, [%i2+7*4]
|
|
nop
|
|
st %f6, [%i2+6*4]
|
|
nop
|
|
E(SPARC_RET_F_6)
|
|
st %f5, [%i2+5*4]
|
|
nop
|
|
st %f4, [%i2+4*4]
|
|
nop
|
|
E(SPARC_RET_F_4)
|
|
std %f2, [%i2+2*4]
|
|
return %i7+8
|
|
std %f0, [%o2]
|
|
E(SPARC_RET_F_2)
|
|
return %i7+8
|
|
std %f0, [%o2]
|
|
E(SP_V9_RET_F_3)
|
|
st %f2, [%i2+2*4]
|
|
nop
|
|
st %f1, [%i2+1*4]
|
|
nop
|
|
E(SPARC_RET_F_1)
|
|
return %i7+8
|
|
st %f0, [%o2]
|
|
|
|
! Finish the SPARC_RET_STRUCT sequence.
|
|
.align 8
|
|
8: stx %o1, [%l2+8]
|
|
stx %o2, [%l2+16]
|
|
stx %o3, [%l2+24]
|
|
std %f0, [%l2+32]
|
|
std %f2, [%l2+40]
|
|
std %f4, [%l2+48]
|
|
std %f6, [%l2+56]
|
|
|
|
! Copy the structure into place.
|
|
srl %l0, SPARC_SIZEMASK_SHIFT, %o0 ! load size_mask
|
|
mov %i2, %o1 ! load dst
|
|
mov %l2, %o2 ! load src_gp
|
|
call C(ffi_struct_float_copy)
|
|
add %l2, 32, %o3 ! load src_fp
|
|
|
|
return %i7+8
|
|
nop
|
|
|
|
.LUW2:
|
|
.size C(ffi_call_v9), . - C(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. */
|
|
|
|
.align 8
|
|
.globl C(ffi_go_closure_v9)
|
|
.type C(ffi_go_closure_v9),#function
|
|
FFI_HIDDEN(C(ffi_go_closure_v9))
|
|
|
|
C(ffi_go_closure_v9):
|
|
.LUW3:
|
|
save %sp, -STACKFRAME, %sp
|
|
.LUW4:
|
|
ldx [%g5+8], %o0
|
|
ldx [%g5+16], %o1
|
|
b 0f
|
|
mov %g5, %o2
|
|
|
|
.LUW5:
|
|
.size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9)
|
|
|
|
.align 8
|
|
.globl C(ffi_closure_v9)
|
|
.type C(ffi_closure_v9),#function
|
|
FFI_HIDDEN(C(ffi_closure_v9))
|
|
|
|
C(ffi_closure_v9):
|
|
.LUW6:
|
|
save %sp, -STACKFRAME, %sp
|
|
.LUW7:
|
|
ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0
|
|
ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1
|
|
ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2
|
|
0:
|
|
! 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.
|
|
add %fp, STACK_BIAS-160, %o3
|
|
add %fp, STACK_BIAS+128, %o4
|
|
call C(ffi_closure_sparc_inner_v9)
|
|
add %fp, STACK_BIAS-128, %o5
|
|
|
|
0: call 1f ! load pc in %o7
|
|
and %o0, SPARC_FLAG_RET_MASK, %o0
|
|
1: sll %o0, 4, %o0 ! o2 = i2 * 16
|
|
add %o7, %o0, %o7 ! o7 = 0b + i2*16
|
|
jmp %o7+(2f-0b)
|
|
nop
|
|
|
|
! Note that we cannot load the data in the delay slot of
|
|
! the return insn because the data is in the stack frame
|
|
! that is deallocated by the return.
|
|
.align 16
|
|
2:
|
|
E(SPARC_RET_VOID)
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_STRUCT)
|
|
ldx [FP-160], %i0
|
|
ldd [FP-160], %f0
|
|
b 8f
|
|
ldx [FP-152], %i1
|
|
E(SPARC_RET_UINT8)
|
|
ldub [FP-160+7], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_SINT8)
|
|
ldsb [FP-160+7], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_UINT16)
|
|
lduh [FP-160+6], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_SINT16)
|
|
ldsh [FP-160+6], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_UINT32)
|
|
lduw [FP-160+4], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SP_V9_RET_SINT32)
|
|
ldsw [FP-160+4], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_INT64)
|
|
ldx [FP-160], %i0
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_INT128)
|
|
ldx [FP-160], %i0
|
|
ldx [FP-160+8], %i1
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_F_8)
|
|
ld [FP-160+7*4], %f7
|
|
nop
|
|
ld [FP-160+6*4], %f6
|
|
nop
|
|
E(SPARC_RET_F_6)
|
|
ld [FP-160+5*4], %f5
|
|
nop
|
|
ld [FP-160+4*4], %f4
|
|
nop
|
|
E(SPARC_RET_F_4)
|
|
ldd [FP-160], %f0
|
|
ldd [FP-160+8], %f2
|
|
return %i7+8
|
|
nop
|
|
E(SPARC_RET_F_2)
|
|
ldd [FP-160], %f0
|
|
return %i7+8
|
|
nop
|
|
E(SP_V9_RET_F_3)
|
|
ld [FP-160+2*4], %f2
|
|
nop
|
|
ld [FP-160+1*4], %f1
|
|
nop
|
|
E(SPARC_RET_F_1)
|
|
ld [FP-160], %f0
|
|
return %i7+8
|
|
nop
|
|
|
|
! Finish the SPARC_RET_STRUCT sequence.
|
|
.align 8
|
|
8: ldd [FP-152], %f2
|
|
ldx [FP-144], %i2
|
|
ldd [FP-144], %f4
|
|
ldx [FP-136], %i3
|
|
ldd [FP-136], %f6
|
|
return %i7+8
|
|
nop
|
|
|
|
.LUW8:
|
|
.size C(ffi_closure_v9), . - C(ffi_closure_v9)
|
|
|
|
#ifdef HAVE_RO_EH_FRAME
|
|
.section ".eh_frame",#alloc
|
|
#else
|
|
.section ".eh_frame",#alloc,#write
|
|
#endif
|
|
|
|
#ifdef HAVE_AS_SPARC_UA_PCREL
|
|
# define FDE_RANGE(B, E) .long %r_disp32(B), E - B
|
|
#else
|
|
# define FDE_RANGE(B, E) .align 8; .xword B, E - B
|
|
#endif
|
|
|
|
.align 8
|
|
.LCIE:
|
|
.long .LECIE - .LSCIE ! CIE Length
|
|
.LSCIE:
|
|
.long 0 ! CIE Identifier Tag
|
|
.byte 1 ! CIE Version
|
|
.ascii "zR\0" ! CIE Augmentation
|
|
.byte 4 ! CIE Code Alignment Factor
|
|
.byte 0x78 ! CIE Data Alignment Factor
|
|
.byte 15 ! CIE RA Column
|
|
.byte 1 ! Augmentation size
|
|
#ifdef HAVE_AS_SPARC_UA_PCREL
|
|
.byte 0x1b ! FDE Encoding (pcrel sdata4)
|
|
#else
|
|
.byte 0x50 ! FDE Encoding (aligned absolute)
|
|
#endif
|
|
.byte 0xc, 14, 0xff, 0xf ! DW_CFA_def_cfa, %o6, offset 0x7ff
|
|
.align 8
|
|
.LECIE:
|
|
|
|
.long .LEFDE1 - .LSFDE1 ! FDE Length
|
|
.LSFDE1:
|
|
.long .LSFDE1 - .LCIE ! FDE CIE offset
|
|
FDE_RANGE(.LUW0, .LUW2)
|
|
.byte 0 ! Augmentation size
|
|
.byte 0x40+1 ! DW_CFA_advance_loc 4
|
|
.byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
|
|
.byte 0x2d ! DW_CFA_GNU_window_save
|
|
.byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
|
|
.align 8
|
|
.LEFDE1:
|
|
|
|
.long .LEFDE2 - .LSFDE2 ! FDE Length
|
|
.LSFDE2:
|
|
.long .LSFDE2 - .LCIE ! FDE CIE offset
|
|
FDE_RANGE(.LUW3, .LUW5)
|
|
.byte 0 ! Augmentation size
|
|
.byte 0x40+1 ! DW_CFA_advance_loc 4
|
|
.byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
|
|
.byte 0x2d ! DW_CFA_GNU_window_save
|
|
.byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
|
|
.align 8
|
|
.LEFDE2:
|
|
|
|
.long .LEFDE3 - .LSFDE3 ! FDE Length
|
|
.LSFDE3:
|
|
.long .LSFDE3 - .LCIE ! FDE CIE offset
|
|
FDE_RANGE(.LUW6, .LUW8)
|
|
.byte 0 ! Augmentation size
|
|
.byte 0x40+1 ! DW_CFA_advance_loc 4
|
|
.byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
|
|
.byte 0x2d ! DW_CFA_GNU_window_save
|
|
.byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
|
|
.align 8
|
|
.LEFDE3:
|
|
|
|
#endif /* SPARC64 */
|
|
#ifdef __linux__
|
|
.section .note.GNU-stack,"",@progbits
|
|
#endif
|