38 #define MAX_GPR_REGS 6
39 #define MAX_SSE_REGS 8
41 #if defined(__INTEL_COMPILER)
42 #include "xmmintrin.h"
43 #define UINT128 __m128
45 #if defined(__SUNPRO_C)
46 #include <sunmedia_types.h>
47 #define UINT128 __m128i
49 #define UINT128 __int128_t
63 UINT64 gpr[MAX_GPR_REGS];
64 union big_int_union sse[MAX_SSE_REGS];
67 extern void ffi_call_unix64 (
void *args,
unsigned long bytes,
unsigned flags,
68 void *raddr,
void (*fnaddr)(
void),
unsigned ssecount);
85 X86_64_INTEGERSI_CLASS,
92 X86_64_COMPLEX_X87_CLASS,
98 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
107 static enum x86_64_reg_class
108 merge_classes (
enum x86_64_reg_class class1,
enum x86_64_reg_class class2)
111 if (class1 == class2)
116 if (class1 == X86_64_NO_CLASS)
118 if (class2 == X86_64_NO_CLASS)
122 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
123 return X86_64_MEMORY_CLASS;
126 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
127 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
128 return X86_64_INTEGERSI_CLASS;
129 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
130 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
131 return X86_64_INTEGER_CLASS;
135 if (class1 == X86_64_X87_CLASS
136 || class1 == X86_64_X87UP_CLASS
137 || class1 == X86_64_COMPLEX_X87_CLASS
138 || class2 == X86_64_X87_CLASS
139 || class2 == X86_64_X87UP_CLASS
140 || class2 == X86_64_COMPLEX_X87_CLASS)
141 return X86_64_MEMORY_CLASS;
144 return X86_64_SSE_CLASS;
156 classify_argument (ffi_type *
type,
enum x86_64_reg_class classes[],
163 case FFI_TYPE_UINT16:
164 case FFI_TYPE_SINT16:
165 case FFI_TYPE_UINT32:
166 case FFI_TYPE_SINT32:
167 case FFI_TYPE_UINT64:
168 case FFI_TYPE_SINT64:
169 case FFI_TYPE_POINTER:
171 size_t size = byte_offset +
type->size;
175 classes[0] = X86_64_INTEGERSI_CLASS;
180 classes[0] = X86_64_INTEGER_CLASS;
185 classes[0] = X86_64_INTEGER_CLASS;
186 classes[1] = X86_64_INTEGERSI_CLASS;
191 classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
198 if (!(byte_offset % 8))
199 classes[0] = X86_64_SSESF_CLASS;
201 classes[0] = X86_64_SSE_CLASS;
203 case FFI_TYPE_DOUBLE:
204 classes[0] = X86_64_SSEDF_CLASS;
206 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
208 classes[0] = X86_64_X87_CLASS;
209 classes[1] = X86_64_X87UP_CLASS;
212 case FFI_TYPE_STRUCT:
214 const size_t UNITS_PER_WORD = 8;
215 size_t words = (
type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
218 enum x86_64_reg_class subclasses[MAX_CLASSES];
224 for (
i = 0;
i < words;
i++)
225 classes[
i] = X86_64_NO_CLASS;
231 classes[0] = X86_64_NO_CLASS;
240 byte_offset =
ALIGN (byte_offset, (*ptr)->alignment);
242 num = classify_argument (*
ptr, subclasses, byte_offset % 8);
245 for (
i = 0;
i < num;
i++)
247 size_t pos = byte_offset / 8;
249 merge_classes (subclasses[
i], classes[
i + pos]);
252 byte_offset += (*ptr)->size;
261 if (classes[0] != X86_64_SSE_CLASS)
264 for (
i = 1;
i < words;
i++)
265 if (classes[
i] != X86_64_SSEUP_CLASS)
270 for (
i = 0;
i < words;
i++)
274 if (classes[
i] == X86_64_MEMORY_CLASS)
279 if (classes[
i] == X86_64_SSEUP_CLASS
280 && classes[
i - 1] != X86_64_SSE_CLASS
281 && classes[
i - 1] != X86_64_SSEUP_CLASS)
285 classes[
i] = X86_64_SSE_CLASS;
290 if (classes[
i] == X86_64_X87UP_CLASS
291 && (classes[
i - 1] != X86_64_X87_CLASS))
312 examine_argument (ffi_type *
type,
enum x86_64_reg_class classes[MAX_CLASSES],
313 _Bool in_return,
int *pngpr,
int *pnsse)
318 n = classify_argument (
type, classes, 0);
323 for (
i = 0;
i <
n; ++
i)
326 case X86_64_INTEGER_CLASS:
327 case X86_64_INTEGERSI_CLASS:
330 case X86_64_SSE_CLASS:
331 case X86_64_SSESF_CLASS:
332 case X86_64_SSEDF_CLASS:
335 case X86_64_NO_CLASS:
336 case X86_64_SSEUP_CLASS:
338 case X86_64_X87_CLASS:
339 case X86_64_X87UP_CLASS:
340 case X86_64_COMPLEX_X87_CLASS:
341 return in_return != 0;
357 int gprcount, ssecount,
i, avn, ngpr, nsse, flags;
358 enum x86_64_reg_class classes[MAX_CLASSES];
361 gprcount = ssecount = 0;
363 flags = cif->rtype->type;
364 if (flags != FFI_TYPE_VOID)
366 n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
373 flags = FFI_TYPE_VOID;
375 else if (flags == FFI_TYPE_STRUCT)
378 _Bool sse0 = SSE_CLASS_P (classes[0]);
379 _Bool sse1 =
n == 2 && SSE_CLASS_P (classes[1]);
382 else if (!sse0 && sse1)
384 else if (sse0 && sse1)
387 flags |= cif->rtype->size << 12;
394 for (bytes = 0,
i = 0, avn = cif->nargs;
i < avn;
i++)
396 if (examine_argument (cif->arg_types[
i], classes, 0, &ngpr, &nsse) == 0
397 || gprcount + ngpr > MAX_GPR_REGS
398 || ssecount + nsse > MAX_SSE_REGS)
400 long align = cif->arg_types[
i]->alignment;
405 bytes =
ALIGN (bytes, align);
406 bytes += cif->arg_types[
i]->size;
423 ffi_call (ffi_cif *cif,
void (*fn)(
void),
void *rvalue,
void **avalue)
425 enum x86_64_reg_class classes[MAX_CLASSES];
427 ffi_type **arg_types;
428 int gprcount, ssecount, ngpr, nsse,
i, avn;
430 struct register_args *reg_args;
438 ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
439 && (cif->flags & 0xff) == FFI_TYPE_VOID);
440 if (rvalue ==
NULL && ret_in_memory)
441 rvalue =
alloca (cif->rtype->size);
444 stack =
alloca (
sizeof (
struct register_args) + cif->bytes + 4*8);
445 reg_args = (
struct register_args *) stack;
446 argp = stack +
sizeof (
struct register_args);
448 gprcount = ssecount = 0;
453 reg_args->gpr[gprcount++] = (
unsigned long) rvalue;
456 arg_types = cif->arg_types;
458 for (
i = 0;
i < avn; ++
i)
460 size_t n,
size = arg_types[
i]->size;
462 n = examine_argument (arg_types[
i], classes, 0, &ngpr, &nsse);
464 || gprcount + ngpr > MAX_GPR_REGS
465 || ssecount + nsse > MAX_SSE_REGS)
467 long align = arg_types[
i]->alignment;
474 argp = (
void *)
ALIGN (argp, align);
481 char *a = (
char *) avalue[
i];
484 for (j = 0; j <
n; j++, a += 8,
size -= 8)
488 case X86_64_INTEGER_CLASS:
489 case X86_64_INTEGERSI_CLASS:
494 switch (arg_types[
i]->
type)
497 *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
499 case FFI_TYPE_SINT16:
500 *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
502 case FFI_TYPE_SINT32:
503 *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
506 reg_args->gpr[gprcount] = 0;
511 case X86_64_SSE_CLASS:
512 case X86_64_SSEDF_CLASS:
513 reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
515 case X86_64_SSESF_CLASS:
516 reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
525 ffi_call_unix64 (stack, cif->bytes + sizeof (
struct register_args),
526 cif->flags, rvalue, fn, ssecount);
530 extern void ffi_closure_unix64(
void);
535 void (*fun)(ffi_cif*,
void*,
void**,
void*),
539 volatile unsigned short *tramp;
548 tramp = (
volatile unsigned short *) &closure->tramp[0];
551 *((
unsigned long long *
volatile) &tramp[1])
552 = (
unsigned long) ffi_closure_unix64;
554 *((
unsigned long long *
volatile) &tramp[6])
555 = (
unsigned long) codeloc;
559 tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
565 closure->user_data = user_data;
571 ffi_closure_unix64_inner(ffi_closure *closure,
void *rvalue,
572 struct register_args *reg_args,
char *argp)
576 ffi_type **arg_types;
578 int gprcount, ssecount, ngpr, nsse;
582 avalue =
alloca(cif->nargs *
sizeof(
void *));
583 gprcount = ssecount = 0;
585 ret = cif->rtype->type;
586 if (ret != FFI_TYPE_VOID)
588 enum x86_64_reg_class classes[MAX_CLASSES];
589 size_t n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
594 rvalue = (
void *) (
unsigned long) reg_args->gpr[gprcount++];
598 else if (ret == FFI_TYPE_STRUCT &&
n == 2)
601 _Bool sse0 = SSE_CLASS_P (classes[0]);
602 _Bool sse1 = SSE_CLASS_P (classes[1]);
605 else if (sse0 && !sse1)
611 arg_types = cif->arg_types;
613 for (
i = 0;
i < avn; ++
i)
615 enum x86_64_reg_class classes[MAX_CLASSES];
618 n = examine_argument (arg_types[
i], classes, 0, &ngpr, &nsse);
620 || gprcount + ngpr > MAX_GPR_REGS
621 || ssecount + nsse > MAX_SSE_REGS)
623 long align = arg_types[
i]->alignment;
630 argp = (
void *)
ALIGN (argp, align);
632 argp += arg_types[
i]->size;
637 || (
n == 2 && !(SSE_CLASS_P (classes[0])
638 || SSE_CLASS_P (classes[1]))))
641 if (SSE_CLASS_P (classes[0]))
643 avalue[
i] = ®_args->sse[ssecount];
648 avalue[
i] = ®_args->gpr[gprcount];
659 for (j = 0; j <
n; j++, a += 8)
661 if (SSE_CLASS_P (classes[j]))
662 memcpy (a, ®_args->sse[ssecount++], 8);
664 memcpy (a, ®_args->gpr[gprcount++], 8);
670 closure->fun (cif, rvalue, avalue, closure->user_data);