1/* -----------------------------------------------------------------------
2   sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima
3
4   SuperH SHmedia Foreign Function Interface
5
6   Permission is hereby granted, free of charge, to any person obtaining
7   a copy of this software and associated documentation files (the
8   ``Software''), to deal in the Software without restriction, including
9   without limitation the rights to use, copy, modify, merge, publish,
10   distribute, sublicense, and/or sell copies of the Software, and to
11   permit persons to whom the Software is furnished to do so, subject to
12   the following conditions:
13
14   The above copyright notice and this permission notice shall be included
15   in all copies or substantial portions of the Software.
16
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#ifdef HAVE_MACHINE_ASM_H
32#include <machine/asm.h>
33#else
34/* XXX these lose for some platforms, I'm sure. */
35#define CNAME(x) x
36#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
37#endif
38
39#ifdef __LITTLE_ENDIAN__
40#define OFS_FLT	0
41#else
42#define OFS_FLT	4
43#endif
44
45	.section	.text..SHmedia32,"ax"
46
47	# r2:	ffi_prep_args
48	# r3:	&ecif
49	# r4:	bytes
50	# r5:	flags
51	# r6:	flags2
52	# r7:	rvalue
53	# r8:	fn
54
55	# This assumes we are using gas.
56	.align	5
57ENTRY(ffi_call_SYSV)
58	# Save registers
59.LFB1:
60	addi.l	r15, -48, r15
61.LCFI0:
62	st.q	r15, 40, r32
63	st.q	r15, 32, r31
64	st.q	r15, 24, r30
65	st.q	r15, 16, r29
66	st.q	r15, 8, r28
67	st.l	r15, 4, r18
68	st.l	r15, 0, r14
69.LCFI1:
70	add.l	r15, r63, r14
71.LCFI2:
72#	add	r4, r63, r28
73	add	r5, r63, r29
74	add	r6, r63, r30
75	add	r7, r63, r31
76	add	r8, r63, r32
77
78	addi	r4, (64 + 7), r4
79	andi	r4, ~7, r4
80	sub.l	r15, r4, r15
81
82	ptabs/l	r2, tr0
83	add	r15, r63, r2
84	blink	tr0, r18
85
86	addi	r15, 64, r22
87	movi	0, r0
88	movi	0, r1
89	movi	-1, r23
90
91	pt/l	1f, tr1
92	bnei/l	r29, FFI_TYPE_STRUCT, tr1
93	ld.l	r15, 0, r19
94	addi	r15, 8, r15
95	addi	r0, 1, r0
961:
97
98.L_pass:
99	andi	r30, 3, r20
100	shlri	r30, 2, r30
101
102	pt/l	.L_call_it, tr0
103	pt/l	.L_pass_i, tr1
104	pt/l	.L_pass_f, tr2
105
106	beqi/l	r20, FFI_TYPE_VOID, tr0
107	beqi/l	r20, FFI_TYPE_INT, tr1
108	beqi/l	r20, FFI_TYPE_FLOAT, tr2
109
110.L_pass_d:
111	addi	r0, 1, r0
112	pt/l	3f, tr0
113	movi	12, r20
114	bge/l	r1, r20, tr0
115
116	pt/l	.L_pop_d, tr1
117	pt/l	2f, tr0
118	blink	tr1, r63
1192:
120	addi.l	r15, 8, r15
1213:
122	pt/l	.L_pass, tr0
123	addi	r1, 2, r1
124	blink	tr0, r63
125
126.L_pop_d:
127	pt/l	.L_pop_d_tbl, tr1
128	gettr	tr1, r20
129	shlli	r1, 2, r21
130	add	r20, r21, r20
131	ptabs/l	r20, tr1
132	blink	tr1, r63
133
134.L_pop_d_tbl:
135	fld.d	r15, 0, dr0
136	blink	tr0, r63
137	fld.d	r15, 0, dr2
138	blink	tr0, r63
139	fld.d	r15, 0, dr4
140	blink	tr0, r63
141	fld.d	r15, 0, dr6
142	blink	tr0, r63
143	fld.d	r15, 0, dr8
144	blink	tr0, r63
145	fld.d	r15, 0, dr10
146	blink	tr0, r63
147
148.L_pass_f:
149	addi	r0, 1, r0
150	pt/l	3f, tr0
151	movi	12, r20
152	bge/l	r1, r20, tr0
153
154	pt/l	.L_pop_f, tr1
155	pt/l	2f, tr0
156	blink	tr1, r63
1572:
158	addi.l	r15, 8, r15
1593:
160	pt/l	.L_pass, tr0
161	blink	tr0, r63
162
163.L_pop_f:
164	pt/l	.L_pop_f_tbl, tr1
165	pt/l	5f, tr2
166	gettr	tr1, r20
167	bge/l	r23, r63, tr2
168	add	r1, r63, r23
169	shlli	r1, 3, r21
170	addi	r1, 2, r1
171	add	r20, r21, r20
172	ptabs/l	r20, tr1
173	blink	tr1, r63
1745:
175	addi	r23, 1, r21
176	movi	-1, r23
177	shlli	r21, 3, r21
178	add	r20, r21, r20
179	ptabs/l	r20, tr1
180	blink	tr1, r63
181
182.L_pop_f_tbl:
183	fld.s	r15, OFS_FLT, fr0
184	blink	tr0, r63
185	fld.s	r15, OFS_FLT, fr1
186	blink	tr0, r63
187	fld.s	r15, OFS_FLT, fr2
188	blink	tr0, r63
189	fld.s	r15, OFS_FLT, fr3
190	blink	tr0, r63
191	fld.s	r15, OFS_FLT, fr4
192	blink	tr0, r63
193	fld.s	r15, OFS_FLT, fr5
194	blink	tr0, r63
195	fld.s	r15, OFS_FLT, fr6
196	blink	tr0, r63
197	fld.s	r15, OFS_FLT, fr7
198	blink	tr0, r63
199	fld.s	r15, OFS_FLT, fr8
200	blink	tr0, r63
201	fld.s	r15, OFS_FLT, fr9
202	blink	tr0, r63
203	fld.s	r15, OFS_FLT, fr10
204	blink	tr0, r63
205	fld.s	r15, OFS_FLT, fr11
206	blink	tr0, r63
207
208.L_pass_i:
209	pt/l	3f, tr0
210	movi	8, r20
211	bge/l	r0, r20, tr0
212
213	pt/l	.L_pop_i, tr1
214	pt/l	2f, tr0
215	blink	tr1, r63
2162:
217	addi.l	r15, 8, r15
2183:
219	pt/l	.L_pass, tr0
220	addi	r0, 1, r0
221	blink	tr0, r63
222
223.L_pop_i:
224	pt/l	.L_pop_i_tbl, tr1
225	gettr	tr1, r20
226	shlli	r0, 3, r21
227	add	r20, r21, r20
228	ptabs/l	r20, tr1
229	blink	tr1, r63
230
231.L_pop_i_tbl:
232	ld.q	r15, 0, r2
233	blink	tr0, r63
234	ld.q	r15, 0, r3
235	blink	tr0, r63
236	ld.q	r15, 0, r4
237	blink	tr0, r63
238	ld.q	r15, 0, r5
239	blink	tr0, r63
240	ld.q	r15, 0, r6
241	blink	tr0, r63
242	ld.q	r15, 0, r7
243	blink	tr0, r63
244	ld.q	r15, 0, r8
245	blink	tr0, r63
246	ld.q	r15, 0, r9
247	blink	tr0, r63
248
249.L_call_it:
250	# call function
251	pt/l	1f, tr1
252	bnei/l	r29, FFI_TYPE_STRUCT, tr1
253	add	r19, r63, r2
2541:
255	add	r22, r63, r15
256	ptabs/l	r32, tr0
257	blink	tr0, r18
258
259	pt/l	.L_ret_i, tr0
260	pt/l	.L_ret_ll, tr1
261	pt/l	.L_ret_d, tr2
262	pt/l	.L_ret_f, tr3
263	pt/l	.L_epilogue, tr4
264
265	beqi/l	r29, FFI_TYPE_INT, tr0
266	beqi/l	r29, FFI_TYPE_UINT32, tr0
267	beqi/l	r29, FFI_TYPE_SINT64, tr1
268	beqi/l	r29, FFI_TYPE_UINT64, tr1
269	beqi/l	r29, FFI_TYPE_DOUBLE, tr2
270	beqi/l	r29, FFI_TYPE_FLOAT, tr3
271
272	pt/l	.L_ret_q, tr0
273	pt/l	.L_ret_h, tr1
274
275	beqi/l	r29, FFI_TYPE_UINT8, tr0
276	beqi/l	r29, FFI_TYPE_UINT16, tr1
277	blink	tr4, r63
278
279.L_ret_d:
280	fst.d	r31, 0, dr0
281	blink	tr4, r63
282
283.L_ret_ll:
284	st.q	r31, 0, r2
285	blink	tr4, r63
286
287.L_ret_f:
288	fst.s	r31, OFS_FLT, fr0
289	blink	tr4, r63
290
291.L_ret_q:
292	st.b	r31, 0, r2
293	blink	tr4, r63
294
295.L_ret_h:
296	st.w	r31, 0, r2
297	blink	tr4, r63
298
299.L_ret_i:
300	st.l	r31, 0, r2
301	# Fall
302
303.L_epilogue:
304	# Remove the space we pushed for the args
305	add	r14, r63, r15
306
307	ld.l	r15, 0, r14
308	ld.l	r15, 4, r18
309	ld.q	r15, 8, r28
310	ld.q	r15, 16, r29
311	ld.q	r15, 24, r30
312	ld.q	r15, 32, r31
313	ld.q	r15, 40, r32
314	addi.l	r15, 48, r15
315	ptabs	r18, tr0
316	blink	tr0, r63
317
318.LFE1:
319.ffi_call_SYSV_end:
320	.size	 CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
321
322	.align	5
323ENTRY(ffi_closure_SYSV)
324.LFB2:
325	addi.l	r15, -136, r15
326.LCFI3:
327	st.l	r15, 12, r18
328	st.l	r15, 8, r14
329	st.l	r15, 4, r12
330.LCFI4:
331	add	r15, r63, r14
332.LCFI5:
333	/* Stack layout:
334	   ...
335	   64 bytes (register parameters)
336	   48 bytes (floating register parameters)
337	    8 bytes (result)
338	    4 bytes (r18)
339	    4 bytes (r14)
340	    4 bytes (r12)
341	    4 bytes (for align)
342	   <- new stack pointer
343	*/
344	fst.d	r14, 24, dr0
345	fst.d	r14, 32, dr2
346	fst.d	r14, 40, dr4
347	fst.d	r14, 48, dr6
348	fst.d	r14, 56, dr8
349	fst.d	r14, 64, dr10
350	st.q	r14, 72, r2
351	st.q	r14, 80, r3
352	st.q	r14, 88, r4
353	st.q	r14, 96, r5
354	st.q	r14, 104, r6
355	st.q	r14, 112, r7
356	st.q	r14, 120, r8
357	st.q	r14, 128, r9
358
359	add	r1, r63, r2
360	addi	r14, 16, r3
361	addi	r14, 72, r4
362	addi	r14, 24, r5
363	addi	r14, 136, r6
364#ifdef PIC
365	movi	(((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
366        shori	((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
367.LPCS0:	ptrel/u r12, tr0
368	movi	((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
369	gettr	tr0, r12
370	ldx.l	r1, r12, r1
371	ptabs	r1, tr0
372#else
373	pt/l	ffi_closure_helper_SYSV, tr0
374#endif
375	blink	tr0, r18
376
377	shlli	r2, 1, r1
378        movi    (((datalabel .L_table) >> 16) & 65535), r2
379        shori   ((datalabel .L_table) & 65535), r2
380        ldx.w   r2, r1, r1
381        add     r1, r2, r1
382	pt/l	.L_case_v, tr1
383        ptabs   r1, tr0
384        blink   tr0, r63
385
386        .align 2
387.L_table:
388	.word	.L_case_v - datalabel .L_table	/* FFI_TYPE_VOID */
389	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_INT */
390	.word	.L_case_f - datalabel .L_table	/* FFI_TYPE_FLOAT */
391	.word	.L_case_d - datalabel .L_table	/* FFI_TYPE_DOUBLE */
392	.word	.L_case_d - datalabel .L_table	/* FFI_TYPE_LONGDOUBLE */
393	.word	.L_case_uq - datalabel .L_table	/* FFI_TYPE_UINT8 */
394	.word	.L_case_q - datalabel .L_table	/* FFI_TYPE_SINT8 */
395	.word	.L_case_uh - datalabel .L_table	/* FFI_TYPE_UINT16 */
396	.word	.L_case_h - datalabel .L_table	/* FFI_TYPE_SINT16 */
397	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_UINT32 */
398	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_SINT32 */
399	.word	.L_case_ll - datalabel .L_table	/* FFI_TYPE_UINT64 */
400	.word	.L_case_ll - datalabel .L_table	/* FFI_TYPE_SINT64 */
401	.word	.L_case_v - datalabel .L_table	/* FFI_TYPE_STRUCT */
402	.word	.L_case_i - datalabel .L_table	/* FFI_TYPE_POINTER */
403
404        .align 2
405.L_case_d:
406	fld.d	r14, 16, dr0
407	blink	tr1, r63
408.L_case_f:
409	fld.s	r14, 16, fr0
410	blink	tr1, r63
411.L_case_ll:
412	ld.q	r14, 16, r2
413	blink	tr1, r63
414.L_case_i:
415	ld.l	r14, 16, r2
416	blink	tr1, r63
417.L_case_q:
418	ld.b	r14, 16, r2
419	blink	tr1, r63
420.L_case_uq:
421	ld.ub	r14, 16, r2
422	blink	tr1, r63
423.L_case_h:
424	ld.w	r14, 16, r2
425	blink	tr1, r63
426.L_case_uh:
427	ld.uw	r14, 16, r2
428	blink	tr1, r63
429.L_case_v:
430	add.l	r14, r63, r15
431	ld.l	r15, 4, r12
432	ld.l	r15, 8, r14
433	ld.l	r15, 12, r18
434	addi.l	r15, 136, r15
435	ptabs	r18, tr0
436	blink	tr0, r63
437
438.LFE2:
439.ffi_closure_SYSV_end:
440	.size	 CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
441
442#if defined __ELF__ && defined __linux__
443	.section	.note.GNU-stack,"",@progbits
444#endif
445
446	.section	".eh_frame","aw",@progbits
447__FRAME_BEGIN__:
448	.4byte	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
449.LSCIE1:
450	.4byte	0x0	/* CIE Identifier Tag */
451	.byte	0x1	/* CIE Version */
452#ifdef PIC
453	.ascii "zR\0"	/* CIE Augmentation */
454#else
455	.byte	0x0	/* CIE Augmentation */
456#endif
457	.uleb128 0x1	/* CIE Code Alignment Factor */
458	.sleb128 -4	/* CIE Data Alignment Factor */
459	.byte	0x12	/* CIE RA Column */
460#ifdef PIC
461	.uleb128 0x1	/* Augmentation size */
462	.byte	0x10	/* FDE Encoding (pcrel) */
463#endif
464	.byte	0xc	/* DW_CFA_def_cfa */
465	.uleb128 0xf
466	.uleb128 0x0
467	.align	2
468.LECIE1:
469.LSFDE1:
470	.4byte	datalabel .LEFDE1-datalabel .LASFDE1	/* FDE Length */
471.LASFDE1:
472	.4byte	datalabel .LASFDE1-datalabel __FRAME_BEGIN__
473#ifdef PIC
474	.4byte	.LFB1-.	/* FDE initial location */
475#else
476	.4byte	.LFB1	/* FDE initial location */
477#endif
478	.4byte	datalabel .LFE1-datalabel .LFB1	/* FDE address range */
479#ifdef PIC
480	.uleb128 0x0	/* Augmentation size */
481#endif
482	.byte	0x4	/* DW_CFA_advance_loc4 */
483	.4byte	datalabel .LCFI0-datalabel .LFB1
484	.byte	0xe	/* DW_CFA_def_cfa_offset */
485	.uleb128 0x30
486	.byte	0x4	/* DW_CFA_advance_loc4 */
487	.4byte	datalabel .LCFI1-datalabel .LCFI0
488	.byte   0x8e	/* DW_CFA_offset, column 0xe */
489	.uleb128 0xc
490	.byte   0x92	/* DW_CFA_offset, column 0x12 */
491	.uleb128 0xb
492	.byte   0x9c	/* DW_CFA_offset, column 0x1c */
493	.uleb128 0xa
494	.byte   0x9d	/* DW_CFA_offset, column 0x1d */
495	.uleb128 0x8
496	.byte   0x9e	/* DW_CFA_offset, column 0x1e */
497	.uleb128 0x6
498	.byte   0x9f	/* DW_CFA_offset, column 0x1f */
499	.uleb128 0x4
500	.byte   0xa0	/* DW_CFA_offset, column 0x20 */
501	.uleb128 0x2
502	.byte	0x4	/* DW_CFA_advance_loc4 */
503	.4byte	datalabel .LCFI2-datalabel .LCFI1
504	.byte	0xd	/* DW_CFA_def_cfa_register */
505	.uleb128 0xe
506	.align	2
507.LEFDE1:
508
509.LSFDE3:
510	.4byte	datalabel .LEFDE3-datalabel .LASFDE3	/* FDE Length */
511.LASFDE3:
512	.4byte	datalabel .LASFDE3-datalabel __FRAME_BEGIN__
513#ifdef PIC
514	.4byte	.LFB2-.	/* FDE initial location */
515#else
516	.4byte	.LFB2	/* FDE initial location */
517#endif
518	.4byte	datalabel .LFE2-datalabel .LFB2	/* FDE address range */
519#ifdef PIC
520	.uleb128 0x0	/* Augmentation size */
521#endif
522	.byte	0x4	/* DW_CFA_advance_loc4 */
523	.4byte	datalabel .LCFI3-datalabel .LFB2
524	.byte	0xe	/* DW_CFA_def_cfa_offset */
525	.uleb128 0x88
526	.byte	0x4	/* DW_CFA_advance_loc4 */
527	.4byte	datalabel .LCFI4-datalabel .LCFI3
528	.byte   0x8c	/* DW_CFA_offset, column 0xc */
529	.uleb128 0x21
530	.byte   0x8e	/* DW_CFA_offset, column 0xe */
531	.uleb128 0x20
532	.byte   0x92	/* DW_CFA_offset, column 0x12 */
533	.uleb128 0x1f
534	.byte	0x4	/* DW_CFA_advance_loc4 */
535	.4byte	datalabel .LCFI5-datalabel .LCFI4
536	.byte	0xd	/* DW_CFA_def_cfa_register */
537	.uleb128 0xe
538	.align	2
539.LEFDE3:
540