• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#include "internal.h"
32
33#ifndef SPARC64
34
35#define C2(X, Y)  X ## Y
36#define C1(X, Y)  C2(X, Y)
37
38#ifdef __USER_LABEL_PREFIX__
39# define C(Y)	C1(__USER_LABEL_PREFIX__, Y)
40#else
41# define C(Y)	Y
42#endif
43#define L(Y)	C1(.L, Y)
44
45	.text
46
47#ifndef __GNUC__
48        .align 8
49	.globl	C(ffi_flush_icache)
50	.type	C(ffi_flush_icache),#function
51	FFI_HIDDEN(C(ffi_flush_icache))
52
53C(ffi_flush_icache):
541:	iflush %o0
55	iflush %o+8
56	nop
57	nop
58	nop
59	nop
60	nop
61	retl
62	 nop
63	.size	C(ffi_flush_icache), . - C(ffi_flush_icache)
64#endif
65
66#if defined(__sun__) && defined(__svr4__)
67# define E(INDEX)	.align 16
68#else
69# define E(INDEX)	.align 16; .org 2b + INDEX * 16
70#endif
71
72        .align 8
73	.globl	C(ffi_call_v8)
74	.type	C(ffi_call_v8),#function
75	FFI_HIDDEN(C(ffi_call_v8))
76
77C(ffi_call_v8):
78.LUW0:
79	! Allocate a stack frame sized by ffi_call.
80	save	%sp, %o4, %sp
81.LUW1:
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
87
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
92	ld	[%sp+64+8], %o1
93	ld	[%sp+64+12], %o2
94	ld	[%sp+64+16], %o3
95	cmp	%l0, SPARC_RET_STRUCT	! struct return needs an unimp 4
96	ld	[%sp+64+20], %o4
97	be	8f
98	 ld	[%sp+64+24], %o5
99
100	! Call foreign function
101	call	%i1
102	 mov	%i5, %g2		! load static chain
103
1040:	call	1f		! load pc in %o7
105	 sll	%l0, 4, %l0
1061:	add	%o7, %l0, %o7	! o7 = 0b + ret_type*16
107	jmp	%o7+(2f-0b)
108	 nop
109
110	! Note that each entry is 4 insns, enforced by the E macro.
111	.align	16
1122:
113E(SPARC_RET_VOID)
114	ret
115	 restore
116E(SPARC_RET_STRUCT)
117	unimp
118E(SPARC_RET_UINT8)
119	and	%o0, 0xff, %o0
120	st	%o0, [%i2]
121	ret
122	 restore
123E(SPARC_RET_SINT8)
124	sll	%o0, 24, %o0
125	b	7f
126	 sra	%o0, 24, %o0
127E(SPARC_RET_UINT16)
128	sll	%o0, 16, %o0
129	b	7f
130	 srl	%o0, 16, %o0
131E(SPARC_RET_SINT16)
132	sll	%o0, 16, %o0
133	b	7f
134	 sra	%o0, 16, %o0
135E(SPARC_RET_UINT32)
1367:	st	%o0, [%i2]
137	ret
138	 restore
139E(SP_V8_RET_CPLX16)
140	sth	%o0, [%i2+2]
141	b	9f
142	 srl	%o0, 16, %o0
143E(SPARC_RET_INT64)
144	st	%o0, [%i2]
145	st	%o1, [%i2+4]
146	ret
147	 restore
148E(SPARC_RET_INT128)
149	std	%o0, [%i2]
150	std	%o2, [%i2+8]
151	ret
152	 restore
153E(SPARC_RET_F_8)
154	st	%f7, [%i2+7*4]
155	nop
156	st	%f6, [%i2+6*4]
157	nop
158E(SPARC_RET_F_6)
159	st	%f5, [%i2+5*4]
160	nop
161	st	%f4, [%i2+4*4]
162	nop
163E(SPARC_RET_F_4)
164	st	%f3, [%i2+3*4]
165	nop
166	st	%f2, [%i2+2*4]
167	nop
168E(SPARC_RET_F_2)
169	st	%f1, [%i2+4]
170	st	%f0, [%i2]
171	ret
172	 restore
173E(SP_V8_RET_CPLX8)
174	stb	%o0, [%i2+1]
175	b	0f
176	 srl	%o0, 8, %o0
177E(SPARC_RET_F_1)
178	st	%f0, [%i2]
179	ret
180	 restore
181
182	.align	8
1839:	sth	%o0, [%i2]
184	ret
185	 restore
186	.align	8
1870:	stb	%o0, [%i2]
188	ret
189	 restore
190
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.
195	.align	8
1968:	call	1f				! load pc in %o7
197	 sll	%l1, 2, %l0			! size * 4
1981:	sll	%l1, 4, %l1			! size * 16
199	add	%l0, %l1, %l0			! size * 20
200	add	%o7, %l0, %o7			! o7 = 8b + size*20
201	jmp	%o7+(2f-8b)
202	 mov	%i5, %g2			! load static chain
2032:
204
205/* The Sun assembler doesn't understand .rept 0x1000.  */
206#define rept1			\
207	call	%i1;		\
208	 nop;			\
209	unimp	(. - 2b) / 20;	\
210	ret;			\
211	 restore
212
213#define rept16				\
214	rept1; rept1; rept1; rept1;	\
215	rept1; rept1; rept1; rept1;	\
216	rept1; rept1; rept1; rept1;	\
217	rept1; rept1; rept1; rept1
218
219#define rept256				\
220	rept16; rept16; rept16; rept16;	\
221	rept16; rept16; rept16; rept16;	\
222	rept16; rept16; rept16; rept16;	\
223	rept16; rept16; rept16; rept16
224
225	rept256; rept256; rept256; rept256
226	rept256; rept256; rept256; rept256
227	rept256; rept256; rept256; rept256
228	rept256; rept256; rept256; rept256
229
230.LUW2:
231	.size	C(ffi_call_v8),. - C(ffi_call_v8)
232
233
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)
237
238/* ffi_closure_v8(...)
239
240   Receives the closure argument in %g2.   */
241
242#ifdef HAVE_AS_REGISTER_PSEUDO_OP
243	.register	%g2, #scratch
244#endif
245
246	.align 8
247	.globl	C(ffi_go_closure_v8)
248	.type	C(ffi_go_closure_v8),#function
249	FFI_HIDDEN(C(ffi_go_closure_v8))
250
251C(ffi_go_closure_v8):
252.LUW3:
253	save	%sp, -STACKFRAME, %sp
254.LUW4:
255	ld	[%g2+4], %o0			! load cif
256	ld	[%g2+8], %o1			! load fun
257	b	0f
258	 mov	%g2, %o2			! load user_data
259.LUW5:
260	.size	C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
261
262	.align 8
263	.globl	C(ffi_closure_v8)
264	.type	C(ffi_closure_v8),#function
265	FFI_HIDDEN(C(ffi_closure_v8))
266
267C(ffi_closure_v8):
268.LUW6:
269	save	%sp, -STACKFRAME, %sp
270.LUW7:
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
2740:
275	! Store all of the potential argument registers in va_list format.
276	st	%i0, [%fp+68+0]
277	st	%i1, [%fp+68+4]
278	st	%i2, [%fp+68+8]
279	st	%i3, [%fp+68+12]
280	st	%i4, [%fp+68+16]
281	st	%i5, [%fp+68+20]
282
283	! Call ffi_closure_sparc_inner to do the bulk of the work.
284	add	%fp, -8*4, %o3
285	call	ffi_closure_sparc_inner_v8
286	 add	%fp,  64, %o4
287
2880:	call	1f
289	 and	%o0, SPARC_FLAG_RET_MASK, %o0
2901:	sll	%o0, 4, %o0	! o0 = o0 * 16
291	add	%o7, %o0, %o7	! o7 = 0b + o0*16
292	jmp	%o7+(2f-0b)
293	 add	%fp, -8*4, %i2
294
295	! Note that each entry is 4 insns, enforced by the E macro.
296	.align	16
2972:
298E(SPARC_RET_VOID)
299	ret
300	 restore
301E(SPARC_RET_STRUCT)
302	ld	[%i2], %i0
303	jmp	%i7+12
304	 restore
305E(SPARC_RET_UINT8)
306	ldub	[%i2+3], %i0
307	ret
308	 restore
309E(SPARC_RET_SINT8)
310	ldsb	[%i2+3], %i0
311	ret
312	 restore
313E(SPARC_RET_UINT16)
314	lduh	[%i2+2], %i0
315	ret
316	 restore
317E(SPARC_RET_SINT16)
318	ldsh	[%i2+2], %i0
319	ret
320	 restore
321E(SPARC_RET_UINT32)
322	ld	[%i2], %i0
323	ret
324	 restore
325E(SP_V8_RET_CPLX16)
326	ld	[%i2], %i0
327	ret
328	 restore
329E(SPARC_RET_INT64)
330	ldd	[%i2], %i0
331	ret
332	 restore
333E(SPARC_RET_INT128)
334	ldd	[%i2], %i0
335	ldd	[%i2+8], %i2
336	ret
337	 restore
338E(SPARC_RET_F_8)
339	ld	[%i2+7*4], %f7
340	nop
341	ld	[%i2+6*4], %f6
342	nop
343E(SPARC_RET_F_6)
344	ld	[%i2+5*4], %f5
345	nop
346	ld	[%i2+4*4], %f4
347	nop
348E(SPARC_RET_F_4)
349	ld	[%i2+3*4], %f3
350	nop
351	ld	[%i2+2*4], %f2
352	nop
353E(SPARC_RET_F_2)
354	ldd	[%i2], %f0
355	ret
356	 restore
357E(SP_V8_RET_CPLX8)
358	lduh	[%i2], %i0
359	ret
360	 restore
361E(SPARC_RET_F_1)
362	ld	[%i2], %f0
363	ret
364	 restore
365
366.LUW8:
367	.size	C(ffi_closure_v8), . - C(ffi_closure_v8)
368
369#ifdef HAVE_RO_EH_FRAME
370        .section        ".eh_frame",#alloc
371#else
372        .section        ".eh_frame",#alloc,#write
373#endif
374
375#ifdef HAVE_AS_SPARC_UA_PCREL
376# define FDE_ADDR(X)	%r_disp32(X)
377#else
378# define FDE_ADDR(X)	X
379#endif
380
381	.align 4
382.LCIE:
383	.long	.LECIE - .LSCIE		! CIE Length
384.LSCIE:
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)
394#else
395	.byte	0x50			! FDE Encoding (aligned absolute)
396#endif
397	.byte	0xc, 14, 0		! DW_CFA_def_cfa, %o6, offset 0
398	.align	4
399.LECIE:
400
401	.long	.LEFDE1 - .LSFDE1	! FDE Length
402.LSFDE1:
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
411	.align	4
412.LEFDE1:
413
414	.long	.LEFDE2 - .LSFDE2	! FDE Length
415.LSFDE2:
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
424	.align	4
425.LEFDE2:
426
427	.long	.LEFDE3 - .LSFDE3	! FDE Length
428.LSFDE3:
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
437	.align	4
438.LEFDE3:
439
440#endif /* !SPARC64 */
441#if defined __ELF__ && defined __linux__
442	.section	.note.GNU-stack,"",@progbits
443#endif
444