1 /* -----------------------------------------------------------------------
2 unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
3 Copyright (c) 2000 Hewlett Packard Company
5 IA64/unix Foreign Function Interface
7 Primary author: Hans Boehm, HP Labs
9 Loosely modeled on Cygnus code for other platforms.
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:
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
33 #include <fficonfig.h>
35 #include "ia64_flags.h"
37 .pred.safe_across_calls p1-p5,p16-p63
40 /* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
41 void (*fn)(void), int flags);
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. */
53 .save ar.pfs, r36 // loc0
54 alloc loc0 = ar.pfs, 4, 3, 8, 0
63 /* Load up all of the argument registers. */
64 ldf.fill f8 = [in0], 32
65 ldf.fill f9 = [r16], 32
67 ldf.fill f10 = [in0], 32
68 ldf.fill f11 = [r16], 32
70 ldf.fill f12 = [in0], 32
71 ldf.fill f13 = [r16], 32
73 ldf.fill f14 = [in0], 32
74 ldf.fill f15 = [r16], 24
89 /* Deallocate the register save area from the stack frame. */
92 /* Call the target function. */
97 br.call.sptk.many b0 = b6
100 /* Dispatch to handle return value. */
105 addl r18 = @ltoffx(.Lst_table), gp
107 ld8.mov r18 = [r18], .Lst_table
110 shladd r18 = r16, 3, r18
179 cmp.lt p6, p0 = 8, in3
180 cmp.lt p7, p0 = 16, in3
181 cmp.lt p8, p0 = 24, in3
194 br.call.sptk.many b0 = memcpy#
203 cmp.lt p6, p0 = 4, in3
206 (p6) stfs [r16] = f9, 8
207 cmp.lt p7, p0 = 8, in3
208 cmp.lt p8, p0 = 12, in3
210 (p7) stfs [in1] = f10, 8
211 (p8) stfs [r16] = f11, 8
212 cmp.lt p9, p0 = 16, in3
213 cmp.lt p10, p0 = 20, in3
215 (p9) stfs [in1] = f12, 8
216 (p10) stfs [r16] = f13, 8
217 cmp.lt p6, p0 = 24, in3
218 cmp.lt p7, p0 = 28, in3
220 (p6) stfs [in1] = f14
221 (p7) stfs [r16] = f15
227 cmp.lt p6, p0 = 8, in3
230 (p6) stfd [r16] = f9, 16
231 cmp.lt p7, p0 = 16, in3
232 cmp.lt p8, p0 = 24, in3
234 (p7) stfd [in1] = f10, 16
235 (p8) stfd [r16] = f11, 16
236 cmp.lt p9, p0 = 32, in3
237 cmp.lt p10, p0 = 40, in3
239 (p9) stfd [in1] = f12, 16
240 (p10) stfd [r16] = f13, 16
241 cmp.lt p6, p0 = 48, in3
242 cmp.lt p7, p0 = 56, in3
244 (p6) stfd [in1] = f14
245 (p7) stfd [r16] = f15
251 cmp.lt p6, p0 = 16, in3
254 (p6) stfe [r16] = f9, 32
255 cmp.lt p7, p0 = 32, in3
256 cmp.lt p8, p0 = 48, in3
258 (p7) stfe [in1] = f10, 32
259 (p8) stfe [r16] = f11, 32
260 cmp.lt p9, p0 = 64, in3
261 cmp.lt p10, p0 = 80, in3
263 (p9) stfe [in1] = f12, 32
264 (p10) stfe [r16] = f13, 32
265 cmp.lt p6, p0 = 96, in3
266 cmp.lt p7, p0 = 112, in3
268 (p6) stfe [in1] = f14
269 (p7) stfe [r16] = f15
276 .global ffi_closure_unix
277 .proc ffi_closure_unix
279 #define FRAME_SIZE (8*16 + 8*8 + 8*16)
283 .save ar.pfs, r40 // loc0
284 alloc loc0 = ar.pfs, 8, 4, 4, 0
286 add r12 = -FRAME_SIZE, r12
293 /* Retrieve closure pointer and real gp. */
304 /* Spill all of the possible argument registers. */
305 add r16 = 16 + 8*16, sp
306 add r17 = 16 + 8*16 + 16, sp
308 stf.spill [r16] = f8, 32
309 stf.spill [r17] = f9, 32
312 stf.spill [r16] = f10, 32
313 stf.spill [r17] = f11, 32
315 stf.spill [r16] = f12, 32
316 stf.spill [r17] = f13, 32
318 stf.spill [r16] = f14, 32
319 stf.spill [r17] = f15, 24
322 st8.spill [r16] = in0, 16
324 st8.spill [r17] = in1, 16
325 add out1 = 16 + 8*16, sp
328 st8.spill [r16] = in2, 16
330 st8.spill [r17] = in3, 16
334 st8.spill [r16] = in4, 16
336 st8.spill [r17] = in5, 16
340 st8.spill [r16] = in6
342 st8.spill [r17] = in7
344 /* Invoke ffi_closure_unix_inner for the hard work. */
345 br.call.sptk.many b0 = ffi_closure_unix_inner
348 /* Dispatch to handle return value. */
352 addl r18 = @ltoffx(.Lld_table), gp
355 ld8.mov r18 = [r18], .Lld_table
358 shladd r18 = r16, 3, r18
374 add sp = FRAME_SIZE, sp
382 add sp = FRAME_SIZE, sp
390 add sp = FRAME_SIZE, sp
398 add sp = FRAME_SIZE, sp
406 add sp = FRAME_SIZE, sp
414 cmp.lt p6, p0 = 8, r8
415 cmp.lt p7, p0 = 16, r8
416 cmp.lt p8, p0 = 24, r8
419 (p6) ld8 r9 = [r17], 16
424 add sp = FRAME_SIZE, sp
432 cmp.lt p6, p0 = 4, r8
435 (p6) ldfs f9 = [r17], 8
436 cmp.lt p7, p0 = 8, r8
437 cmp.lt p8, p0 = 12, r8
439 (p7) ldfs f10 = [r16], 8
440 (p8) ldfs f11 = [r17], 8
441 cmp.lt p9, p0 = 16, r8
442 cmp.lt p10, p0 = 20, r8
444 (p9) ldfs f12 = [r16], 8
445 (p10) ldfs f13 = [r17], 8
446 cmp.lt p6, p0 = 24, r8
447 cmp.lt p7, p0 = 28, r8
449 (p6) ldfs f14 = [r16]
450 (p7) ldfs f15 = [r17]
452 add sp = FRAME_SIZE, sp
460 cmp.lt p6, p0 = 8, r8
463 (p6) ldfd f9 = [r17], 16
464 cmp.lt p7, p0 = 16, r8
465 cmp.lt p8, p0 = 24, r8
467 (p7) ldfd f10 = [r16], 16
468 (p8) ldfd f11 = [r17], 16
469 cmp.lt p9, p0 = 32, r8
470 cmp.lt p10, p0 = 40, r8
472 (p9) ldfd f12 = [r16], 16
473 (p10) ldfd f13 = [r17], 16
474 cmp.lt p6, p0 = 48, r8
475 cmp.lt p7, p0 = 56, r8
477 (p6) ldfd f14 = [r16]
478 (p7) ldfd f15 = [r17]
480 add sp = FRAME_SIZE, sp
488 cmp.lt p6, p0 = 16, r8
491 (p6) ldfe f9 = [r17], 32
492 cmp.lt p7, p0 = 32, r8
493 cmp.lt p8, p0 = 48, r8
495 (p7) ldfe f10 = [r16], 32
496 (p8) ldfe f11 = [r17], 32
497 cmp.lt p9, p0 = 64, r8
498 cmp.lt p10, p0 = 80, r8
500 (p9) ldfe f12 = [r16], 32
501 (p10) ldfe f13 = [r17], 32
502 cmp.lt p6, p0 = 96, r8
503 cmp.lt p7, p0 = 112, r8
505 (p6) ldfe f14 = [r16]
506 (p7) ldfe f15 = [r17]
508 add sp = FRAME_SIZE, sp
512 .endp ffi_closure_unix
517 data8 @pcrel(.Lst_void) // FFI_TYPE_VOID
518 data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT
519 data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT
520 data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE
521 data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE
522 data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8
523 data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8
524 data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16
525 data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16
526 data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32
527 data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32
528 data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64
529 data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64
530 data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT
531 data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER
532 data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
533 data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
534 data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
535 data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
538 data8 @pcrel(.Lld_void) // FFI_TYPE_VOID
539 data8 @pcrel(.Lld_int) // FFI_TYPE_INT
540 data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT
541 data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE
542 data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE
543 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8
544 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8
545 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16
546 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16
547 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32
548 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32
549 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64
550 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64
551 data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT
552 data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER
553 data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
554 data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
555 data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
556 data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
558 #if defined __ELF__ && defined __linux__
559 .section .note.GNU-stack,"",@progbits