Home | History | Annotate | Download | only in sparc
      1 /* -----------------------------------------------------------------------
      2    v8.S - Copyright (c) 2013  The Written Word, Inc.
      3 	  Copyright (c) 1996, 1997, 2003, 2004, 2008  Red Hat, Inc.
      4 
      5    SPARC Foreign Function Interface
      6 
      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:
     14 
     15    The above copyright notice and this permission notice shall be included
     16    in all copies or substantial portions of the Software.
     17 
     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    ----------------------------------------------------------------------- */
     27 
     28 #define LIBFFI_ASM
     29 #include <fficonfig.h>
     30 #include <ffi.h>
     31 
     32 #define STACKFRAME 96		/* Minimum stack framesize for SPARC */
     33 #define ARGS (64+4)		/* Offset of register area in frame */
     34 
     35 #ifndef __GNUC__
     36 	.text
     37         .align 8
     38 .globl ffi_flush_icache
     39 .globl _ffi_flush_icache
     40 
     41 ffi_flush_icache:
     42 _ffi_flush_icache:
     43         add %o0, %o1, %o2
     44 #ifdef SPARC64
     45 1:	flush %o0
     46 #else
     47 1:	iflush %o0
     48 #endif
     49 	add %o0, 8, %o0
     50 	cmp %o0, %o2
     51 	blt 1b
     52 	nop
     53 	nop
     54 	nop
     55 	nop
     56 	nop
     57 	retl
     58 	nop
     59 .ffi_flush_icache_end:
     60 	.size	ffi_flush_icache,.ffi_flush_icache_end-ffi_flush_icache
     61 #endif
     62 
     63 	.text
     64         .align 8
     65 .globl ffi_call_v8
     66 .globl _ffi_call_v8
     67 
     68 ffi_call_v8:
     69 _ffi_call_v8:
     70 .LLFB1:
     71 	save	%sp, -STACKFRAME, %sp
     72 .LLCFI0:
     73 
     74 	sub	%sp, %i2, %sp	! alloca() space in stack for frame to set up
     75 	add	%sp, STACKFRAME, %l0	! %l0 has start of
     76 					! frame to set up
     77 
     78 	mov	%l0, %o0	! call routine to set up frame
     79 	call	%i0
     80 	mov	%i1, %o1	! (delay)
     81 
     82 	ld	[%l0+ARGS], %o0	! call foreign function
     83 	ld	[%l0+ARGS+4], %o1
     84 	ld	[%l0+ARGS+8], %o2
     85 	ld	[%l0+ARGS+12], %o3
     86 	ld	[%l0+ARGS+16], %o4
     87 	ld	[%l0+ARGS+20], %o5
     88 	call	%i5
     89 	mov	%l0, %sp	! (delay) switch to frame
     90 	nop			! STRUCT returning functions skip 12 instead of 8 bytes
     91 
     92 	! If the return value pointer is NULL, assume no return value.
     93 	tst	%i4
     94 	bz	done
     95 	nop
     96 
     97 	cmp	%i3, FFI_TYPE_INT
     98 	be,a	done
     99 	st	%o0, [%i4]	! (delay)
    100 
    101 	cmp	%i3, FFI_TYPE_FLOAT
    102 	be,a	done
    103 	st	%f0, [%i4+0]	! (delay)
    104 
    105 	cmp	%i3, FFI_TYPE_DOUBLE
    106 	be,a	double
    107 	st	%f0, [%i4+0]	! (delay)
    108 
    109 	cmp	%i3, FFI_TYPE_SINT8
    110 	be,a	sint8
    111 	sll	%o0, 24, %o0	! (delay)
    112 
    113 	cmp	%i3, FFI_TYPE_UINT8
    114 	be,a	uint8
    115 	sll	%o0, 24, %o0	! (delay)
    116 
    117 	cmp	%i3, FFI_TYPE_SINT16
    118 	be,a	sint16
    119 	sll	%o0, 16, %o0	! (delay)
    120 
    121 	cmp	%i3, FFI_TYPE_UINT16
    122 	be,a	uint16
    123 	sll	%o0, 16, %o0	! (delay)
    124 
    125 	cmp	%i3, FFI_TYPE_SINT64
    126 	be,a	longlong
    127 	st	%o0, [%i4+0]	! (delay)
    128 done:
    129 	ret
    130 	restore
    131 
    132 double:
    133 	st	%f1, [%i4+4]
    134 	ret
    135 	restore
    136 
    137 sint8:
    138 	sra	%o0, 24, %o0
    139 	st	%o0, [%i4+0]
    140 	ret
    141 	restore
    142 
    143 uint8:
    144 	srl	%o0, 24, %o0
    145 	st	%o0, [%i4+0]
    146 	ret
    147 	restore
    148 
    149 sint16:
    150 	sra	%o0, 16, %o0
    151 	st	%o0, [%i4+0]
    152 	ret
    153 	restore
    154 
    155 uint16:
    156 	srl	%o0, 16, %o0
    157 	st	%o0, [%i4+0]
    158 	ret
    159 	restore
    160 
    161 longlong:
    162 	st	%o1, [%i4+4]
    163 	ret
    164 	restore
    165 .LLFE1:
    166 
    167 .ffi_call_v8_end:
    168 	.size	ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
    169 
    170 
    171 #undef STACKFRAME
    172 #define	STACKFRAME	104	/* 16*4 register window +
    173 				   1*4 struct return +
    174 				   6*4 args backing store +
    175 				   3*4 locals */
    176 
    177 /* ffi_closure_v8(...)
    178 
    179    Receives the closure argument in %g2.   */
    180 
    181 	.text
    182 	.align 8
    183 	.globl ffi_closure_v8
    184 
    185 ffi_closure_v8:
    186 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
    187 		.register	%g2, #scratch
    188 #endif
    189 .LLFB2:
    190 	! Reserve frame space for all arguments in case
    191 	! we need to align them on a 8-byte boundary.
    192 	ld	[%g2+FFI_TRAMPOLINE_SIZE], %g1
    193 	ld	[%g1+4], %g1
    194 	sll	%g1, 3, %g1
    195 	add	%g1, STACKFRAME, %g1
    196 	! %g1 == STACKFRAME + 8*nargs
    197 	neg	%g1
    198 	save	%sp, %g1, %sp
    199 .LLCFI1:
    200 
    201 	! Store all of the potential argument registers in va_list format.
    202 	st	%i0, [%fp+68+0]
    203 	st	%i1, [%fp+68+4]
    204 	st	%i2, [%fp+68+8]
    205 	st	%i3, [%fp+68+12]
    206 	st	%i4, [%fp+68+16]
    207 	st	%i5, [%fp+68+20]
    208 
    209 	! Call ffi_closure_sparc_inner to do the bulk of the work.
    210 	mov	%g2, %o0
    211 	add	%fp, -8, %o1
    212 	add	%fp,  64, %o2
    213 	call	ffi_closure_sparc_inner_v8
    214 	 add	%fp, -16, %o3
    215 
    216 	! Load up the return value in the proper type.
    217 	! See ffi_prep_cif_machdep for the list of cases.
    218 	cmp	%o0, FFI_TYPE_VOID
    219 	be	done1
    220 
    221 	cmp	%o0, FFI_TYPE_INT
    222 	be	done1
    223 	 ld	[%fp-8], %i0
    224 
    225 	cmp	%o0, FFI_TYPE_FLOAT
    226 	be,a	done1
    227 	 ld	[%fp-8], %f0
    228 
    229 	cmp	%o0, FFI_TYPE_DOUBLE
    230 	be,a	done1
    231 	 ldd	[%fp-8], %f0
    232 
    233 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    234 	cmp	%o0, FFI_TYPE_LONGDOUBLE
    235 	be	done2
    236 #endif
    237 
    238 	cmp	%o0, FFI_TYPE_STRUCT
    239 	be	done2
    240 
    241 	cmp	%o0, FFI_TYPE_SINT64
    242 	be,a	done1
    243 	 ldd	[%fp-8], %i0
    244 
    245 	cmp	%o0, FFI_TYPE_UINT64
    246 	be,a	done1
    247 	 ldd	[%fp-8], %i0
    248 
    249 	ld	[%fp-8], %i0
    250 done1:
    251 	jmp	%i7+8
    252 	 restore
    253 done2:
    254 	! Skip 'unimp'.
    255 	jmp	%i7+12
    256 	 restore
    257 .LLFE2:
    258 
    259 .ffi_closure_v8_end:
    260 	.size	ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
    261 
    262 #ifdef SPARC64
    263 #define WS 8
    264 #define nword	xword
    265 #define uanword	uaxword
    266 #else
    267 #define WS 4
    268 #define nword	long
    269 #define uanword	uaword
    270 #endif
    271 
    272 #ifdef HAVE_RO_EH_FRAME
    273 	.section	".eh_frame",#alloc
    274 #else
    275 	.section	".eh_frame",#alloc,#write
    276 #endif
    277 .LLframe1:
    278 	.uaword	.LLECIE1-.LLSCIE1	! Length of Common Information Entry
    279 .LLSCIE1:
    280 	.uaword	0x0	! CIE Identifier Tag
    281 	.byte	0x1	! CIE Version
    282 	.ascii "zR\0"	! CIE Augmentation
    283 	.byte	0x1	! uleb128 0x1; CIE Code Alignment Factor
    284 	.byte	0x80-WS	! sleb128 -WS; CIE Data Alignment Factor
    285 	.byte	0xf	! CIE RA Column
    286 	.byte	0x1	! uleb128 0x1; Augmentation size
    287 #ifdef HAVE_AS_SPARC_UA_PCREL
    288 	.byte	0x1b	! FDE Encoding (pcrel sdata4)
    289 #else
    290 	.byte	0x50	! FDE Encoding (aligned absolute)
    291 #endif
    292 	.byte	0xc	! DW_CFA_def_cfa
    293 	.byte	0xe	! uleb128 0xe
    294 	.byte	0x0	! uleb128 0x0
    295 	.align	WS
    296 .LLECIE1:
    297 .LLSFDE1:
    298 	.uaword	.LLEFDE1-.LLASFDE1	! FDE Length
    299 .LLASFDE1:
    300 	.uaword	.LLASFDE1-.LLframe1	! FDE CIE offset
    301 #ifdef HAVE_AS_SPARC_UA_PCREL
    302 	.uaword	%r_disp32(.LLFB1)
    303 	.uaword	.LLFE1-.LLFB1	! FDE address range
    304 #else
    305 	.align	WS
    306 	.nword	.LLFB1
    307 	.uanword .LLFE1-.LLFB1	! FDE address range
    308 #endif
    309 	.byte	0x0	! uleb128 0x0; Augmentation size
    310 	.byte	0x4	! DW_CFA_advance_loc4
    311 	.uaword	.LLCFI0-.LLFB1
    312 	.byte	0xd	! DW_CFA_def_cfa_register
    313 	.byte	0x1e	! uleb128 0x1e
    314 	.byte	0x2d	! DW_CFA_GNU_window_save
    315 	.byte	0x9	! DW_CFA_register
    316 	.byte	0xf	! uleb128 0xf
    317 	.byte	0x1f	! uleb128 0x1f
    318 	.align	WS
    319 .LLEFDE1:
    320 .LLSFDE2:
    321 	.uaword	.LLEFDE2-.LLASFDE2	! FDE Length
    322 .LLASFDE2:
    323 	.uaword	.LLASFDE2-.LLframe1	! FDE CIE offset
    324 #ifdef HAVE_AS_SPARC_UA_PCREL
    325 	.uaword	%r_disp32(.LLFB2)
    326 	.uaword	.LLFE2-.LLFB2	! FDE address range
    327 #else
    328 	.align	WS
    329 	.nword	.LLFB2
    330 	.uanword .LLFE2-.LLFB2	! FDE address range
    331 #endif
    332 	.byte	0x0	! uleb128 0x0; Augmentation size
    333 	.byte	0x4	! DW_CFA_advance_loc4
    334 	.uaword	.LLCFI1-.LLFB2
    335 	.byte	0xd	! DW_CFA_def_cfa_register
    336 	.byte	0x1e	! uleb128 0x1e
    337 	.byte	0x2d	! DW_CFA_GNU_window_save
    338 	.byte	0x9	! DW_CFA_register
    339 	.byte	0xf	! uleb128 0xf
    340 	.byte	0x1f	! uleb128 0x1f
    341 	.align	WS
    342 .LLEFDE2:
    343 
    344 #if defined __ELF__ && defined __linux__
    345 	.section	.note.GNU-stack,"",@progbits
    346 #endif
    347