1 /* -----------------------------------------------------------------------
2 v8.S - Copyright (c) 2013 The Written Word, Inc.
3 Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
5 SPARC Foreign Function Interface
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
29 #include <fficonfig.h>
35 #define C2(X, Y) X ## Y
36 #define C1(X, Y) C2(X, Y)
38 #ifdef __USER_LABEL_PREFIX__
39 # define C(Y) C1(__USER_LABEL_PREFIX__, Y)
43 #define L(Y) C1(.L, Y)
49 .globl C(ffi_flush_icache)
50 .type C(ffi_flush_icache),#function
51 FFI_HIDDEN(C(ffi_flush_icache))
63 .size C(ffi_flush_icache), . - C(ffi_flush_icache)
66 #if defined(__sun__) && defined(__svr4__)
67 # define E(INDEX) .align 16
69 # define E(INDEX) .align 16; .org 2b + INDEX * 16
74 .type C(ffi_call_v8),#function
75 FFI_HIDDEN(C(ffi_call_v8))
79 ! Allocate a stack frame sized by ffi_call.
82 mov %i0, %o0 ! copy cif
83 add %sp, 64+32, %o1 ! load args area
84 mov %i2, %o2 ! copy rvalue
85 call C(ffi_prep_args_v8)
86 mov %i3, %o3 ! copy avalue
88 add %sp, 32, %sp ! deallocate prep frame
89 and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type
90 srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size
91 ld [%sp+64+4], %o0 ! load all argument registers
95 cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4
100 ! Call foreign function
102 mov %i5, %g2 ! load static chain
104 0: call 1f ! load pc in %o7
106 1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16
110 ! Note that each entry is 4 insns, enforced by the E macro.
191 ! Struct returning functions expect and skip the unimp here.
192 ! To make it worse, conforming callees examine the unimp and
193 ! make sure the low 12 bits of the unimp match the size of
194 ! the struct being returned.
196 8: call 1f ! load pc in %o7
197 sll %l1, 2, %l0 ! size * 4
198 1: sll %l1, 4, %l1 ! size * 16
199 add %l0, %l1, %l0 ! size * 20
200 add %o7, %l0, %o7 ! o7 = 8b + size*20
202 mov %i5, %g2 ! load static chain
205 /* The Sun assembler doesn't understand .rept 0x1000. */
209 unimp (. - 2b) / 20; \
214 rept1; rept1; rept1; rept1; \
215 rept1; rept1; rept1; rept1; \
216 rept1; rept1; rept1; rept1; \
217 rept1; rept1; rept1; rept1
220 rept16; rept16; rept16; rept16; \
221 rept16; rept16; rept16; rept16; \
222 rept16; rept16; rept16; rept16; \
223 rept16; rept16; rept16; rept16
225 rept256; rept256; rept256; rept256
226 rept256; rept256; rept256; rept256
227 rept256; rept256; rept256; rept256
228 rept256; rept256; rept256; rept256
231 .size C(ffi_call_v8),. - C(ffi_call_v8)
234 /* 16*4 register window + 1*4 struct return + 6*4 args backing store
235 + 8*4 return storage + 1*4 alignment. */
236 #define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
238 /* ffi_closure_v8(...)
240 Receives the closure argument in %g2. */
242 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
243 .register %g2, #scratch
247 .globl C(ffi_go_closure_v8)
248 .type C(ffi_go_closure_v8),#function
249 FFI_HIDDEN(C(ffi_go_closure_v8))
251 C(ffi_go_closure_v8):
253 save %sp, -STACKFRAME, %sp
255 ld [%g2+4], %o0 ! load cif
256 ld [%g2+8], %o1 ! load fun
258 mov %g2, %o2 ! load user_data
260 .size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
263 .globl C(ffi_closure_v8)
264 .type C(ffi_closure_v8),#function
265 FFI_HIDDEN(C(ffi_closure_v8))
269 save %sp, -STACKFRAME, %sp
271 ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
272 ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
273 ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data
275 ! Store all of the potential argument registers in va_list format.
283 ! Call ffi_closure_sparc_inner to do the bulk of the work.
285 call ffi_closure_sparc_inner_v8
289 and %o0, SPARC_FLAG_RET_MASK, %o0
290 1: sll %o0, 4, %o0 ! o0 = o0 * 16
291 add %o7, %o0, %o7 ! o7 = 0b + o0*16
295 ! Note that each entry is 4 insns, enforced by the E macro.
367 .size C(ffi_closure_v8), . - C(ffi_closure_v8)
369 #ifdef HAVE_RO_EH_FRAME
370 .section ".eh_frame",#alloc
372 .section ".eh_frame",#alloc,#write
375 #ifdef HAVE_AS_SPARC_UA_PCREL
376 # define FDE_ADDR(X) %r_disp32(X)
378 # define FDE_ADDR(X) X
383 .long .LECIE - .LSCIE ! CIE Length
385 .long 0 ! CIE Identifier Tag
386 .byte 1 ! CIE Version
387 .ascii "zR\0" ! CIE Augmentation
388 .byte 4 ! CIE Code Alignment Factor
389 .byte 0x7c ! CIE Data Alignment Factor
390 .byte 15 ! CIE RA Column
391 .byte 1 ! Augmentation size
392 #ifdef HAVE_AS_SPARC_UA_PCREL
393 .byte 0x1b ! FDE Encoding (pcrel sdata4)
395 .byte 0x50 ! FDE Encoding (aligned absolute)
397 .byte 0xc, 14, 0 ! DW_CFA_def_cfa, %o6, offset 0
401 .long .LEFDE1 - .LSFDE1 ! FDE Length
403 .long .LSFDE1 - .LCIE ! FDE CIE offset
404 .long FDE_ADDR(.LUW0) ! Initial location
405 .long .LUW2 - .LUW0 ! Address range
406 .byte 0 ! Augmentation size
407 .byte 0x40+1 ! DW_CFA_advance_loc 4
408 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
409 .byte 0x2d ! DW_CFA_GNU_window_save
410 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
414 .long .LEFDE2 - .LSFDE2 ! FDE Length
416 .long .LSFDE2 - .LCIE ! FDE CIE offset
417 .long FDE_ADDR(.LUW3) ! Initial location
418 .long .LUW5 - .LUW3 ! Address range
419 .byte 0 ! Augmentation size
420 .byte 0x40+1 ! DW_CFA_advance_loc 4
421 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
422 .byte 0x2d ! DW_CFA_GNU_window_save
423 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
427 .long .LEFDE3 - .LSFDE3 ! FDE Length
429 .long .LSFDE3 - .LCIE ! FDE CIE offset
430 .long FDE_ADDR(.LUW6) ! Initial location
431 .long .LUW8 - .LUW6 ! Address range
432 .byte 0 ! Augmentation size
433 .byte 0x40+1 ! DW_CFA_advance_loc 4
434 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
435 .byte 0x2d ! DW_CFA_GNU_window_save
436 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
440 #endif /* !SPARC64 */
441 #if defined __ELF__ && defined __linux__
442 .section .note.GNU-stack,"",@progbits