1 /* -----------------------------------------------------------------------
2 ffi64.c - Copyright (c) 2011, 2018 Anthony Green
3 Copyright (c) 2013 The Written Word, Inc.
4 Copyright (c) 2008, 2010 Red Hat, Inc.
5 Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
7 x86-64 Foreign Function Interface
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 ``Software''), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 ----------------------------------------------------------------------- */
31 #include <ffi_common.h>
37 #include "internal64.h"
41 #define MAX_GPR_REGS 6
42 #define MAX_SSE_REGS 8
44 #if defined(__INTEL_COMPILER)
45 #include "xmmintrin.h"
46 #define UINT128 __m128
48 #if defined(__SUNPRO_C)
49 #include <sunmedia_types.h>
50 #define UINT128 __m128i
52 #define UINT128 __int128_t
65 /* Registers for argument passing. */
66 UINT64 gpr
[MAX_GPR_REGS
];
67 union big_int_union sse
[MAX_SSE_REGS
];
68 UINT64 rax
; /* ssecount */
69 UINT64 r10
; /* static chain */
72 extern void ffi_call_unix64 (void *args
, unsigned long bytes
, unsigned flags
,
73 void *raddr
, void (*fnaddr
)(void)) FFI_HIDDEN
;
75 /* All reference to register classes here is identical to the code in
76 gcc/config/i386/i386.c. Do *not* change one without the other. */
78 /* Register class used for passing given 64bit part of the argument.
79 These represent classes as documented by the PS ABI, with the
80 exception of SSESF, SSEDF classes, that are basically SSE class,
81 just gcc will use SF or DFmode move instead of DImode to avoid
82 reformatting penalties.
84 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
85 whenever possible (upper half does contain padding). */
90 X86_64_INTEGERSI_CLASS
,
97 X86_64_COMPLEX_X87_CLASS
,
101 #define MAX_CLASSES 4
103 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
105 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
106 of this code is to classify each 8bytes of incoming argument by the register
107 class and assign registers accordingly. */
109 /* Return the union class of CLASS1 and CLASS2.
110 See the x86-64 PS ABI for details. */
112 static enum x86_64_reg_class
113 merge_classes (enum x86_64_reg_class class1
, enum x86_64_reg_class class2
)
115 /* Rule #1: If both classes are equal, this is the resulting class. */
116 if (class1
== class2
)
119 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
121 if (class1
== X86_64_NO_CLASS
)
123 if (class2
== X86_64_NO_CLASS
)
126 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
127 if (class1
== X86_64_MEMORY_CLASS
|| class2
== X86_64_MEMORY_CLASS
)
128 return X86_64_MEMORY_CLASS
;
130 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
131 if ((class1
== X86_64_INTEGERSI_CLASS
&& class2
== X86_64_SSESF_CLASS
)
132 || (class2
== X86_64_INTEGERSI_CLASS
&& class1
== X86_64_SSESF_CLASS
))
133 return X86_64_INTEGERSI_CLASS
;
134 if (class1
== X86_64_INTEGER_CLASS
|| class1
== X86_64_INTEGERSI_CLASS
135 || class2
== X86_64_INTEGER_CLASS
|| class2
== X86_64_INTEGERSI_CLASS
)
136 return X86_64_INTEGER_CLASS
;
138 /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
140 if (class1
== X86_64_X87_CLASS
141 || class1
== X86_64_X87UP_CLASS
142 || class1
== X86_64_COMPLEX_X87_CLASS
143 || class2
== X86_64_X87_CLASS
144 || class2
== X86_64_X87UP_CLASS
145 || class2
== X86_64_COMPLEX_X87_CLASS
)
146 return X86_64_MEMORY_CLASS
;
148 /* Rule #6: Otherwise class SSE is used. */
149 return X86_64_SSE_CLASS
;
152 /* Classify the argument of type TYPE and mode MODE.
153 CLASSES will be filled by the register class used to pass each word
154 of the operand. The number of words is returned. In case the parameter
155 should be passed in memory, 0 is returned. As a special case for zero
156 sized containers, classes[0] will be NO_CLASS and 1 is returned.
158 See the x86-64 PS ABI for details.
161 classify_argument (ffi_type
*type
, enum x86_64_reg_class classes
[],
168 case FFI_TYPE_UINT16
:
169 case FFI_TYPE_SINT16
:
170 case FFI_TYPE_UINT32
:
171 case FFI_TYPE_SINT32
:
172 case FFI_TYPE_UINT64
:
173 case FFI_TYPE_SINT64
:
174 case FFI_TYPE_POINTER
:
177 size_t size
= byte_offset
+ type
->size
;
181 classes
[0] = X86_64_INTEGERSI_CLASS
;
186 classes
[0] = X86_64_INTEGER_CLASS
;
191 classes
[0] = X86_64_INTEGER_CLASS
;
192 classes
[1] = X86_64_INTEGERSI_CLASS
;
197 classes
[0] = classes
[1] = X86_64_INTEGER_CLASS
;
204 if (!(byte_offset
% 8))
205 classes
[0] = X86_64_SSESF_CLASS
;
207 classes
[0] = X86_64_SSE_CLASS
;
209 case FFI_TYPE_DOUBLE
:
210 classes
[0] = X86_64_SSEDF_CLASS
;
212 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
213 case FFI_TYPE_LONGDOUBLE
:
214 classes
[0] = X86_64_X87_CLASS
;
215 classes
[1] = X86_64_X87UP_CLASS
;
218 case FFI_TYPE_STRUCT
:
220 const size_t UNITS_PER_WORD
= 8;
221 size_t words
= (type
->size
+ byte_offset
+ UNITS_PER_WORD
- 1)
225 enum x86_64_reg_class subclasses
[MAX_CLASSES
];
227 /* If the struct is larger than 32 bytes, pass it on the stack. */
231 for (i
= 0; i
< words
; i
++)
232 classes
[i
] = X86_64_NO_CLASS
;
234 /* Zero sized arrays or structures are NO_CLASS. We return 0 to
235 signalize memory class, so handle it as special case. */
239 classes
[0] = X86_64_NO_CLASS
;
243 /* Merge the fields of structure. */
244 for (ptr
= type
->elements
; *ptr
!= NULL
; ptr
++)
248 byte_offset
= FFI_ALIGN (byte_offset
, (*ptr
)->alignment
);
250 num
= classify_argument (*ptr
, subclasses
, byte_offset
% 8);
253 pos
= byte_offset
/ 8;
254 for (i
= 0; i
< num
&& (i
+ pos
) < words
; i
++)
256 size_t pos
= byte_offset
/ 8;
258 merge_classes (subclasses
[i
], classes
[i
+ pos
]);
261 byte_offset
+= (*ptr
)->size
;
266 /* When size > 16 bytes, if the first one isn't
267 X86_64_SSE_CLASS or any other ones aren't
268 X86_64_SSEUP_CLASS, everything should be passed in
270 if (classes
[0] != X86_64_SSE_CLASS
)
273 for (i
= 1; i
< words
; i
++)
274 if (classes
[i
] != X86_64_SSEUP_CLASS
)
278 /* Final merger cleanup. */
279 for (i
= 0; i
< words
; i
++)
281 /* If one class is MEMORY, everything should be passed in
283 if (classes
[i
] == X86_64_MEMORY_CLASS
)
286 /* The X86_64_SSEUP_CLASS should be always preceded by
287 X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
288 if (i
> 1 && classes
[i
] == X86_64_SSEUP_CLASS
289 && classes
[i
- 1] != X86_64_SSE_CLASS
290 && classes
[i
- 1] != X86_64_SSEUP_CLASS
)
292 /* The first one should never be X86_64_SSEUP_CLASS. */
294 classes
[i
] = X86_64_SSE_CLASS
;
297 /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
298 everything should be passed in memory. */
299 if (i
> 1 && classes
[i
] == X86_64_X87UP_CLASS
300 && (classes
[i
- 1] != X86_64_X87_CLASS
))
302 /* The first one should never be X86_64_X87UP_CLASS. */
309 case FFI_TYPE_COMPLEX
:
311 ffi_type
*inner
= type
->elements
[0];
317 case FFI_TYPE_UINT16
:
318 case FFI_TYPE_SINT16
:
319 case FFI_TYPE_UINT32
:
320 case FFI_TYPE_SINT32
:
321 case FFI_TYPE_UINT64
:
322 case FFI_TYPE_SINT64
:
326 classes
[0] = X86_64_SSE_CLASS
;
329 classes
[1] = X86_64_SSESF_CLASS
;
333 case FFI_TYPE_DOUBLE
:
334 classes
[0] = classes
[1] = X86_64_SSEDF_CLASS
;
336 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
337 case FFI_TYPE_LONGDOUBLE
:
338 classes
[0] = X86_64_COMPLEX_X87_CLASS
;
347 /* Examine the argument and return set number of register required in each
348 class. Return zero iff parameter should be passed in memory, otherwise
349 the number of registers. */
352 examine_argument (ffi_type
*type
, enum x86_64_reg_class classes
[MAX_CLASSES
],
353 _Bool in_return
, int *pngpr
, int *pnsse
)
359 n
= classify_argument (type
, classes
, 0);
364 for (i
= 0; i
< n
; ++i
)
367 case X86_64_INTEGER_CLASS
:
368 case X86_64_INTEGERSI_CLASS
:
371 case X86_64_SSE_CLASS
:
372 case X86_64_SSESF_CLASS
:
373 case X86_64_SSEDF_CLASS
:
376 case X86_64_NO_CLASS
:
377 case X86_64_SSEUP_CLASS
:
379 case X86_64_X87_CLASS
:
380 case X86_64_X87UP_CLASS
:
381 case X86_64_COMPLEX_X87_CLASS
:
382 return in_return
!= 0;
393 /* Perform machine dependent cif processing. */
397 ffi_prep_cif_machdep_efi64(ffi_cif
*cif
);
400 ffi_status FFI_HIDDEN
401 ffi_prep_cif_machdep (ffi_cif
*cif
)
403 int gprcount
, ssecount
, i
, avn
, ngpr
, nsse
;
405 enum x86_64_reg_class classes
[MAX_CLASSES
];
406 size_t bytes
, n
, rtype_size
;
410 if (cif
->abi
== FFI_EFI64
|| cif
->abi
== FFI_GNUW64
)
411 return ffi_prep_cif_machdep_efi64(cif
);
413 if (cif
->abi
!= FFI_UNIX64
)
416 gprcount
= ssecount
= 0;
419 rtype_size
= rtype
->size
;
423 flags
= UNIX64_RET_VOID
;
426 flags
= UNIX64_RET_UINT8
;
429 flags
= UNIX64_RET_SINT8
;
431 case FFI_TYPE_UINT16
:
432 flags
= UNIX64_RET_UINT16
;
434 case FFI_TYPE_SINT16
:
435 flags
= UNIX64_RET_SINT16
;
437 case FFI_TYPE_UINT32
:
438 flags
= UNIX64_RET_UINT32
;
441 case FFI_TYPE_SINT32
:
442 flags
= UNIX64_RET_SINT32
;
444 case FFI_TYPE_UINT64
:
445 case FFI_TYPE_SINT64
:
446 flags
= UNIX64_RET_INT64
;
448 case FFI_TYPE_POINTER
:
449 flags
= (sizeof(void *) == 4 ? UNIX64_RET_UINT32
: UNIX64_RET_INT64
);
452 flags
= UNIX64_RET_XMM32
;
454 case FFI_TYPE_DOUBLE
:
455 flags
= UNIX64_RET_XMM64
;
457 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
458 case FFI_TYPE_LONGDOUBLE
:
459 flags
= UNIX64_RET_X87
;
462 case FFI_TYPE_STRUCT
:
463 n
= examine_argument (cif
->rtype
, classes
, 1, &ngpr
, &nsse
);
466 /* The return value is passed in memory. A pointer to that
467 memory is the first argument. Allocate a register for it. */
469 /* We don't have to do anything in asm for the return. */
470 flags
= UNIX64_RET_VOID
| UNIX64_FLAG_RET_IN_MEM
;
474 _Bool sse0
= SSE_CLASS_P (classes
[0]);
476 if (rtype_size
== 4 && sse0
)
477 flags
= UNIX64_RET_XMM32
;
478 else if (rtype_size
== 8)
479 flags
= sse0
? UNIX64_RET_XMM64
: UNIX64_RET_INT64
;
482 _Bool sse1
= n
== 2 && SSE_CLASS_P (classes
[1]);
484 flags
= UNIX64_RET_ST_XMM0_XMM1
;
486 flags
= UNIX64_RET_ST_XMM0_RAX
;
488 flags
= UNIX64_RET_ST_RAX_XMM0
;
490 flags
= UNIX64_RET_ST_RAX_RDX
;
491 flags
|= rtype_size
<< UNIX64_SIZE_SHIFT
;
495 case FFI_TYPE_COMPLEX
:
496 switch (rtype
->elements
[0]->type
)
500 case FFI_TYPE_UINT16
:
501 case FFI_TYPE_SINT16
:
503 case FFI_TYPE_UINT32
:
504 case FFI_TYPE_SINT32
:
505 case FFI_TYPE_UINT64
:
506 case FFI_TYPE_SINT64
:
507 flags
= UNIX64_RET_ST_RAX_RDX
| ((unsigned) rtype_size
<< UNIX64_SIZE_SHIFT
);
510 flags
= UNIX64_RET_XMM64
;
512 case FFI_TYPE_DOUBLE
:
513 flags
= UNIX64_RET_ST_XMM0_XMM1
| (16 << UNIX64_SIZE_SHIFT
);
515 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
516 case FFI_TYPE_LONGDOUBLE
:
517 flags
= UNIX64_RET_X87_2
;
521 return FFI_BAD_TYPEDEF
;
525 return FFI_BAD_TYPEDEF
;
528 /* Go over all arguments and determine the way they should be passed.
529 If it's in a register and there is space for it, let that be so. If
530 not, add it's size to the stack byte count. */
531 for (bytes
= 0, i
= 0, avn
= cif
->nargs
; i
< avn
; i
++)
533 if (examine_argument (cif
->arg_types
[i
], classes
, 0, &ngpr
, &nsse
) == 0
534 || gprcount
+ ngpr
> MAX_GPR_REGS
535 || ssecount
+ nsse
> MAX_SSE_REGS
)
537 long align
= cif
->arg_types
[i
]->alignment
;
542 bytes
= FFI_ALIGN (bytes
, align
);
543 bytes
+= cif
->arg_types
[i
]->size
;
552 flags
|= UNIX64_FLAG_XMM_ARGS
;
555 cif
->bytes
= (unsigned) FFI_ALIGN (bytes
, 8);
561 ffi_call_int (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
562 void **avalue
, void *closure
)
564 enum x86_64_reg_class classes
[MAX_CLASSES
];
566 ffi_type
**arg_types
;
567 int gprcount
, ssecount
, ngpr
, nsse
, i
, avn
, flags
;
568 struct register_args
*reg_args
;
570 /* Can't call 32-bit mode from 64-bit mode. */
571 FFI_ASSERT (cif
->abi
== FFI_UNIX64
);
573 /* If the return value is a struct and we don't have a return value
574 address then we need to make one. Otherwise we can ignore it. */
578 if (flags
& UNIX64_FLAG_RET_IN_MEM
)
579 rvalue
= alloca (cif
->rtype
->size
);
581 flags
= UNIX64_RET_VOID
;
584 /* Allocate the space for the arguments, plus 4 words of temp space. */
585 stack
= alloca (sizeof (struct register_args
) + cif
->bytes
+ 4*8);
586 reg_args
= (struct register_args
*) stack
;
587 argp
= stack
+ sizeof (struct register_args
);
589 reg_args
->r10
= (uintptr_t) closure
;
591 gprcount
= ssecount
= 0;
593 /* If the return value is passed in memory, add the pointer as the
594 first integer argument. */
595 if (flags
& UNIX64_FLAG_RET_IN_MEM
)
596 reg_args
->gpr
[gprcount
++] = (unsigned long) rvalue
;
599 arg_types
= cif
->arg_types
;
601 for (i
= 0; i
< avn
; ++i
)
603 size_t n
, size
= arg_types
[i
]->size
;
605 n
= examine_argument (arg_types
[i
], classes
, 0, &ngpr
, &nsse
);
607 || gprcount
+ ngpr
> MAX_GPR_REGS
608 || ssecount
+ nsse
> MAX_SSE_REGS
)
610 long align
= arg_types
[i
]->alignment
;
612 /* Stack arguments are *always* at least 8 byte aligned. */
616 /* Pass this argument in memory. */
617 argp
= (void *) FFI_ALIGN (argp
, align
);
618 memcpy (argp
, avalue
[i
], size
);
623 /* The argument is passed entirely in registers. */
624 char *a
= (char *) avalue
[i
];
627 for (j
= 0; j
< n
; j
++, a
+= 8, size
-= 8)
631 case X86_64_NO_CLASS
:
632 case X86_64_SSEUP_CLASS
:
634 case X86_64_INTEGER_CLASS
:
635 case X86_64_INTEGERSI_CLASS
:
636 /* Sign-extend integer arguments passed in general
637 purpose registers, to cope with the fact that
638 LLVM incorrectly assumes that this will be done
639 (the x86-64 PS ABI does not specify this). */
640 switch (arg_types
[i
]->type
)
643 reg_args
->gpr
[gprcount
] = (SINT64
) *((SINT8
*) a
);
645 case FFI_TYPE_SINT16
:
646 reg_args
->gpr
[gprcount
] = (SINT64
) *((SINT16
*) a
);
648 case FFI_TYPE_SINT32
:
649 reg_args
->gpr
[gprcount
] = (SINT64
) *((SINT32
*) a
);
652 reg_args
->gpr
[gprcount
] = 0;
653 memcpy (®_args
->gpr
[gprcount
], a
, size
);
657 case X86_64_SSE_CLASS
:
658 case X86_64_SSEDF_CLASS
:
659 memcpy (®_args
->sse
[ssecount
++].i64
, a
, sizeof(UINT64
));
661 case X86_64_SSESF_CLASS
:
662 memcpy (®_args
->sse
[ssecount
++].i32
, a
, sizeof(UINT32
));
670 reg_args
->rax
= ssecount
;
672 ffi_call_unix64 (stack
, cif
->bytes
+ sizeof (struct register_args
),
678 ffi_call_efi64(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
);
682 ffi_call (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
685 if (cif
->abi
== FFI_EFI64
|| cif
->abi
== FFI_GNUW64
)
687 ffi_call_efi64(cif
, fn
, rvalue
, avalue
);
691 ffi_call_int (cif
, fn
, rvalue
, avalue
, NULL
);
694 #ifdef FFI_GO_CLOSURES
698 ffi_call_go_efi64(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
699 void **avalue
, void *closure
);
703 ffi_call_go (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
704 void **avalue
, void *closure
)
707 if (cif
->abi
== FFI_EFI64
|| cif
->abi
== FFI_GNUW64
)
709 ffi_call_go_efi64(cif
, fn
, rvalue
, avalue
, closure
);
713 ffi_call_int (cif
, fn
, rvalue
, avalue
, closure
);
716 #endif /* FFI_GO_CLOSURES */
718 extern void ffi_closure_unix64(void) FFI_HIDDEN
;
719 extern void ffi_closure_unix64_sse(void) FFI_HIDDEN
;
720 #if defined(FFI_EXEC_STATIC_TRAMP)
721 extern void ffi_closure_unix64_alt(void) FFI_HIDDEN
;
722 extern void ffi_closure_unix64_sse_alt(void) FFI_HIDDEN
;
727 ffi_prep_closure_loc_efi64(ffi_closure
* closure
,
729 void (*fun
)(ffi_cif
*, void*, void**, void*),
735 ffi_prep_closure_loc (ffi_closure
* closure
,
737 void (*fun
)(ffi_cif
*, void*, void**, void*),
741 static const unsigned char trampoline
[24] = {
743 0xf3, 0x0f, 0x1e, 0xfa,
744 /* leaq -0xb(%rip),%r10 # 0x0 */
745 0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff,
746 /* jmpq *0x7(%rip) # 0x18 */
747 0xff, 0x25, 0x07, 0x00, 0x00, 0x00,
749 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00
752 char *tramp
= closure
->tramp
;
755 if (cif
->abi
== FFI_EFI64
|| cif
->abi
== FFI_GNUW64
)
756 return ffi_prep_closure_loc_efi64(closure
, cif
, fun
, user_data
, codeloc
);
758 if (cif
->abi
!= FFI_UNIX64
)
761 if (cif
->flags
& UNIX64_FLAG_XMM_ARGS
)
762 dest
= ffi_closure_unix64_sse
;
764 dest
= ffi_closure_unix64
;
766 #if defined(FFI_EXEC_STATIC_TRAMP)
767 if (ffi_tramp_is_present(closure
))
769 /* Initialize the static trampoline's parameters. */
770 if (dest
== ffi_closure_unix64_sse
)
771 dest
= ffi_closure_unix64_sse_alt
;
773 dest
= ffi_closure_unix64_alt
;
774 ffi_tramp_set_parms (closure
->ftramp
, dest
, closure
);
779 /* Initialize the dynamic trampoline. */
780 memcpy (tramp
, trampoline
, sizeof(trampoline
));
781 *(UINT64
*)(tramp
+ sizeof (trampoline
)) = (uintptr_t)dest
;
786 closure
->user_data
= user_data
;
792 ffi_closure_unix64_inner(ffi_cif
*cif
,
793 void (*fun
)(ffi_cif
*, void*, void**, void*),
796 struct register_args
*reg_args
,
800 ffi_type
**arg_types
;
802 int gprcount
, ssecount
, ngpr
, nsse
;
807 avalue
= alloca(avn
* sizeof(void *));
808 gprcount
= ssecount
= 0;
810 if (flags
& UNIX64_FLAG_RET_IN_MEM
)
812 /* On return, %rax will contain the address that was passed
813 by the caller in %rdi. */
814 void *r
= (void *)(uintptr_t)reg_args
->gpr
[gprcount
++];
815 *(void **)rvalue
= r
;
817 flags
= (sizeof(void *) == 4 ? UNIX64_RET_UINT32
: UNIX64_RET_INT64
);
820 arg_types
= cif
->arg_types
;
821 for (i
= 0; i
< avn
; ++i
)
823 enum x86_64_reg_class classes
[MAX_CLASSES
];
826 n
= examine_argument (arg_types
[i
], classes
, 0, &ngpr
, &nsse
);
828 || gprcount
+ ngpr
> MAX_GPR_REGS
829 || ssecount
+ nsse
> MAX_SSE_REGS
)
831 long align
= arg_types
[i
]->alignment
;
833 /* Stack arguments are *always* at least 8 byte aligned. */
837 /* Pass this argument in memory. */
838 argp
= (void *) FFI_ALIGN (argp
, align
);
840 argp
+= arg_types
[i
]->size
;
842 /* If the argument is in a single register, or two consecutive
843 integer registers, then we can use that address directly. */
845 || (n
== 2 && !(SSE_CLASS_P (classes
[0])
846 || SSE_CLASS_P (classes
[1]))))
848 /* The argument is in a single register. */
849 if (SSE_CLASS_P (classes
[0]))
851 avalue
[i
] = ®_args
->sse
[ssecount
];
856 avalue
[i
] = ®_args
->gpr
[gprcount
];
860 /* Otherwise, allocate space to make them consecutive. */
863 char *a
= alloca (16);
867 for (j
= 0; j
< n
; j
++, a
+= 8)
869 if (SSE_CLASS_P (classes
[j
]))
870 memcpy (a
, ®_args
->sse
[ssecount
++], 8);
872 memcpy (a
, ®_args
->gpr
[gprcount
++], 8);
877 /* Invoke the closure. */
878 fun (cif
, rvalue
, avalue
, user_data
);
880 /* Tell assembly how to perform return type promotions. */
884 #ifdef FFI_GO_CLOSURES
886 extern void ffi_go_closure_unix64(void) FFI_HIDDEN
;
887 extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN
;
891 ffi_prep_go_closure_efi64(ffi_go_closure
* closure
, ffi_cif
* cif
,
892 void (*fun
)(ffi_cif
*, void*, void**, void*));
896 ffi_prep_go_closure (ffi_go_closure
* closure
, ffi_cif
* cif
,
897 void (*fun
)(ffi_cif
*, void*, void**, void*))
900 if (cif
->abi
== FFI_EFI64
|| cif
->abi
== FFI_GNUW64
)
901 return ffi_prep_go_closure_efi64(closure
, cif
, fun
);
903 if (cif
->abi
!= FFI_UNIX64
)
906 closure
->tramp
= (cif
->flags
& UNIX64_FLAG_XMM_ARGS
907 ? ffi_go_closure_unix64_sse
908 : ffi_go_closure_unix64
);
915 #endif /* FFI_GO_CLOSURES */
917 #if defined(FFI_EXEC_STATIC_TRAMP)
919 ffi_tramp_arch (size_t *tramp_size
, size_t *map_size
)
921 extern void *trampoline_code_table
;
923 *map_size
= UNIX64_TRAMP_MAP_SIZE
;
924 *tramp_size
= UNIX64_TRAMP_SIZE
;
925 return &trampoline_code_table
;
929 #endif /* __x86_64__ */