aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/sparc/v8.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/sparc/v8.S')
-rw-r--r--libffi/src/sparc/v8.S535
1 files changed, 290 insertions, 245 deletions
diff --git a/libffi/src/sparc/v8.S b/libffi/src/sparc/v8.S
index 7ec6e1c..3a811ef 100644
--- a/libffi/src/sparc/v8.S
+++ b/libffi/src/sparc/v8.S
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
+ v8.S - Copyright (c) 2013 The Written Word, Inc.
+ Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
- SPARC Foreign Function Interface
+ SPARC Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -24,153 +25,243 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
-#define LIBFFI_ASM
+#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
#ifndef SPARC64
-#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
-#define ARGS (64+4) /* Offset of register area in frame */
+#define C2(X, Y) X ## Y
+#define C1(X, Y) C2(X, Y)
-.text
- .align 8
-.globl ffi_call_v8
-.globl _ffi_call_v8
-
-ffi_call_v8:
-_ffi_call_v8:
-.LLFB1:
- save %sp, -STACKFRAME, %sp
-.LLCFI0:
-
- sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
- add %sp, STACKFRAME, %l0 ! %l0 has start of
- ! frame to set up
-
- mov %l0, %o0 ! call routine to set up frame
- call %i0
- mov %i1, %o1 ! (delay)
-
- ld [%l0+ARGS], %o0 ! call foreign function
- ld [%l0+ARGS+4], %o1
- ld [%l0+ARGS+8], %o2
- ld [%l0+ARGS+12], %o3
- ld [%l0+ARGS+16], %o4
- ld [%l0+ARGS+20], %o5
- call %i5
- mov %l0, %sp ! (delay) switch to frame
- nop ! STRUCT returning functions skip 12 instead of 8 bytes
-
- ! If the return value pointer is NULL, assume no return value.
- tst %i4
- bz done
- nop
-
- cmp %i3, FFI_TYPE_INT
- be,a done
- st %o0, [%i4] ! (delay)
-
- cmp %i3, FFI_TYPE_FLOAT
- be,a done
- st %f0, [%i4+0] ! (delay)
-
- cmp %i3, FFI_TYPE_DOUBLE
- be,a double
- st %f0, [%i4+0] ! (delay)
-
- cmp %i3, FFI_TYPE_SINT8
- be,a sint8
- sll %o0, 24, %o0 ! (delay)
+#ifdef __USER_LABEL_PREFIX__
+# define C(Y) C1(__USER_LABEL_PREFIX__, Y)
+#else
+# define C(Y) Y
+#endif
+#define L(Y) C1(.L, Y)
- cmp %i3, FFI_TYPE_UINT8
- be,a uint8
- sll %o0, 24, %o0 ! (delay)
+ .text
- cmp %i3, FFI_TYPE_SINT16
- be,a sint16
- sll %o0, 16, %o0 ! (delay)
+#ifndef __GNUC__
+ .align 8
+ .globl C(ffi_flush_icache)
+ .type C(ffi_flush_icache),@function
+ FFI_HIDDEN(C(ffi_flush_icache))
+
+C(ffi_flush_icache):
+ cfi_startproc
+1: iflush %o0
+ iflush %o+8
+ nop
+ nop
+ nop
+ nop
+ nop
+ retl
+ nop
+ cfi_endproc
+ .size C(ffi_flush_icache), . - C(ffi_flush_icache)
+#endif
- cmp %i3, FFI_TYPE_UINT16
- be,a uint16
- sll %o0, 16, %o0 ! (delay)
+.macro E index
+ .align 16
+ .org 2b + \index * 16
+.endm
- cmp %i3, FFI_TYPE_SINT64
- be,a longlong
- st %o0, [%i4+0] ! (delay)
-done:
+ .align 8
+ .globl C(ffi_call_v8)
+ .type C(ffi_call_v8),@function
+ FFI_HIDDEN(C(ffi_call_v8))
+
+C(ffi_call_v8):
+ cfi_startproc
+ ! Allocate a stack frame sized by ffi_call.
+ save %sp, %o4, %sp
+ cfi_def_cfa_register(%fp)
+ cfi_window_save
+
+ mov %i0, %o0 ! copy cif
+ add %sp, 64+32, %o1 ! load args area
+ mov %i2, %o2 ! copy rvalue
+ call C(ffi_prep_args_v8)
+ mov %i3, %o3 ! copy avalue
+
+ add %sp, 32, %sp ! deallocate prep frame
+ and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type
+ srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size
+ ld [%sp+64+4], %o0 ! load all argument registers
+ ld [%sp+64+8], %o1
+ ld [%sp+64+12], %o2
+ ld [%sp+64+16], %o3
+ cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4
+ ld [%sp+64+20], %o4
+ be 8f
+ ld [%sp+64+24], %o5
+
+ ! Call foreign function
+ call %i1
+ mov %i5, %g2 ! load static chain
+
+0: call 1f ! load pc in %o7
+ sll %l0, 4, %l0
+1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16
+ jmp %o7+(2f-0b)
+ nop
+
+ ! Note that each entry is 4 insns, enforced by the E macro.
+ .align 16
+2:
+E SPARC_RET_VOID
ret
- restore
-
-double:
- st %f1, [%i4+4]
+ restore
+E SPARC_RET_STRUCT
+ unimp
+E SPARC_RET_UINT8
+ and %o0, 0xff, %o0
+ st %o0, [%i2]
ret
- restore
-
-sint8:
- sra %o0, 24, %o0
- st %o0, [%i4+0]
+ restore
+E SPARC_RET_SINT8
+ sll %o0, 24, %o0
+ b 7f
+ sra %o0, 24, %o0
+E SPARC_RET_UINT16
+ sll %o0, 16, %o0
+ b 7f
+ srl %o0, 16, %o0
+E SPARC_RET_SINT16
+ sll %o0, 16, %o0
+ b 7f
+ sra %o0, 16, %o0
+E SPARC_RET_UINT32
+7: st %o0, [%i2]
ret
- restore
-
-uint8:
- srl %o0, 24, %o0
- st %o0, [%i4+0]
+ restore
+E SP_V8_RET_CPLX16
+ sth %o0, [%i2+2]
+ b 9f
+ srl %o0, 16, %o0
+E SPARC_RET_INT64
+ st %o0, [%i2]
+ st %o1, [%i2+4]
ret
- restore
-
-sint16:
- sra %o0, 16, %o0
- st %o0, [%i4+0]
+ restore
+E SPARC_RET_INT128
+ std %o0, [%i2]
+ std %o2, [%i2+8]
ret
- restore
+ restore
+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
+ st %f3, [%i2+3*4]
+ nop
+ st %f2, [%i2+2*4]
+ nop
+E SPARC_RET_F_2
+ st %f1, [%i2+4]
+ st %f0, [%i2]
+ ret
+ restore
+E SP_V8_RET_CPLX8
+ stb %o0, [%i2+1]
+ b 10f
+ srl %o0, 8, %o0
+E SPARC_RET_F_1
+ st %f0, [%i2]
+ ret
+ restore
-uint16:
- srl %o0, 16, %o0
- st %o0, [%i4+0]
+ .align 8
+9: sth %o0, [%i2]
+ ret
+ restore
+ .align 8
+10: stb %o0, [%i2]
ret
- restore
+ restore
-longlong:
- st %o1, [%i4+4]
+ ! Struct returning functions expect and skip the unimp here.
+ ! To make it worse, conforming callees examine the unimp and
+ ! make sure the low 12 bits of the unimp match the size of
+ ! the struct being returned.
+ .align 8
+8: call 1f ! load pc in %o7
+ sll %l1, 2, %l0 ! size * 4
+1: sll %l1, 4, %l1 ! size * 16
+ add %l0, %l1, %l0 ! size * 20
+ add %o7, %l0, %o7 ! o7 = 0b + size*20
+ jmp %o7+(2f-8b)
+ mov %i5, %g2 ! load static chain
+2:
+.rept 0x1000
+ call %i1
+ nop
+ unimp (. - 2b) / 20
ret
- restore
-.LLFE1:
+ restore
+.endr
-.ffi_call_v8_end:
- .size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
+ cfi_endproc
+ .size C(ffi_call_v8),. - C(ffi_call_v8)
-#undef STACKFRAME
-#define STACKFRAME 104 /* 16*4 register window +
- 1*4 struct return +
- 6*4 args backing store +
- 3*4 locals */
+/* 16*4 register window + 1*4 struct return + 6*4 args backing store
+ + 8*4 return storage + 1*4 alignment. */
+#define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
/* ffi_closure_v8(...)
Receives the closure argument in %g2. */
- .text
- .align 8
- .globl ffi_closure_v8
-
-ffi_closure_v8:
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
- .register %g2, #scratch
+ .register %g2, #scratch
#endif
-.LLFB2:
- ! Reserve frame space for all arguments in case
- ! we need to align them on a 8-byte boundary.
- ld [%g2+FFI_TRAMPOLINE_SIZE], %g1
- ld [%g1+4], %g1
- sll %g1, 3, %g1
- add %g1, STACKFRAME, %g1
- ! %g1 == STACKFRAME + 8*nargs
- neg %g1
- save %sp, %g1, %sp
-.LLCFI1:
+ .align 8
+ .globl C(ffi_go_closure_v8)
+ .type C(ffi_go_closure_v8),@function
+ FFI_HIDDEN(C(ffi_go_closure_v8))
+
+C(ffi_go_closure_v8):
+ cfi_startproc
+ save %sp, -STACKFRAME, %sp
+ cfi_def_cfa_register(%fp)
+ cfi_window_save
+
+ ld [%g2+4], %o0 ! load cif
+ ld [%g2+8], %o1 ! load fun
+ b 0f
+ mov %g2, %o2 ! load user_data
+ cfi_endproc
+ .size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
+
+ .align 8
+ .globl C(ffi_closure_v8)
+ .type C(ffi_closure_v8),@function
+ FFI_HIDDEN(C(ffi_closure_v8))
+
+C(ffi_closure_v8):
+ cfi_startproc
+ save %sp, -STACKFRAME, %sp
+ cfi_def_cfa_register(%fp)
+ cfi_window_save
+
+ ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
+ ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
+ ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data
+0:
! Store all of the potential argument registers in va_list format.
st %i0, [%fp+68+0]
st %i1, [%fp+68+4]
@@ -180,137 +271,91 @@ ffi_closure_v8:
st %i5, [%fp+68+20]
! Call ffi_closure_sparc_inner to do the bulk of the work.
- mov %g2, %o0
- add %fp, -8, %o1
- add %fp, 64, %o2
+ add %fp, -8*4, %o3
call ffi_closure_sparc_inner_v8
- add %fp, -16, %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 done1
-
- cmp %o0, FFI_TYPE_INT
- be done1
- ld [%fp-8], %i0
-
- cmp %o0, FFI_TYPE_FLOAT
- be,a done1
- ld [%fp-8], %f0
-
- cmp %o0, FFI_TYPE_DOUBLE
- be,a done1
- ldd [%fp-8], %f0
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- cmp %o0, FFI_TYPE_LONGDOUBLE
- be done2
-#endif
-
- cmp %o0, FFI_TYPE_STRUCT
- be done2
-
- cmp %o0, FFI_TYPE_SINT64
- be,a done1
- ldd [%fp-8], %i0
-
- ld [%fp-8], %i0
-done1:
- jmp %i7+8
+ add %fp, 64, %o4
+
+0: call 1f
+ and %o0, SPARC_FLAG_RET_MASK, %o0
+1: sll %o0, 4, %o0 ! o0 = o0 * 16
+ add %o7, %o0, %o7 ! o7 = 0b + o0*16
+ jmp %o7+(2f-0b)
+ add %fp, -8*4, %i2
+
+ ! Note that each entry is 4 insns, enforced by the E macro.
+ .align 16
+2:
+E SPARC_RET_VOID
+ ret
restore
-done2:
- ! Skip 'unimp'.
+E SPARC_RET_STRUCT
+ ld [%i2], %i0
jmp %i7+12
restore
-.LLFE2:
-
-.ffi_closure_v8_end:
- .size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
-
-#ifdef SPARC64
-#define WS 8
-#define nword xword
-#define uanword uaxword
-#else
-#define WS 4
-#define nword long
-#define uanword uaword
-#endif
-
-#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 0x80-WS ! sleb128 -WS; 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 0x0 ! uleb128 0x0
- .align WS
-.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 WS
- .nword .LLFB1
- .uanword .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 WS
-.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 WS
- .nword .LLFB2
- .uanword .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 WS
-.LLEFDE2:
-#endif
+E SPARC_RET_UINT8
+ ldub [%i2+3], %i0
+ ret
+ restore
+E SPARC_RET_SINT8
+ ldsb [%i2+3], %i0
+ ret
+ restore
+E SPARC_RET_UINT16
+ lduh [%i2+2], %i0
+ ret
+ restore
+E SPARC_RET_SINT16
+ ldsh [%i2+2], %i0
+ ret
+ restore
+E SPARC_RET_UINT32
+ ld [%i2], %i0
+ ret
+ restore
+E SP_V8_RET_CPLX16
+ ld [%i2], %i0
+ ret
+ restore
+E SPARC_RET_INT64
+ ldd [%i2], %i0
+ ret
+ restore
+E SPARC_RET_INT128
+ ldd [%i2], %i0
+ ldd [%i2+8], %i2
+ ret
+ restore
+E SPARC_RET_F_8
+ ld [%i2+7*4], %f7
+ nop
+ ld [%i2+6*4], %f6
+ nop
+E SPARC_RET_F_6
+ ld [%i2+5*4], %f5
+ nop
+ ld [%i2+4*4], %f4
+ nop
+E SPARC_RET_F_4
+ ld [%i2+3*4], %f3
+ nop
+ ld [%i2+2*4], %f2
+ nop
+E SPARC_RET_F_2
+ ldd [%i2], %f0
+ ret
+ restore
+E SP_V8_RET_CPLX8
+ lduh [%i2], %i0
+ ret
+ restore
+E SPARC_RET_F_1
+ ld [%i2], %f0
+ ret
+ restore
+ cfi_endproc
+ .size C(ffi_closure_v8), . - C(ffi_closure_v8)
+#endif /* !SPARC64 */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits
#endif