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
41ffi_flush_icache:
42_ffi_flush_icache:
43        add %o0, %o1, %o2
44#ifdef SPARC64
451:	flush %o0
46#else
471:	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
68ffi_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)
128done:
129	ret
130	restore
131
132double:
133	st	%f1, [%i4+4]
134	ret
135	restore
136
137sint8:
138	sra	%o0, 24, %o0
139	st	%o0, [%i4+0]
140	ret
141	restore
142
143uint8:
144	srl	%o0, 24, %o0
145	st	%o0, [%i4+0]
146	ret
147	restore
148
149sint16:
150	sra	%o0, 16, %o0
151	st	%o0, [%i4+0]
152	ret
153	restore
154
155uint16:
156	srl	%o0, 16, %o0
157	st	%o0, [%i4+0]
158	ret
159	restore
160
161longlong:
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
185ffi_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
250done1:
251	jmp	%i7+8
252	 restore
253done2:
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