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