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
178 cmp.lt p6, p0 = 8, in3
179 cmp.lt p7, p0 = 16, in3
180 cmp.lt p8, p0 = 24, in3
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
199 br.call.sptk.many b0 = memcpy#
208 cmp.lt p6, p0 = 4, in3
211 (p6) stfs [r16] = f9, 8
212 cmp.lt p7, p0 = 8, in3
213 cmp.lt p8, p0 = 12, in3
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
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
225 (p6) stfs [in1] = f14
226 (p7) stfs [r16] = f15
232 cmp.lt p6, p0 = 8, in3
235 (p6) stfd [r16] = f9, 16
236 cmp.lt p7, p0 = 16, in3
237 cmp.lt p8, p0 = 24, in3
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
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
249 (p6) stfd [in1] = f14
250 (p7) stfd [r16] = f15
256 cmp.lt p6, p0 = 16, in3
259 (p6) stfe [r16] = f9, 32
260 cmp.lt p7, p0 = 32, in3
261 cmp.lt p8, p0 = 48, in3
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
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
273 (p6) stfe [in1] = f14
274 (p7) stfe [r16] = f15
281 .global ffi_closure_unix
282 .proc ffi_closure_unix
284 #define FRAME_SIZE (8*16 + 8*8 + 8*16)
288 .save ar.pfs, r40 // loc0
289 alloc loc0 = ar.pfs, 8, 4, 4, 0
291 add r12 = -FRAME_SIZE, r12
298 /* Retrieve closure pointer and real gp. */
309 /* Spill all of the possible argument registers. */
310 add r16 = 16 + 8*16, sp
311 add r17 = 16 + 8*16 + 16, sp
313 stf.spill [r16] = f8, 32
314 stf.spill [r17] = f9, 32
317 stf.spill [r16] = f10, 32
318 stf.spill [r17] = f11, 32
320 stf.spill [r16] = f12, 32
321 stf.spill [r17] = f13, 32
323 stf.spill [r16] = f14, 32
324 stf.spill [r17] = f15, 24
327 st8.spill [r16] = in0, 16
329 st8.spill [r17] = in1, 16
330 add out1 = 16 + 8*16, sp
333 st8.spill [r16] = in2, 16
335 st8.spill [r17] = in3, 16
339 st8.spill [r16] = in4, 16
341 st8.spill [r17] = in5, 16
345 st8.spill [r16] = in6
347 st8.spill [r17] = in7
349 /* Invoke ffi_closure_unix_inner for the hard work. */
350 br.call.sptk.many b0 = ffi_closure_unix_inner
353 /* Dispatch to handle return value. */
357 addl r18 = @ltoffx(.Lld_table), gp
360 ld8.mov r18 = [r18], .Lld_table
363 shladd r18 = r16, 3, r18
379 add sp = FRAME_SIZE, sp
387 add sp = FRAME_SIZE, sp
395 add sp = FRAME_SIZE, sp
403 add sp = FRAME_SIZE, sp
411 add sp = FRAME_SIZE, sp
419 cmp.lt p6, p0 = 8, r8
420 cmp.lt p7, p0 = 16, r8
421 cmp.lt p8, p0 = 24, r8
424 (p6) ld8 r9 = [r17], 16
429 add sp = FRAME_SIZE, sp
437 cmp.lt p6, p0 = 4, r8
440 (p6) ldfs f9 = [r17], 8
441 cmp.lt p7, p0 = 8, r8
442 cmp.lt p8, p0 = 12, r8
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
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
454 (p6) ldfs f14 = [r16]
455 (p7) ldfs f15 = [r17]
457 add sp = FRAME_SIZE, sp
465 cmp.lt p6, p0 = 8, r8
468 (p6) ldfd f9 = [r17], 16
469 cmp.lt p7, p0 = 16, r8
470 cmp.lt p8, p0 = 24, r8
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
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
482 (p6) ldfd f14 = [r16]
483 (p7) ldfd f15 = [r17]
485 add sp = FRAME_SIZE, sp
493 cmp.lt p6, p0 = 16, r8
496 (p6) ldfe f9 = [r17], 32
497 cmp.lt p7, p0 = 32, r8
498 cmp.lt p8, p0 = 48, r8
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
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
510 (p6) ldfe f14 = [r16]
511 (p7) ldfe f15 = [r17]
513 add sp = FRAME_SIZE, sp
517 .endp ffi_closure_unix
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
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
565 #if defined __ELF__ && defined __linux__
566 .section .note.GNU-stack,"",@progbits