• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* -----------------------------------------------------------------------
2   unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
3            Copyright (c) 2000 Hewlett Packard Company
4
5   IA64/unix Foreign Function Interface
6
7   Primary author: Hans Boehm, HP Labs
8
9   Loosely modeled on Cygnus code for other platforms.
10
11   Permission is hereby granted, free of charge, to any person obtaining
12   a copy of this software and associated documentation files (the
13   ``Software''), to deal in the Software without restriction, including
14   without limitation the rights to use, copy, modify, merge, publish,
15   distribute, sublicense, and/or sell copies of the Software, and to
16   permit persons to whom the Software is furnished to do so, subject to
17   the following conditions:
18
19   The above copyright notice and this permission notice shall be included
20   in all copies or substantial portions of the Software.
21
22   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
23   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29   DEALINGS IN THE SOFTWARE.
30   ----------------------------------------------------------------------- */
31
32#define LIBFFI_ASM
33#include <fficonfig.h>
34#include <ffi.h>
35#include "ia64_flags.h"
36
37	.pred.safe_across_calls p1-p5,p16-p63
38.text
39
40/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
41		      void (*fn)(void), int flags);
42 */
43
44        .align 16
45        .global	ffi_call_unix
46        .proc	ffi_call_unix
47ffi_call_unix:
48	.prologue
49	/* Bit o trickiness.  We actually share a stack frame with ffi_call.
50	   Rely on the fact that ffi_call uses a vframe and don't bother
51	   tracking one here at all.  */
52	.fframe	0
53	.save	ar.pfs, r36 // loc0
54	alloc   loc0 = ar.pfs, 4, 3, 8, 0
55	.save	rp, loc1
56	mov 	loc1 = b0
57	.body
58	add	r16 = 16, in0
59	mov	loc2 = gp
60	mov	r8 = in1
61	;;
62
63	/* Load up all of the argument registers.  */
64	ldf.fill f8 = [in0], 32
65	ldf.fill f9 = [r16], 32
66	;;
67	ldf.fill f10 = [in0], 32
68	ldf.fill f11 = [r16], 32
69	;;
70	ldf.fill f12 = [in0], 32
71	ldf.fill f13 = [r16], 32
72	;;
73	ldf.fill f14 = [in0], 32
74	ldf.fill f15 = [r16], 24
75	;;
76	ld8	out0 = [in0], 16
77	ld8	out1 = [r16], 16
78	;;
79	ld8	out2 = [in0], 16
80	ld8	out3 = [r16], 16
81	;;
82	ld8	out4 = [in0], 16
83	ld8	out5 = [r16], 16
84	;;
85	ld8	out6 = [in0]
86	ld8	out7 = [r16]
87	;;
88
89	/* Deallocate the register save area from the stack frame.  */
90	mov	sp = in0
91
92	/* Call the target function.  */
93	ld8	r16 = [in2], 8
94	;;
95	ld8	gp = [in2]
96	mov	b6 = r16
97	br.call.sptk.many b0 = b6
98	;;
99
100	/* Dispatch to handle return value.  */
101	mov	gp = loc2
102	zxt1	r16 = in3
103	;;
104	mov	ar.pfs = loc0
105	addl	r18 = @ltoffx(.Lst_table), gp
106	;;
107	ld8.mov	r18 = [r18], .Lst_table
108	mov	b0 = loc1
109	;;
110	shladd	r18 = r16, 3, r18
111	;;
112	ld8	r17 = [r18]
113	shr	in3 = in3, 8
114	;;
115	add	r17 = r17, r18
116	;;
117	mov	b6 = r17
118	br	b6
119	;;
120
121.Lst_void:
122	br.ret.sptk.many b0
123	;;
124.Lst_uint8:
125	zxt1	r8 = r8
126	;;
127	st8	[in1] = r8
128	br.ret.sptk.many b0
129	;;
130.Lst_sint8:
131	sxt1	r8 = r8
132	;;
133	st8	[in1] = r8
134	br.ret.sptk.many b0
135	;;
136.Lst_uint16:
137	zxt2	r8 = r8
138	;;
139	st8	[in1] = r8
140	br.ret.sptk.many b0
141	;;
142.Lst_sint16:
143	sxt2	r8 = r8
144	;;
145	st8	[in1] = r8
146	br.ret.sptk.many b0
147	;;
148.Lst_uint32:
149	zxt4	r8 = r8
150	;;
151	st8	[in1] = r8
152	br.ret.sptk.many b0
153	;;
154.Lst_sint32:
155	sxt4	r8 = r8
156	;;
157	st8	[in1] = r8
158	br.ret.sptk.many b0
159	;;
160.Lst_int64:
161	st8	[in1] = r8
162	br.ret.sptk.many b0
163	;;
164.Lst_float:
165	stfs	[in1] = f8
166	br.ret.sptk.many b0
167	;;
168.Lst_double:
169	stfd	[in1] = f8
170	br.ret.sptk.many b0
171	;;
172.Lst_ldouble:
173	stfe	[in1] = f8
174	br.ret.sptk.many b0
175	;;
176
177.Lst_small_struct:
178	cmp.lt	p6, p0 = 8, in3
179	cmp.lt	p7, p0 = 16, in3
180	cmp.lt	p8, p0 = 24, in3
181	;;
182	add	r16 = 8, sp
183	add	r17 = 16, sp
184	add	r18 = 24, sp
185	;;
186	st8	[sp] = r8
187(p6)	st8	[r16] = r9
188	mov	out0 = in1
189(p7)	st8	[r17] = r10
190(p8)	st8	[r18] = r11
191	mov	out1 = sp
192	mov	out2 = in3
193	;;
194	// ia64 software calling convention requires
195	// top 16 bytes of stack to be scratch space
196	// PLT resolver uses that scratch space at
197	// 'memcpy' symbol reolution time
198	add	sp = -16, sp
199	br.call.sptk.many b0 = memcpy#
200	;;
201	mov	ar.pfs = loc0
202	mov	b0 = loc1
203	mov	gp = loc2
204	br.ret.sptk.many b0
205
206.Lst_hfa_float:
207	add	r16 = 4, in1
208	cmp.lt	p6, p0 = 4, in3
209	;;
210	stfs	[in1] = f8, 8
211(p6)	stfs	[r16] = f9, 8
212	cmp.lt	p7, p0 = 8, in3
213	cmp.lt	p8, p0 = 12, in3
214	;;
215(p7)	stfs	[in1] = f10, 8
216(p8)	stfs	[r16] = f11, 8
217	cmp.lt	p9, p0 = 16, in3
218	cmp.lt	p10, p0 = 20, in3
219	;;
220(p9)	stfs	[in1] = f12, 8
221(p10)	stfs	[r16] = f13, 8
222	cmp.lt	p6, p0 = 24, in3
223	cmp.lt	p7, p0 = 28, in3
224	;;
225(p6)	stfs	[in1] = f14
226(p7)	stfs	[r16] = f15
227	br.ret.sptk.many b0
228	;;
229
230.Lst_hfa_double:
231	add	r16 = 8, in1
232	cmp.lt	p6, p0 = 8, in3
233	;;
234	stfd	[in1] = f8, 16
235(p6)	stfd	[r16] = f9, 16
236	cmp.lt	p7, p0 = 16, in3
237	cmp.lt	p8, p0 = 24, in3
238	;;
239(p7)	stfd	[in1] = f10, 16
240(p8)	stfd	[r16] = f11, 16
241	cmp.lt	p9, p0 = 32, in3
242	cmp.lt	p10, p0 = 40, in3
243	;;
244(p9)	stfd	[in1] = f12, 16
245(p10)	stfd	[r16] = f13, 16
246	cmp.lt	p6, p0 = 48, in3
247	cmp.lt	p7, p0 = 56, in3
248	;;
249(p6)	stfd	[in1] = f14
250(p7)	stfd	[r16] = f15
251	br.ret.sptk.many b0
252	;;
253
254.Lst_hfa_ldouble:
255	add	r16 = 16, in1
256	cmp.lt	p6, p0 = 16, in3
257	;;
258	stfe	[in1] = f8, 32
259(p6)	stfe	[r16] = f9, 32
260	cmp.lt	p7, p0 = 32, in3
261	cmp.lt	p8, p0 = 48, in3
262	;;
263(p7)	stfe	[in1] = f10, 32
264(p8)	stfe	[r16] = f11, 32
265	cmp.lt	p9, p0 = 64, in3
266	cmp.lt	p10, p0 = 80, in3
267	;;
268(p9)	stfe	[in1] = f12, 32
269(p10)	stfe	[r16] = f13, 32
270	cmp.lt	p6, p0 = 96, in3
271	cmp.lt	p7, p0 = 112, in3
272	;;
273(p6)	stfe	[in1] = f14
274(p7)	stfe	[r16] = f15
275	br.ret.sptk.many b0
276	;;
277
278        .endp ffi_call_unix
279
280        .align 16
281        .global ffi_closure_unix
282        .proc ffi_closure_unix
283
284#define FRAME_SIZE	(8*16 + 8*8 + 8*16)
285
286ffi_closure_unix:
287	.prologue
288	.save	ar.pfs, r40 // loc0
289	alloc   loc0 = ar.pfs, 8, 4, 4, 0
290	.fframe	FRAME_SIZE
291	add	r12 = -FRAME_SIZE, r12
292	.save	rp, loc1
293	mov	loc1 = b0
294	.save	ar.unat, loc2
295	mov	loc2 = ar.unat
296	.body
297
298	/* Retrieve closure pointer and real gp.  */
299#ifdef _ILP32
300	addp4	out0 = 0, gp
301	addp4	gp = 16, gp
302#else
303	mov	out0 = gp
304	add	gp = 16, gp
305#endif
306	;;
307	ld8	gp = [gp]
308
309	/* Spill all of the possible argument registers.  */
310	add	r16 = 16 + 8*16, sp
311	add	r17 = 16 + 8*16 + 16, sp
312	;;
313	stf.spill [r16] = f8, 32
314	stf.spill [r17] = f9, 32
315	mov	loc3 = gp
316	;;
317	stf.spill [r16] = f10, 32
318	stf.spill [r17] = f11, 32
319	;;
320	stf.spill [r16] = f12, 32
321	stf.spill [r17] = f13, 32
322	;;
323	stf.spill [r16] = f14, 32
324	stf.spill [r17] = f15, 24
325	;;
326	.mem.offset 0, 0
327	st8.spill [r16] = in0, 16
328	.mem.offset 8, 0
329	st8.spill [r17] = in1, 16
330	add	out1 = 16 + 8*16, sp
331	;;
332	.mem.offset 0, 0
333	st8.spill [r16] = in2, 16
334	.mem.offset 8, 0
335	st8.spill [r17] = in3, 16
336	add	out2 = 16, sp
337	;;
338	.mem.offset 0, 0
339	st8.spill [r16] = in4, 16
340	.mem.offset 8, 0
341	st8.spill [r17] = in5, 16
342	mov	out3 = r8
343	;;
344	.mem.offset 0, 0
345	st8.spill [r16] = in6
346	.mem.offset 8, 0
347	st8.spill [r17] = in7
348
349	/* Invoke ffi_closure_unix_inner for the hard work.  */
350	br.call.sptk.many b0 = ffi_closure_unix_inner
351	;;
352
353	/* Dispatch to handle return value.  */
354	mov	gp = loc3
355	zxt1	r16 = r8
356	;;
357	addl	r18 = @ltoffx(.Lld_table), gp
358	mov	ar.pfs = loc0
359	;;
360	ld8.mov	r18 = [r18], .Lld_table
361	mov	b0 = loc1
362	;;
363	shladd	r18 = r16, 3, r18
364	mov	ar.unat = loc2
365	;;
366	ld8	r17 = [r18]
367	shr	r8 = r8, 8
368	;;
369	add	r17 = r17, r18
370	add	r16 = 16, sp
371	;;
372	mov	b6 = r17
373	br	b6
374	;;
375	.label_state 1
376
377.Lld_void:
378	.restore sp
379	add	sp = FRAME_SIZE, sp
380	br.ret.sptk.many b0
381	;;
382.Lld_int:
383	.body
384	.copy_state 1
385	ld8	r8 = [r16]
386	.restore sp
387	add	sp = FRAME_SIZE, sp
388	br.ret.sptk.many b0
389	;;
390.Lld_float:
391	.body
392	.copy_state 1
393	ldfs	f8 = [r16]
394	.restore sp
395	add	sp = FRAME_SIZE, sp
396	br.ret.sptk.many b0
397	;;
398.Lld_double:
399	.body
400	.copy_state 1
401	ldfd	f8 = [r16]
402	.restore sp
403	add	sp = FRAME_SIZE, sp
404	br.ret.sptk.many b0
405	;;
406.Lld_ldouble:
407	.body
408	.copy_state 1
409	ldfe	f8 = [r16]
410	.restore sp
411	add	sp = FRAME_SIZE, sp
412	br.ret.sptk.many b0
413	;;
414
415.Lld_small_struct:
416	.body
417	.copy_state 1
418	add	r17 = 8, r16
419	cmp.lt	p6, p0 = 8, r8
420	cmp.lt	p7, p0 = 16, r8
421	cmp.lt	p8, p0 = 24, r8
422	;;
423	ld8	r8 = [r16], 16
424(p6)	ld8	r9 = [r17], 16
425	;;
426(p7)	ld8	r10 = [r16]
427(p8)	ld8	r11 = [r17]
428	.restore sp
429	add	sp = FRAME_SIZE, sp
430	br.ret.sptk.many b0
431	;;
432
433.Lld_hfa_float:
434	.body
435	.copy_state 1
436	add	r17 = 4, r16
437	cmp.lt	p6, p0 = 4, r8
438	;;
439	ldfs	f8 = [r16], 8
440(p6)	ldfs	f9 = [r17], 8
441	cmp.lt	p7, p0 = 8, r8
442	cmp.lt	p8, p0 = 12, r8
443	;;
444(p7)	ldfs	f10 = [r16], 8
445(p8)	ldfs	f11 = [r17], 8
446	cmp.lt	p9, p0 = 16, r8
447	cmp.lt	p10, p0 = 20, r8
448	;;
449(p9)	ldfs	f12 = [r16], 8
450(p10)	ldfs	f13 = [r17], 8
451	cmp.lt	p6, p0 = 24, r8
452	cmp.lt	p7, p0 = 28, r8
453	;;
454(p6)	ldfs	f14 = [r16]
455(p7)	ldfs	f15 = [r17]
456	.restore sp
457	add	sp = FRAME_SIZE, sp
458	br.ret.sptk.many b0
459	;;
460
461.Lld_hfa_double:
462	.body
463	.copy_state 1
464	add	r17 = 8, r16
465	cmp.lt	p6, p0 = 8, r8
466	;;
467	ldfd	f8 = [r16], 16
468(p6)	ldfd	f9 = [r17], 16
469	cmp.lt	p7, p0 = 16, r8
470	cmp.lt	p8, p0 = 24, r8
471	;;
472(p7)	ldfd	f10 = [r16], 16
473(p8)	ldfd	f11 = [r17], 16
474	cmp.lt	p9, p0 = 32, r8
475	cmp.lt	p10, p0 = 40, r8
476	;;
477(p9)	ldfd	f12 = [r16], 16
478(p10)	ldfd	f13 = [r17], 16
479	cmp.lt	p6, p0 = 48, r8
480	cmp.lt	p7, p0 = 56, r8
481	;;
482(p6)	ldfd	f14 = [r16]
483(p7)	ldfd	f15 = [r17]
484	.restore sp
485	add	sp = FRAME_SIZE, sp
486	br.ret.sptk.many b0
487	;;
488
489.Lld_hfa_ldouble:
490	.body
491	.copy_state 1
492	add	r17 = 16, r16
493	cmp.lt	p6, p0 = 16, r8
494	;;
495	ldfe	f8 = [r16], 32
496(p6)	ldfe	f9 = [r17], 32
497	cmp.lt	p7, p0 = 32, r8
498	cmp.lt	p8, p0 = 48, r8
499	;;
500(p7)	ldfe	f10 = [r16], 32
501(p8)	ldfe	f11 = [r17], 32
502	cmp.lt	p9, p0 = 64, r8
503	cmp.lt	p10, p0 = 80, r8
504	;;
505(p9)	ldfe	f12 = [r16], 32
506(p10)	ldfe	f13 = [r17], 32
507	cmp.lt	p6, p0 = 96, r8
508	cmp.lt	p7, p0 = 112, r8
509	;;
510(p6)	ldfe	f14 = [r16]
511(p7)	ldfe	f15 = [r17]
512	.restore sp
513	add	sp = FRAME_SIZE, sp
514	br.ret.sptk.many b0
515	;;
516
517	.endp	ffi_closure_unix
518
519	.section .rodata
520	.align	8
521.Lst_table:
522	data8	@pcrel(.Lst_void)		// FFI_TYPE_VOID
523	data8	@pcrel(.Lst_sint32)		// FFI_TYPE_INT
524	data8	@pcrel(.Lst_float)		// FFI_TYPE_FLOAT
525	data8	@pcrel(.Lst_double)		// FFI_TYPE_DOUBLE
526	data8	@pcrel(.Lst_ldouble)		// FFI_TYPE_LONGDOUBLE
527	data8	@pcrel(.Lst_uint8)		// FFI_TYPE_UINT8
528	data8	@pcrel(.Lst_sint8)		// FFI_TYPE_SINT8
529	data8	@pcrel(.Lst_uint16)		// FFI_TYPE_UINT16
530	data8	@pcrel(.Lst_sint16)		// FFI_TYPE_SINT16
531	data8	@pcrel(.Lst_uint32)		// FFI_TYPE_UINT32
532	data8	@pcrel(.Lst_sint32)		// FFI_TYPE_SINT32
533	data8	@pcrel(.Lst_int64)		// FFI_TYPE_UINT64
534	data8	@pcrel(.Lst_int64)		// FFI_TYPE_SINT64
535	data8	@pcrel(.Lst_void)		// FFI_TYPE_STRUCT
536	data8	@pcrel(.Lst_int64)		// FFI_TYPE_POINTER
537	data8	@pcrel(.Lst_void)		// FFI_TYPE_COMPLEX (not implemented)
538	data8 	@pcrel(.Lst_small_struct)	// FFI_IA64_TYPE_SMALL_STRUCT
539	data8	@pcrel(.Lst_hfa_float)		// FFI_IA64_TYPE_HFA_FLOAT
540	data8	@pcrel(.Lst_hfa_double)		// FFI_IA64_TYPE_HFA_DOUBLE
541	data8	@pcrel(.Lst_hfa_ldouble)	// FFI_IA64_TYPE_HFA_LDOUBLE
542
543.Lld_table:
544	data8	@pcrel(.Lld_void)		// FFI_TYPE_VOID
545	data8	@pcrel(.Lld_int)		// FFI_TYPE_INT
546	data8	@pcrel(.Lld_float)		// FFI_TYPE_FLOAT
547	data8	@pcrel(.Lld_double)		// FFI_TYPE_DOUBLE
548	data8	@pcrel(.Lld_ldouble)		// FFI_TYPE_LONGDOUBLE
549	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT8
550	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT8
551	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT16
552	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT16
553	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT32
554	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT32
555	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT64
556	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT64
557	data8	@pcrel(.Lld_void)		// FFI_TYPE_STRUCT
558	data8	@pcrel(.Lld_int)		// FFI_TYPE_POINTER
559	data8	@pcrel(.Lld_void)		// FFI_TYPE_COMPLEX (not implemented)
560	data8 	@pcrel(.Lld_small_struct)	// FFI_IA64_TYPE_SMALL_STRUCT
561	data8	@pcrel(.Lld_hfa_float)		// FFI_IA64_TYPE_HFA_FLOAT
562	data8	@pcrel(.Lld_hfa_double)		// FFI_IA64_TYPE_HFA_DOUBLE
563	data8	@pcrel(.Lld_hfa_ldouble)	// FFI_IA64_TYPE_HFA_LDOUBLE
564
565#if defined __ELF__ && defined __linux__
566	.section	.note.GNU-stack,"",@progbits
567#endif
568