1 /* -----------------------------------------------------------------------
2 ffi64.c - Copyright (c) 2013 The Written Word, Inc.
3 Copyright (c) 2011 Anthony Green
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>
36 #include "internal64.h"
40 #define MAX_GPR_REGS 6
41 #define MAX_SSE_REGS 8
43 #if defined(__INTEL_COMPILER)
44 #include "xmmintrin.h"
45 #define UINT128 __m128
47 #if defined(__SUNPRO_C)
48 #include <sunmedia_types.h>
49 #define UINT128 __m128i
51 #define UINT128 __int128_t
64 /* Registers for argument passing. */
65 UINT64 gpr
[MAX_GPR_REGS
];
66 union big_int_union sse
[MAX_SSE_REGS
];
67 UINT64 rax
; /* ssecount */
68 UINT64 r10
; /* static chain */
71 extern void ffi_call_unix64 (void *args
, unsigned long bytes
, unsigned flags
,
72 void *raddr
, void (*fnaddr
)(void)) FFI_HIDDEN
;
74 /* All reference to register classes here is identical to the code in
75 gcc/config/i386/i386.c. Do *not* change one without the other. */
77 /* Register class used for passing given 64bit part of the argument.
78 These represent classes as documented by the PS ABI, with the
79 exception of SSESF, SSEDF classes, that are basically SSE class,
80 just gcc will use SF or DFmode move instead of DImode to avoid
81 reformatting penalties.
83 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
84 whenever possible (upper half does contain padding). */
89 X86_64_INTEGERSI_CLASS
,
96 X86_64_COMPLEX_X87_CLASS
,
100 #define MAX_CLASSES 4
102 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
104 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
105 of this code is to classify each 8bytes of incoming argument by the register
106 class and assign registers accordingly. */
108 /* Return the union class of CLASS1 and CLASS2.
109 See the x86-64 PS ABI for details. */
111 static enum x86_64_reg_class
112 merge_classes (enum x86_64_reg_class class1
, enum x86_64_reg_class class2
)
114 /* Rule #1: If both classes are equal, this is the resulting class. */
115 if (class1
== class2
)
118 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
120 if (class1
== X86_64_NO_CLASS
)
122 if (class2
== X86_64_NO_CLASS
)
125 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
126 if (class1
== X86_64_MEMORY_CLASS
|| class2
== X86_64_MEMORY_CLASS
)
127 return X86_64_MEMORY_CLASS
;
129 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
130 if ((class1
== X86_64_INTEGERSI_CLASS
&& class2
== X86_64_SSESF_CLASS
)
131 || (class2
== X86_64_INTEGERSI_CLASS
&& class1
== X86_64_SSESF_CLASS
))
132 return X86_64_INTEGERSI_CLASS
;
133 if (class1
== X86_64_INTEGER_CLASS
|| class1
== X86_64_INTEGERSI_CLASS
134 || class2
== X86_64_INTEGER_CLASS
|| class2
== X86_64_INTEGERSI_CLASS
)
135 return X86_64_INTEGER_CLASS
;
137 /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
139 if (class1
== X86_64_X87_CLASS
140 || class1
== X86_64_X87UP_CLASS
141 || class1
== X86_64_COMPLEX_X87_CLASS
142 || class2
== X86_64_X87_CLASS
143 || class2
== X86_64_X87UP_CLASS
144 || class2
== X86_64_COMPLEX_X87_CLASS
)
145 return X86_64_MEMORY_CLASS
;
147 /* Rule #6: Otherwise class SSE is used. */
148 return X86_64_SSE_CLASS
;
151 /* Classify the argument of type TYPE and mode MODE.
152 CLASSES will be filled by the register class used to pass each word
153 of the operand. The number of words is returned. In case the parameter
154 should be passed in memory, 0 is returned. As a special case for zero
155 sized containers, classes[0] will be NO_CLASS and 1 is returned.
157 See the x86-64 PS ABI for details.
160 classify_argument (ffi_type
*type
, enum x86_64_reg_class classes
[],
167 case FFI_TYPE_UINT16
:
168 case FFI_TYPE_SINT16
:
169 case FFI_TYPE_UINT32
:
170 case FFI_TYPE_SINT32
:
171 case FFI_TYPE_UINT64
:
172 case FFI_TYPE_SINT64
:
173 case FFI_TYPE_POINTER
:
176 size_t size
= byte_offset
+ type
->size
;
180 classes
[0] = X86_64_INTEGERSI_CLASS
;
185 classes
[0] = X86_64_INTEGER_CLASS
;
190 classes
[0] = X86_64_INTEGER_CLASS
;
191 classes
[1] = X86_64_INTEGERSI_CLASS
;
196 classes
[0] = classes
[1] = X86_64_INTEGER_CLASS
;
203 if (!(byte_offset
% 8))
204 classes
[0] = X86_64_SSESF_CLASS
;
206 classes
[0] = X86_64_SSE_CLASS
;
208 case FFI_TYPE_DOUBLE
:
209 classes
[0] = X86_64_SSEDF_CLASS
;
211 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
212 case FFI_TYPE_LONGDOUBLE
:
213 classes
[0] = X86_64_X87_CLASS
;
214 classes
[1] = X86_64_X87UP_CLASS
;
217 case FFI_TYPE_STRUCT
:
219 const size_t UNITS_PER_WORD
= 8;
220 size_t words
= (type
->size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
223 enum x86_64_reg_class subclasses
[MAX_CLASSES
];
225 /* If the struct is larger than 32 bytes, pass it on the stack. */
229 for (i
= 0; i
< words
; i
++)
230 classes
[i
] = X86_64_NO_CLASS
;
232 /* Zero sized arrays or structures are NO_CLASS. We return 0 to
233 signalize memory class, so handle it as special case. */
237 classes
[0] = X86_64_NO_CLASS
;
241 /* Merge the fields of structure. */
242 for (ptr
= type
->elements
; *ptr
!= NULL
; ptr
++)
246 byte_offset
= ALIGN (byte_offset
, (*ptr
)->alignment
);
248 num
= classify_argument (*ptr
, subclasses
, byte_offset
% 8);
251 for (i
= 0; i
< num
; i
++)
253 size_t pos
= byte_offset
/ 8;
255 merge_classes (subclasses
[i
], classes
[i
+ pos
]);
258 byte_offset
+= (*ptr
)->size
;
263 /* When size > 16 bytes, if the first one isn't
264 X86_64_SSE_CLASS or any other ones aren't
265 X86_64_SSEUP_CLASS, everything should be passed in
267 if (classes
[0] != X86_64_SSE_CLASS
)
270 for (i
= 1; i
< words
; i
++)
271 if (classes
[i
] != X86_64_SSEUP_CLASS
)
275 /* Final merger cleanup. */
276 for (i
= 0; i
< words
; i
++)
278 /* If one class is MEMORY, everything should be passed in
280 if (classes
[i
] == X86_64_MEMORY_CLASS
)
283 /* The X86_64_SSEUP_CLASS should be always preceded by
284 X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
285 if (classes
[i
] == X86_64_SSEUP_CLASS
286 && classes
[i
- 1] != X86_64_SSE_CLASS
287 && classes
[i
- 1] != X86_64_SSEUP_CLASS
)
289 /* The first one should never be X86_64_SSEUP_CLASS. */
291 classes
[i
] = X86_64_SSE_CLASS
;
294 /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
295 everything should be passed in memory. */
296 if (classes
[i
] == X86_64_X87UP_CLASS
297 && (classes
[i
- 1] != X86_64_X87_CLASS
))
299 /* The first one should never be X86_64_X87UP_CLASS. */
306 case FFI_TYPE_COMPLEX
:
308 ffi_type
*inner
= type
->elements
[0];
314 case FFI_TYPE_UINT16
:
315 case FFI_TYPE_SINT16
:
316 case FFI_TYPE_UINT32
:
317 case FFI_TYPE_SINT32
:
318 case FFI_TYPE_UINT64
:
319 case FFI_TYPE_SINT64
:
323 classes
[0] = X86_64_SSE_CLASS
;
326 classes
[1] = X86_64_SSESF_CLASS
;
330 case FFI_TYPE_DOUBLE
:
331 classes
[0] = classes
[1] = X86_64_SSEDF_CLASS
;
333 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
334 case FFI_TYPE_LONGDOUBLE
:
335 classes
[0] = X86_64_COMPLEX_X87_CLASS
;
344 /* Examine the argument and return set number of register required in each
345 class. Return zero iff parameter should be passed in memory, otherwise
346 the number of registers. */
349 examine_argument (ffi_type
*type
, enum x86_64_reg_class classes
[MAX_CLASSES
],
350 _Bool in_return
, int *pngpr
, int *pnsse
)
355 n
= classify_argument (type
, classes
, 0);
360 for (i
= 0; i
< n
; ++i
)
363 case X86_64_INTEGER_CLASS
:
364 case X86_64_INTEGERSI_CLASS
:
367 case X86_64_SSE_CLASS
:
368 case X86_64_SSESF_CLASS
:
369 case X86_64_SSEDF_CLASS
:
372 case X86_64_NO_CLASS
:
373 case X86_64_SSEUP_CLASS
:
375 case X86_64_X87_CLASS
:
376 case X86_64_X87UP_CLASS
:
377 case X86_64_COMPLEX_X87_CLASS
:
378 return in_return
!= 0;
389 /* Perform machine dependent cif processing. */
392 ffi_prep_cif_machdep (ffi_cif
*cif
)
394 int gprcount
, ssecount
, i
, avn
, ngpr
, nsse
, flags
;
395 enum x86_64_reg_class classes
[MAX_CLASSES
];
396 size_t bytes
, n
, rtype_size
;
399 if (cif
->abi
!= FFI_UNIX64
)
402 gprcount
= ssecount
= 0;
405 rtype_size
= rtype
->size
;
409 flags
= UNIX64_RET_VOID
;
412 flags
= UNIX64_RET_UINT8
;
415 flags
= UNIX64_RET_SINT8
;
417 case FFI_TYPE_UINT16
:
418 flags
= UNIX64_RET_UINT16
;
420 case FFI_TYPE_SINT16
:
421 flags
= UNIX64_RET_SINT16
;
423 case FFI_TYPE_UINT32
:
424 flags
= UNIX64_RET_UINT32
;
427 case FFI_TYPE_SINT32
:
428 flags
= UNIX64_RET_SINT32
;
430 case FFI_TYPE_UINT64
:
431 case FFI_TYPE_SINT64
:
432 flags
= UNIX64_RET_INT64
;
434 case FFI_TYPE_POINTER
:
435 flags
= (sizeof(void *) == 4 ? UNIX64_RET_UINT32
: UNIX64_RET_INT64
);
438 flags
= UNIX64_RET_XMM32
;
440 case FFI_TYPE_DOUBLE
:
441 flags
= UNIX64_RET_XMM64
;
443 case FFI_TYPE_LONGDOUBLE
:
444 flags
= UNIX64_RET_X87
;
446 case FFI_TYPE_STRUCT
:
447 n
= examine_argument (cif
->rtype
, classes
, 1, &ngpr
, &nsse
);
450 /* The return value is passed in memory. A pointer to that
451 memory is the first argument. Allocate a register for it. */
453 /* We don't have to do anything in asm for the return. */
454 flags
= UNIX64_RET_VOID
| UNIX64_FLAG_RET_IN_MEM
;
458 _Bool sse0
= SSE_CLASS_P (classes
[0]);
460 if (rtype_size
== 4 && sse0
)
461 flags
= UNIX64_RET_XMM32
;
462 else if (rtype_size
== 8)
463 flags
= sse0
? UNIX64_RET_XMM64
: UNIX64_RET_INT64
;
466 _Bool sse1
= n
== 2 && SSE_CLASS_P (classes
[1]);
468 flags
= UNIX64_RET_ST_XMM0_XMM1
;
470 flags
= UNIX64_RET_ST_XMM0_RAX
;
472 flags
= UNIX64_RET_ST_RAX_XMM0
;
474 flags
= UNIX64_RET_ST_RAX_RDX
;
475 flags
|= rtype_size
<< UNIX64_SIZE_SHIFT
;
479 case FFI_TYPE_COMPLEX
:
480 switch (rtype
->elements
[0]->type
)
484 case FFI_TYPE_UINT16
:
485 case FFI_TYPE_SINT16
:
487 case FFI_TYPE_UINT32
:
488 case FFI_TYPE_SINT32
:
489 case FFI_TYPE_UINT64
:
490 case FFI_TYPE_SINT64
:
491 flags
= UNIX64_RET_ST_RAX_RDX
| (rtype_size
<< UNIX64_SIZE_SHIFT
);
494 flags
= UNIX64_RET_XMM64
;
496 case FFI_TYPE_DOUBLE
:
497 flags
= UNIX64_RET_ST_XMM0_XMM1
| (16 << UNIX64_SIZE_SHIFT
);
499 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
500 case FFI_TYPE_LONGDOUBLE
:
501 flags
= UNIX64_RET_X87_2
;
505 return FFI_BAD_TYPEDEF
;
509 return FFI_BAD_TYPEDEF
;
512 /* Go over all arguments and determine the way they should be passed.
513 If it's in a register and there is space for it, let that be so. If
514 not, add it's size to the stack byte count. */
515 for (bytes
= 0, i
= 0, avn
= cif
->nargs
; i
< avn
; i
++)
517 if (examine_argument (cif
->arg_types
[i
], classes
, 0, &ngpr
, &nsse
) == 0
518 || gprcount
+ ngpr
> MAX_GPR_REGS
519 || ssecount
+ nsse
> MAX_SSE_REGS
)
521 long align
= cif
->arg_types
[i
]->alignment
;
526 bytes
= ALIGN (bytes
, align
);
527 bytes
+= cif
->arg_types
[i
]->size
;
536 flags
|= UNIX64_FLAG_XMM_ARGS
;
539 cif
->bytes
= ALIGN (bytes
, 8);
545 ffi_call_int (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
546 void **avalue
, void *closure
)
548 enum x86_64_reg_class classes
[MAX_CLASSES
];
550 ffi_type
**arg_types
;
551 int gprcount
, ssecount
, ngpr
, nsse
, i
, avn
, flags
;
552 struct register_args
*reg_args
;
554 /* Can't call 32-bit mode from 64-bit mode. */
555 FFI_ASSERT (cif
->abi
== FFI_UNIX64
);
557 /* If the return value is a struct and we don't have a return value
558 address then we need to make one. Otherwise we can ignore it. */
562 if (flags
& UNIX64_FLAG_RET_IN_MEM
)
563 rvalue
= alloca (cif
->rtype
->size
);
565 flags
= UNIX64_RET_VOID
;
568 /* Allocate the space for the arguments, plus 4 words of temp space. */
569 stack
= alloca (sizeof (struct register_args
) + cif
->bytes
+ 4*8);
570 reg_args
= (struct register_args
*) stack
;
571 argp
= stack
+ sizeof (struct register_args
);
573 reg_args
->r10
= (uintptr_t) closure
;
575 gprcount
= ssecount
= 0;
577 /* If the return value is passed in memory, add the pointer as the
578 first integer argument. */
579 if (flags
& UNIX64_FLAG_RET_IN_MEM
)
580 reg_args
->gpr
[gprcount
++] = (unsigned long) rvalue
;
583 arg_types
= cif
->arg_types
;
585 for (i
= 0; i
< avn
; ++i
)
587 size_t n
, size
= arg_types
[i
]->size
;
589 n
= examine_argument (arg_types
[i
], classes
, 0, &ngpr
, &nsse
);
591 || gprcount
+ ngpr
> MAX_GPR_REGS
592 || ssecount
+ nsse
> MAX_SSE_REGS
)
594 long align
= arg_types
[i
]->alignment
;
596 /* Stack arguments are *always* at least 8 byte aligned. */
600 /* Pass this argument in memory. */
601 argp
= (void *) ALIGN (argp
, align
);
602 memcpy (argp
, avalue
[i
], size
);
607 /* The argument is passed entirely in registers. */
608 char *a
= (char *) avalue
[i
];
611 for (j
= 0; j
< n
; j
++, a
+= 8, size
-= 8)
615 case X86_64_NO_CLASS
:
616 case X86_64_SSEUP_CLASS
:
618 case X86_64_INTEGER_CLASS
:
619 case X86_64_INTEGERSI_CLASS
:
620 /* Sign-extend integer arguments passed in general
621 purpose registers, to cope with the fact that
622 LLVM incorrectly assumes that this will be done
623 (the x86-64 PS ABI does not specify this). */
624 switch (arg_types
[i
]->type
)
627 reg_args
->gpr
[gprcount
] = (SINT64
) *((SINT8
*) a
);
629 case FFI_TYPE_SINT16
:
630 reg_args
->gpr
[gprcount
] = (SINT64
) *((SINT16
*) a
);
632 case FFI_TYPE_SINT32
:
633 reg_args
->gpr
[gprcount
] = (SINT64
) *((SINT32
*) a
);
636 reg_args
->gpr
[gprcount
] = 0;
637 memcpy (®_args
->gpr
[gprcount
], a
, size
);
641 case X86_64_SSE_CLASS
:
642 case X86_64_SSEDF_CLASS
:
643 reg_args
->sse
[ssecount
++].i64
= *(UINT64
*) a
;
645 case X86_64_SSESF_CLASS
:
646 reg_args
->sse
[ssecount
++].i32
= *(UINT32
*) a
;
654 reg_args
->rax
= ssecount
;
656 ffi_call_unix64 (stack
, cif
->bytes
+ sizeof (struct register_args
),
661 ffi_call (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
663 ffi_call_int (cif
, fn
, rvalue
, avalue
, NULL
);
667 ffi_call_go (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
668 void **avalue
, void *closure
)
670 ffi_call_int (cif
, fn
, rvalue
, avalue
, closure
);
673 extern void ffi_closure_unix64(void) FFI_HIDDEN
;
674 extern void ffi_closure_unix64_sse(void) FFI_HIDDEN
;
677 ffi_prep_closure_loc (ffi_closure
* closure
,
679 void (*fun
)(ffi_cif
*, void*, void**, void*),
683 static const unsigned char trampoline
[16] = {
684 /* leaq -0x7(%rip),%r10 # 0x0 */
685 0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
686 /* jmpq *0x3(%rip) # 0x10 */
687 0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
692 char *tramp
= closure
->tramp
;
694 if (cif
->abi
!= FFI_UNIX64
)
697 if (cif
->flags
& UNIX64_FLAG_XMM_ARGS
)
698 dest
= ffi_closure_unix64_sse
;
700 dest
= ffi_closure_unix64
;
702 memcpy (tramp
, trampoline
, sizeof(trampoline
));
703 *(UINT64
*)(tramp
+ 16) = (uintptr_t)dest
;
707 closure
->user_data
= user_data
;
713 ffi_closure_unix64_inner(ffi_cif
*cif
,
714 void (*fun
)(ffi_cif
*, void*, void**, void*),
717 struct register_args
*reg_args
,
721 ffi_type
**arg_types
;
723 int gprcount
, ssecount
, ngpr
, nsse
;
728 avalue
= alloca(avn
* sizeof(void *));
729 gprcount
= ssecount
= 0;
731 if (flags
& UNIX64_FLAG_RET_IN_MEM
)
733 /* On return, %rax will contain the address that was passed
734 by the caller in %rdi. */
735 void *r
= (void *)(uintptr_t)reg_args
->gpr
[gprcount
++];
736 *(void **)rvalue
= r
;
738 flags
= (sizeof(void *) == 4 ? UNIX64_RET_UINT32
: UNIX64_RET_INT64
);
741 arg_types
= cif
->arg_types
;
742 for (i
= 0; i
< avn
; ++i
)
744 enum x86_64_reg_class classes
[MAX_CLASSES
];
747 n
= examine_argument (arg_types
[i
], classes
, 0, &ngpr
, &nsse
);
749 || gprcount
+ ngpr
> MAX_GPR_REGS
750 || ssecount
+ nsse
> MAX_SSE_REGS
)
752 long align
= arg_types
[i
]->alignment
;
754 /* Stack arguments are *always* at least 8 byte aligned. */
758 /* Pass this argument in memory. */
759 argp
= (void *) ALIGN (argp
, align
);
761 argp
+= arg_types
[i
]->size
;
763 /* If the argument is in a single register, or two consecutive
764 integer registers, then we can use that address directly. */
766 || (n
== 2 && !(SSE_CLASS_P (classes
[0])
767 || SSE_CLASS_P (classes
[1]))))
769 /* The argument is in a single register. */
770 if (SSE_CLASS_P (classes
[0]))
772 avalue
[i
] = ®_args
->sse
[ssecount
];
777 avalue
[i
] = ®_args
->gpr
[gprcount
];
781 /* Otherwise, allocate space to make them consecutive. */
784 char *a
= alloca (16);
788 for (j
= 0; j
< n
; j
++, a
+= 8)
790 if (SSE_CLASS_P (classes
[j
]))
791 memcpy (a
, ®_args
->sse
[ssecount
++], 8);
793 memcpy (a
, ®_args
->gpr
[gprcount
++], 8);
798 /* Invoke the closure. */
799 fun (cif
, rvalue
, avalue
, user_data
);
801 /* Tell assembly how to perform return type promotions. */
805 extern void ffi_go_closure_unix64(void) FFI_HIDDEN
;
806 extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN
;
809 ffi_prep_go_closure (ffi_go_closure
* closure
, ffi_cif
* cif
,
810 void (*fun
)(ffi_cif
*, void*, void**, void*))
812 if (cif
->abi
!= FFI_UNIX64
)
815 closure
->tramp
= (cif
->flags
& UNIX64_FLAG_XMM_ARGS
816 ? ffi_go_closure_unix64_sse
817 : ffi_go_closure_unix64
);
824 #endif /* __x86_64__ */