1 /* -----------------------------------------------------------------------
2 ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
3 Copyright (c) 2008, 2010 Red Hat, Inc.
5 x86-64 Foreign Function Interface
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
29 #include <ffi_common.h>
36 #define MAX_GPR_REGS 6
37 #define MAX_SSE_REGS 8
41 /* Registers for argument passing. */
42 UINT64 gpr
[MAX_GPR_REGS
];
43 __int128_t sse
[MAX_SSE_REGS
];
46 extern void ffi_call_unix64 (void *args
, unsigned long bytes
, unsigned flags
,
47 void *raddr
, void (*fnaddr
)(void), unsigned ssecount
);
49 /* All reference to register classes here is identical to the code in
50 gcc/config/i386/i386.c. Do *not* change one without the other. */
52 /* Register class used for passing given 64bit part of the argument.
53 These represent classes as documented by the PS ABI, with the
54 exception of SSESF, SSEDF classes, that are basically SSE class,
55 just gcc will use SF or DFmode move instead of DImode to avoid
56 reformatting penalties.
58 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
59 whenever possible (upper half does contain padding). */
64 X86_64_INTEGERSI_CLASS
,
71 X86_64_COMPLEX_X87_CLASS
,
77 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
79 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
80 of this code is to classify each 8bytes of incoming argument by the register
81 class and assign registers accordingly. */
83 /* Return the union class of CLASS1 and CLASS2.
84 See the x86-64 PS ABI for details. */
86 static enum x86_64_reg_class
87 merge_classes (enum x86_64_reg_class class1
, enum x86_64_reg_class class2
)
89 /* Rule #1: If both classes are equal, this is the resulting class. */
93 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
95 if (class1
== X86_64_NO_CLASS
)
97 if (class2
== X86_64_NO_CLASS
)
100 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
101 if (class1
== X86_64_MEMORY_CLASS
|| class2
== X86_64_MEMORY_CLASS
)
102 return X86_64_MEMORY_CLASS
;
104 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
105 if ((class1
== X86_64_INTEGERSI_CLASS
&& class2
== X86_64_SSESF_CLASS
)
106 || (class2
== X86_64_INTEGERSI_CLASS
&& class1
== X86_64_SSESF_CLASS
))
107 return X86_64_INTEGERSI_CLASS
;
108 if (class1
== X86_64_INTEGER_CLASS
|| class1
== X86_64_INTEGERSI_CLASS
109 || class2
== X86_64_INTEGER_CLASS
|| class2
== X86_64_INTEGERSI_CLASS
)
110 return X86_64_INTEGER_CLASS
;
112 /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
114 if (class1
== X86_64_X87_CLASS
115 || class1
== X86_64_X87UP_CLASS
116 || class1
== X86_64_COMPLEX_X87_CLASS
117 || class2
== X86_64_X87_CLASS
118 || class2
== X86_64_X87UP_CLASS
119 || class2
== X86_64_COMPLEX_X87_CLASS
)
120 return X86_64_MEMORY_CLASS
;
122 /* Rule #6: Otherwise class SSE is used. */
123 return X86_64_SSE_CLASS
;
126 /* Classify the argument of type TYPE and mode MODE.
127 CLASSES will be filled by the register class used to pass each word
128 of the operand. The number of words is returned. In case the parameter
129 should be passed in memory, 0 is returned. As a special case for zero
130 sized containers, classes[0] will be NO_CLASS and 1 is returned.
132 See the x86-64 PS ABI for details.
135 classify_argument (ffi_type
*type
, enum x86_64_reg_class classes
[],
142 case FFI_TYPE_UINT16
:
143 case FFI_TYPE_SINT16
:
144 case FFI_TYPE_UINT32
:
145 case FFI_TYPE_SINT32
:
146 case FFI_TYPE_UINT64
:
147 case FFI_TYPE_SINT64
:
148 case FFI_TYPE_POINTER
:
150 int size
= byte_offset
+ type
->size
;
154 classes
[0] = X86_64_INTEGERSI_CLASS
;
159 classes
[0] = X86_64_INTEGER_CLASS
;
164 classes
[0] = X86_64_INTEGER_CLASS
;
165 classes
[1] = X86_64_INTEGERSI_CLASS
;
170 classes
[0] = classes
[1] = X86_64_INTEGERSI_CLASS
;
177 if (!(byte_offset
% 8))
178 classes
[0] = X86_64_SSESF_CLASS
;
180 classes
[0] = X86_64_SSE_CLASS
;
182 case FFI_TYPE_DOUBLE
:
183 classes
[0] = X86_64_SSEDF_CLASS
;
185 case FFI_TYPE_LONGDOUBLE
:
186 classes
[0] = X86_64_X87_CLASS
;
187 classes
[1] = X86_64_X87UP_CLASS
;
189 case FFI_TYPE_STRUCT
:
191 const int UNITS_PER_WORD
= 8;
192 int words
= (type
->size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
195 enum x86_64_reg_class subclasses
[MAX_CLASSES
];
197 /* If the struct is larger than 32 bytes, pass it on the stack. */
201 for (i
= 0; i
< words
; i
++)
202 classes
[i
] = X86_64_NO_CLASS
;
204 /* Zero sized arrays or structures are NO_CLASS. We return 0 to
205 signalize memory class, so handle it as special case. */
208 classes
[0] = X86_64_NO_CLASS
;
212 /* Merge the fields of structure. */
213 for (ptr
= type
->elements
; *ptr
!= NULL
; ptr
++)
217 byte_offset
= ALIGN (byte_offset
, (*ptr
)->alignment
);
219 num
= classify_argument (*ptr
, subclasses
, byte_offset
% 8);
222 for (i
= 0; i
< num
; i
++)
224 int pos
= byte_offset
/ 8;
226 merge_classes (subclasses
[i
], classes
[i
+ pos
]);
229 byte_offset
+= (*ptr
)->size
;
234 /* When size > 16 bytes, if the first one isn't
235 X86_64_SSE_CLASS or any other ones aren't
236 X86_64_SSEUP_CLASS, everything should be passed in
238 if (classes
[0] != X86_64_SSE_CLASS
)
241 for (i
= 1; i
< words
; i
++)
242 if (classes
[i
] != X86_64_SSEUP_CLASS
)
246 /* Final merger cleanup. */
247 for (i
= 0; i
< words
; i
++)
249 /* If one class is MEMORY, everything should be passed in
251 if (classes
[i
] == X86_64_MEMORY_CLASS
)
254 /* The X86_64_SSEUP_CLASS should be always preceded by
255 X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
256 if (classes
[i
] == X86_64_SSEUP_CLASS
257 && classes
[i
- 1] != X86_64_SSE_CLASS
258 && classes
[i
- 1] != X86_64_SSEUP_CLASS
)
260 /* The first one should never be X86_64_SSEUP_CLASS. */
262 classes
[i
] = X86_64_SSE_CLASS
;
265 /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
266 everything should be passed in memory. */
267 if (classes
[i
] == X86_64_X87UP_CLASS
268 && (classes
[i
- 1] != X86_64_X87_CLASS
))
270 /* The first one should never be X86_64_X87UP_CLASS. */
281 return 0; /* Never reached. */
284 /* Examine the argument and return set number of register required in each
285 class. Return zero iff parameter should be passed in memory, otherwise
286 the number of registers. */
289 examine_argument (ffi_type
*type
, enum x86_64_reg_class classes
[MAX_CLASSES
],
290 _Bool in_return
, int *pngpr
, int *pnsse
)
292 int i
, n
, ngpr
, nsse
;
294 n
= classify_argument (type
, classes
, 0);
299 for (i
= 0; i
< n
; ++i
)
302 case X86_64_INTEGER_CLASS
:
303 case X86_64_INTEGERSI_CLASS
:
306 case X86_64_SSE_CLASS
:
307 case X86_64_SSESF_CLASS
:
308 case X86_64_SSEDF_CLASS
:
311 case X86_64_NO_CLASS
:
312 case X86_64_SSEUP_CLASS
:
314 case X86_64_X87_CLASS
:
315 case X86_64_X87UP_CLASS
:
316 case X86_64_COMPLEX_X87_CLASS
:
317 return in_return
!= 0;
328 /* Perform machine dependent cif processing. */
331 ffi_prep_cif_machdep (ffi_cif
*cif
)
333 int gprcount
, ssecount
, i
, avn
, n
, ngpr
, nsse
, flags
;
334 enum x86_64_reg_class classes
[MAX_CLASSES
];
337 gprcount
= ssecount
= 0;
339 flags
= cif
->rtype
->type
;
340 if (flags
!= FFI_TYPE_VOID
)
342 n
= examine_argument (cif
->rtype
, classes
, 1, &ngpr
, &nsse
);
345 /* The return value is passed in memory. A pointer to that
346 memory is the first argument. Allocate a register for it. */
348 /* We don't have to do anything in asm for the return. */
349 flags
= FFI_TYPE_VOID
;
351 else if (flags
== FFI_TYPE_STRUCT
)
353 /* Mark which registers the result appears in. */
354 _Bool sse0
= SSE_CLASS_P (classes
[0]);
355 _Bool sse1
= n
== 2 && SSE_CLASS_P (classes
[1]);
358 else if (!sse0
&& sse1
)
360 else if (sse0
&& sse1
)
362 /* Mark the true size of the structure. */
363 flags
|= cif
->rtype
->size
<< 12;
367 /* Go over all arguments and determine the way they should be passed.
368 If it's in a register and there is space for it, let that be so. If
369 not, add it's size to the stack byte count. */
370 for (bytes
= 0, i
= 0, avn
= cif
->nargs
; i
< avn
; i
++)
372 if (examine_argument (cif
->arg_types
[i
], classes
, 0, &ngpr
, &nsse
) == 0
373 || gprcount
+ ngpr
> MAX_GPR_REGS
374 || ssecount
+ nsse
> MAX_SSE_REGS
)
376 long align
= cif
->arg_types
[i
]->alignment
;
381 bytes
= ALIGN (bytes
, align
);
382 bytes
+= cif
->arg_types
[i
]->size
;
393 cif
->bytes
= ALIGN (bytes
, 8);
399 ffi_call (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
401 enum x86_64_reg_class classes
[MAX_CLASSES
];
403 ffi_type
**arg_types
;
404 int gprcount
, ssecount
, ngpr
, nsse
, i
, avn
;
406 struct register_args
*reg_args
;
408 /* Can't call 32-bit mode from 64-bit mode. */
409 FFI_ASSERT (cif
->abi
== FFI_UNIX64
);
411 /* If the return value is a struct and we don't have a return value
412 address then we need to make one. Note the setting of flags to
413 VOID above in ffi_prep_cif_machdep. */
414 ret_in_memory
= (cif
->rtype
->type
== FFI_TYPE_STRUCT
415 && (cif
->flags
& 0xff) == FFI_TYPE_VOID
);
416 if (rvalue
== NULL
&& ret_in_memory
)
417 rvalue
= alloca (cif
->rtype
->size
);
419 /* Allocate the space for the arguments, plus 4 words of temp space. */
420 stack
= alloca (sizeof (struct register_args
) + cif
->bytes
+ 4*8);
421 reg_args
= (struct register_args
*) stack
;
422 argp
= stack
+ sizeof (struct register_args
);
424 gprcount
= ssecount
= 0;
426 /* If the return value is passed in memory, add the pointer as the
427 first integer argument. */
429 reg_args
->gpr
[gprcount
++] = (long) rvalue
;
432 arg_types
= cif
->arg_types
;
434 for (i
= 0; i
< avn
; ++i
)
436 size_t size
= arg_types
[i
]->size
;
439 n
= examine_argument (arg_types
[i
], classes
, 0, &ngpr
, &nsse
);
441 || gprcount
+ ngpr
> MAX_GPR_REGS
442 || ssecount
+ nsse
> MAX_SSE_REGS
)
444 long align
= arg_types
[i
]->alignment
;
446 /* Stack arguments are *always* at least 8 byte aligned. */
450 /* Pass this argument in memory. */
451 argp
= (void *) ALIGN (argp
, align
);
452 memcpy (argp
, avalue
[i
], size
);
457 /* The argument is passed entirely in registers. */
458 char *a
= (char *) avalue
[i
];
461 for (j
= 0; j
< n
; j
++, a
+= 8, size
-= 8)
465 case X86_64_INTEGER_CLASS
:
466 case X86_64_INTEGERSI_CLASS
:
467 reg_args
->gpr
[gprcount
] = 0;
468 memcpy (®_args
->gpr
[gprcount
], a
, size
< 8 ? size
: 8);
471 case X86_64_SSE_CLASS
:
472 case X86_64_SSEDF_CLASS
:
473 reg_args
->sse
[ssecount
++] = *(UINT64
*) a
;
475 case X86_64_SSESF_CLASS
:
476 reg_args
->sse
[ssecount
++] = *(UINT32
*) a
;
485 ffi_call_unix64 (stack
, cif
->bytes
+ sizeof (struct register_args
),
486 cif
->flags
, rvalue
, fn
, ssecount
);
490 extern void ffi_closure_unix64(void);
493 ffi_prep_closure_loc (ffi_closure
* closure
,
495 void (*fun
)(ffi_cif
*, void*, void**, void*),
499 volatile unsigned short *tramp
;
501 tramp
= (volatile unsigned short *) &closure
->tramp
[0];
503 tramp
[0] = 0xbb49; /* mov <code>, %r11 */
504 *(void * volatile *) &tramp
[1] = ffi_closure_unix64
;
505 tramp
[5] = 0xba49; /* mov <data>, %r10 */
506 *(void * volatile *) &tramp
[6] = codeloc
;
508 /* Set the carry bit iff the function uses any sse registers.
509 This is clc or stc, together with the first byte of the jmp. */
510 tramp
[10] = cif
->flags
& (1 << 11) ? 0x49f9 : 0x49f8;
512 tramp
[11] = 0xe3ff; /* jmp *%r11 */
516 closure
->user_data
= user_data
;
522 ffi_closure_unix64_inner(ffi_closure
*closure
, void *rvalue
,
523 struct register_args
*reg_args
, char *argp
)
527 ffi_type
**arg_types
;
529 int gprcount
, ssecount
, ngpr
, nsse
;
533 avalue
= alloca(cif
->nargs
* sizeof(void *));
534 gprcount
= ssecount
= 0;
536 ret
= cif
->rtype
->type
;
537 if (ret
!= FFI_TYPE_VOID
)
539 enum x86_64_reg_class classes
[MAX_CLASSES
];
540 int n
= examine_argument (cif
->rtype
, classes
, 1, &ngpr
, &nsse
);
543 /* The return value goes in memory. Arrange for the closure
544 return value to go directly back to the original caller. */
545 rvalue
= (void *) reg_args
->gpr
[gprcount
++];
546 /* We don't have to do anything in asm for the return. */
549 else if (ret
== FFI_TYPE_STRUCT
&& n
== 2)
551 /* Mark which register the second word of the structure goes in. */
552 _Bool sse0
= SSE_CLASS_P (classes
[0]);
553 _Bool sse1
= SSE_CLASS_P (classes
[1]);
556 else if (sse0
&& !sse1
)
562 arg_types
= cif
->arg_types
;
564 for (i
= 0; i
< avn
; ++i
)
566 enum x86_64_reg_class classes
[MAX_CLASSES
];
569 n
= examine_argument (arg_types
[i
], classes
, 0, &ngpr
, &nsse
);
571 || gprcount
+ ngpr
> MAX_GPR_REGS
572 || ssecount
+ nsse
> MAX_SSE_REGS
)
574 long align
= arg_types
[i
]->alignment
;
576 /* Stack arguments are *always* at least 8 byte aligned. */
580 /* Pass this argument in memory. */
581 argp
= (void *) ALIGN (argp
, align
);
583 argp
+= arg_types
[i
]->size
;
585 /* If the argument is in a single register, or two consecutive
586 integer registers, then we can use that address directly. */
588 || (n
== 2 && !(SSE_CLASS_P (classes
[0])
589 || SSE_CLASS_P (classes
[1]))))
591 /* The argument is in a single register. */
592 if (SSE_CLASS_P (classes
[0]))
594 avalue
[i
] = ®_args
->sse
[ssecount
];
599 avalue
[i
] = ®_args
->gpr
[gprcount
];
603 /* Otherwise, allocate space to make them consecutive. */
606 char *a
= alloca (16);
610 for (j
= 0; j
< n
; j
++, a
+= 8)
612 if (SSE_CLASS_P (classes
[j
]))
613 memcpy (a
, ®_args
->sse
[ssecount
++], 8);
615 memcpy (a
, ®_args
->gpr
[gprcount
++], 8);
620 /* Invoke the closure. */
621 closure
->fun (cif
, rvalue
, avalue
, closure
->user_data
);
623 /* Tell assembly how to perform return type promotions. */
627 #endif /* __x86_64__ */