Fix -Wsign-compare warnings in x86/ffi64.c
[libffi.git] / src / x86 / ffi64.c
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>
6
7 x86-64 Foreign Function Interface
8
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:
16
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
19
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 ----------------------------------------------------------------------- */
29
30 #include <ffi.h>
31 #include <ffi_common.h>
32
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdint.h>
36 #include "internal64.h"
37
38 #ifdef __x86_64__
39
40 #define MAX_GPR_REGS 6
41 #define MAX_SSE_REGS 8
42
43 #if defined(__INTEL_COMPILER)
44 #include "xmmintrin.h"
45 #define UINT128 __m128
46 #else
47 #if defined(__SUNPRO_C)
48 #include <sunmedia_types.h>
49 #define UINT128 __m128i
50 #else
51 #define UINT128 __int128_t
52 #endif
53 #endif
54
55 union big_int_union
56 {
57 UINT32 i32;
58 UINT64 i64;
59 UINT128 i128;
60 };
61
62 struct register_args
63 {
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 */
69 };
70
71 extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
72 void *raddr, void (*fnaddr)(void)) FFI_HIDDEN;
73
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. */
76
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.
82
83 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
84 whenever possible (upper half does contain padding). */
85 enum x86_64_reg_class
86 {
87 X86_64_NO_CLASS,
88 X86_64_INTEGER_CLASS,
89 X86_64_INTEGERSI_CLASS,
90 X86_64_SSE_CLASS,
91 X86_64_SSESF_CLASS,
92 X86_64_SSEDF_CLASS,
93 X86_64_SSEUP_CLASS,
94 X86_64_X87_CLASS,
95 X86_64_X87UP_CLASS,
96 X86_64_COMPLEX_X87_CLASS,
97 X86_64_MEMORY_CLASS
98 };
99
100 #define MAX_CLASSES 4
101
102 #define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
103
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. */
107
108 /* Return the union class of CLASS1 and CLASS2.
109 See the x86-64 PS ABI for details. */
110
111 static enum x86_64_reg_class
112 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
113 {
114 /* Rule #1: If both classes are equal, this is the resulting class. */
115 if (class1 == class2)
116 return class1;
117
118 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
119 the other class. */
120 if (class1 == X86_64_NO_CLASS)
121 return class2;
122 if (class2 == X86_64_NO_CLASS)
123 return class1;
124
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;
128
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;
136
137 /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
138 MEMORY is used. */
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;
146
147 /* Rule #6: Otherwise class SSE is used. */
148 return X86_64_SSE_CLASS;
149 }
150
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.
156
157 See the x86-64 PS ABI for details.
158 */
159 static size_t
160 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
161 size_t byte_offset)
162 {
163 switch (type->type)
164 {
165 case FFI_TYPE_UINT8:
166 case FFI_TYPE_SINT8:
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:
174 do_integer:
175 {
176 size_t size = byte_offset + type->size;
177
178 if (size <= 4)
179 {
180 classes[0] = X86_64_INTEGERSI_CLASS;
181 return 1;
182 }
183 else if (size <= 8)
184 {
185 classes[0] = X86_64_INTEGER_CLASS;
186 return 1;
187 }
188 else if (size <= 12)
189 {
190 classes[0] = X86_64_INTEGER_CLASS;
191 classes[1] = X86_64_INTEGERSI_CLASS;
192 return 2;
193 }
194 else if (size <= 16)
195 {
196 classes[0] = classes[1] = X86_64_INTEGER_CLASS;
197 return 2;
198 }
199 else
200 FFI_ASSERT (0);
201 }
202 case FFI_TYPE_FLOAT:
203 if (!(byte_offset % 8))
204 classes[0] = X86_64_SSESF_CLASS;
205 else
206 classes[0] = X86_64_SSE_CLASS;
207 return 1;
208 case FFI_TYPE_DOUBLE:
209 classes[0] = X86_64_SSEDF_CLASS;
210 return 1;
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;
215 return 2;
216 #endif
217 case FFI_TYPE_STRUCT:
218 {
219 const size_t UNITS_PER_WORD = 8;
220 size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
221 ffi_type **ptr;
222 unsigned int i;
223 enum x86_64_reg_class subclasses[MAX_CLASSES];
224
225 /* If the struct is larger than 32 bytes, pass it on the stack. */
226 if (type->size > 32)
227 return 0;
228
229 for (i = 0; i < words; i++)
230 classes[i] = X86_64_NO_CLASS;
231
232 /* Zero sized arrays or structures are NO_CLASS. We return 0 to
233 signalize memory class, so handle it as special case. */
234 if (!words)
235 {
236 case FFI_TYPE_VOID:
237 classes[0] = X86_64_NO_CLASS;
238 return 1;
239 }
240
241 /* Merge the fields of structure. */
242 for (ptr = type->elements; *ptr != NULL; ptr++)
243 {
244 size_t num;
245
246 byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
247
248 num = classify_argument (*ptr, subclasses, byte_offset % 8);
249 if (num == 0)
250 return 0;
251 for (i = 0; i < num; i++)
252 {
253 size_t pos = byte_offset / 8;
254 classes[i + pos] =
255 merge_classes (subclasses[i], classes[i + pos]);
256 }
257
258 byte_offset += (*ptr)->size;
259 }
260
261 if (words > 2)
262 {
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
266 memory. */
267 if (classes[0] != X86_64_SSE_CLASS)
268 return 0;
269
270 for (i = 1; i < words; i++)
271 if (classes[i] != X86_64_SSEUP_CLASS)
272 return 0;
273 }
274
275 /* Final merger cleanup. */
276 for (i = 0; i < words; i++)
277 {
278 /* If one class is MEMORY, everything should be passed in
279 memory. */
280 if (classes[i] == X86_64_MEMORY_CLASS)
281 return 0;
282
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)
288 {
289 /* The first one should never be X86_64_SSEUP_CLASS. */
290 FFI_ASSERT (i != 0);
291 classes[i] = X86_64_SSE_CLASS;
292 }
293
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))
298 {
299 /* The first one should never be X86_64_X87UP_CLASS. */
300 FFI_ASSERT (i != 0);
301 return 0;
302 }
303 }
304 return words;
305 }
306 case FFI_TYPE_COMPLEX:
307 {
308 ffi_type *inner = type->elements[0];
309 switch (inner->type)
310 {
311 case FFI_TYPE_INT:
312 case FFI_TYPE_UINT8:
313 case FFI_TYPE_SINT8:
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:
320 goto do_integer;
321
322 case FFI_TYPE_FLOAT:
323 classes[0] = X86_64_SSE_CLASS;
324 if (byte_offset % 8)
325 {
326 classes[1] = X86_64_SSESF_CLASS;
327 return 2;
328 }
329 return 1;
330 case FFI_TYPE_DOUBLE:
331 classes[0] = classes[1] = X86_64_SSEDF_CLASS;
332 return 2;
333 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
334 case FFI_TYPE_LONGDOUBLE:
335 classes[0] = X86_64_COMPLEX_X87_CLASS;
336 return 1;
337 #endif
338 }
339 }
340 }
341 abort();
342 }
343
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. */
347
348 static size_t
349 examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
350 _Bool in_return, int *pngpr, int *pnsse)
351 {
352 size_t n;
353 unsigned int i;
354 int ngpr, nsse;
355
356 n = classify_argument (type, classes, 0);
357 if (n == 0)
358 return 0;
359
360 ngpr = nsse = 0;
361 for (i = 0; i < n; ++i)
362 switch (classes[i])
363 {
364 case X86_64_INTEGER_CLASS:
365 case X86_64_INTEGERSI_CLASS:
366 ngpr++;
367 break;
368 case X86_64_SSE_CLASS:
369 case X86_64_SSESF_CLASS:
370 case X86_64_SSEDF_CLASS:
371 nsse++;
372 break;
373 case X86_64_NO_CLASS:
374 case X86_64_SSEUP_CLASS:
375 break;
376 case X86_64_X87_CLASS:
377 case X86_64_X87UP_CLASS:
378 case X86_64_COMPLEX_X87_CLASS:
379 return in_return != 0;
380 default:
381 abort ();
382 }
383
384 *pngpr = ngpr;
385 *pnsse = nsse;
386
387 return n;
388 }
389
390 /* Perform machine dependent cif processing. */
391
392 extern ffi_status
393 ffi_prep_cif_machdep_efi64(ffi_cif *cif);
394
395 ffi_status
396 ffi_prep_cif_machdep (ffi_cif *cif)
397 {
398 int gprcount, ssecount, i, avn, ngpr, nsse, flags;
399 enum x86_64_reg_class classes[MAX_CLASSES];
400 size_t bytes, n, rtype_size;
401 ffi_type *rtype;
402
403 if (cif->abi == FFI_EFI64)
404 return ffi_prep_cif_machdep_efi64(cif);
405 if (cif->abi != FFI_UNIX64)
406 return FFI_BAD_ABI;
407
408 gprcount = ssecount = 0;
409
410 rtype = cif->rtype;
411 rtype_size = rtype->size;
412 switch (rtype->type)
413 {
414 case FFI_TYPE_VOID:
415 flags = UNIX64_RET_VOID;
416 break;
417 case FFI_TYPE_UINT8:
418 flags = UNIX64_RET_UINT8;
419 break;
420 case FFI_TYPE_SINT8:
421 flags = UNIX64_RET_SINT8;
422 break;
423 case FFI_TYPE_UINT16:
424 flags = UNIX64_RET_UINT16;
425 break;
426 case FFI_TYPE_SINT16:
427 flags = UNIX64_RET_SINT16;
428 break;
429 case FFI_TYPE_UINT32:
430 flags = UNIX64_RET_UINT32;
431 break;
432 case FFI_TYPE_INT:
433 case FFI_TYPE_SINT32:
434 flags = UNIX64_RET_SINT32;
435 break;
436 case FFI_TYPE_UINT64:
437 case FFI_TYPE_SINT64:
438 flags = UNIX64_RET_INT64;
439 break;
440 case FFI_TYPE_POINTER:
441 flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
442 break;
443 case FFI_TYPE_FLOAT:
444 flags = UNIX64_RET_XMM32;
445 break;
446 case FFI_TYPE_DOUBLE:
447 flags = UNIX64_RET_XMM64;
448 break;
449 case FFI_TYPE_LONGDOUBLE:
450 flags = UNIX64_RET_X87;
451 break;
452 case FFI_TYPE_STRUCT:
453 n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
454 if (n == 0)
455 {
456 /* The return value is passed in memory. A pointer to that
457 memory is the first argument. Allocate a register for it. */
458 gprcount++;
459 /* We don't have to do anything in asm for the return. */
460 flags = UNIX64_RET_VOID | UNIX64_FLAG_RET_IN_MEM;
461 }
462 else
463 {
464 _Bool sse0 = SSE_CLASS_P (classes[0]);
465
466 if (rtype_size == 4 && sse0)
467 flags = UNIX64_RET_XMM32;
468 else if (rtype_size == 8)
469 flags = sse0 ? UNIX64_RET_XMM64 : UNIX64_RET_INT64;
470 else
471 {
472 _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
473 if (sse0 && sse1)
474 flags = UNIX64_RET_ST_XMM0_XMM1;
475 else if (sse0)
476 flags = UNIX64_RET_ST_XMM0_RAX;
477 else if (sse1)
478 flags = UNIX64_RET_ST_RAX_XMM0;
479 else
480 flags = UNIX64_RET_ST_RAX_RDX;
481 flags |= rtype_size << UNIX64_SIZE_SHIFT;
482 }
483 }
484 break;
485 case FFI_TYPE_COMPLEX:
486 switch (rtype->elements[0]->type)
487 {
488 case FFI_TYPE_UINT8:
489 case FFI_TYPE_SINT8:
490 case FFI_TYPE_UINT16:
491 case FFI_TYPE_SINT16:
492 case FFI_TYPE_INT:
493 case FFI_TYPE_UINT32:
494 case FFI_TYPE_SINT32:
495 case FFI_TYPE_UINT64:
496 case FFI_TYPE_SINT64:
497 flags = UNIX64_RET_ST_RAX_RDX | (rtype_size << UNIX64_SIZE_SHIFT);
498 break;
499 case FFI_TYPE_FLOAT:
500 flags = UNIX64_RET_XMM64;
501 break;
502 case FFI_TYPE_DOUBLE:
503 flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT);
504 break;
505 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
506 case FFI_TYPE_LONGDOUBLE:
507 flags = UNIX64_RET_X87_2;
508 break;
509 #endif
510 default:
511 return FFI_BAD_TYPEDEF;
512 }
513 break;
514 default:
515 return FFI_BAD_TYPEDEF;
516 }
517
518 /* Go over all arguments and determine the way they should be passed.
519 If it's in a register and there is space for it, let that be so. If
520 not, add it's size to the stack byte count. */
521 for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
522 {
523 if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
524 || gprcount + ngpr > MAX_GPR_REGS
525 || ssecount + nsse > MAX_SSE_REGS)
526 {
527 long align = cif->arg_types[i]->alignment;
528
529 if (align < 8)
530 align = 8;
531
532 bytes = ALIGN (bytes, align);
533 bytes += cif->arg_types[i]->size;
534 }
535 else
536 {
537 gprcount += ngpr;
538 ssecount += nsse;
539 }
540 }
541 if (ssecount)
542 flags |= UNIX64_FLAG_XMM_ARGS;
543
544 cif->flags = flags;
545 cif->bytes = ALIGN (bytes, 8);
546
547 return FFI_OK;
548 }
549
550 static void
551 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
552 void **avalue, void *closure)
553 {
554 enum x86_64_reg_class classes[MAX_CLASSES];
555 char *stack, *argp;
556 ffi_type **arg_types;
557 int gprcount, ssecount, ngpr, nsse, i, avn, flags;
558 struct register_args *reg_args;
559
560 /* Can't call 32-bit mode from 64-bit mode. */
561 FFI_ASSERT (cif->abi == FFI_UNIX64);
562
563 /* If the return value is a struct and we don't have a return value
564 address then we need to make one. Otherwise we can ignore it. */
565 flags = cif->flags;
566 if (rvalue == NULL)
567 {
568 if (flags & UNIX64_FLAG_RET_IN_MEM)
569 rvalue = alloca (cif->rtype->size);
570 else
571 flags = UNIX64_RET_VOID;
572 }
573
574 /* Allocate the space for the arguments, plus 4 words of temp space. */
575 stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
576 reg_args = (struct register_args *) stack;
577 argp = stack + sizeof (struct register_args);
578
579 reg_args->r10 = (uintptr_t) closure;
580
581 gprcount = ssecount = 0;
582
583 /* If the return value is passed in memory, add the pointer as the
584 first integer argument. */
585 if (flags & UNIX64_FLAG_RET_IN_MEM)
586 reg_args->gpr[gprcount++] = (unsigned long) rvalue;
587
588 avn = cif->nargs;
589 arg_types = cif->arg_types;
590
591 for (i = 0; i < avn; ++i)
592 {
593 size_t n, size = arg_types[i]->size;
594
595 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
596 if (n == 0
597 || gprcount + ngpr > MAX_GPR_REGS
598 || ssecount + nsse > MAX_SSE_REGS)
599 {
600 long align = arg_types[i]->alignment;
601
602 /* Stack arguments are *always* at least 8 byte aligned. */
603 if (align < 8)
604 align = 8;
605
606 /* Pass this argument in memory. */
607 argp = (void *) ALIGN (argp, align);
608 memcpy (argp, avalue[i], size);
609 argp += size;
610 }
611 else
612 {
613 /* The argument is passed entirely in registers. */
614 char *a = (char *) avalue[i];
615 unsigned int j;
616
617 for (j = 0; j < n; j++, a += 8, size -= 8)
618 {
619 switch (classes[j])
620 {
621 case X86_64_NO_CLASS:
622 case X86_64_SSEUP_CLASS:
623 break;
624 case X86_64_INTEGER_CLASS:
625 case X86_64_INTEGERSI_CLASS:
626 /* Sign-extend integer arguments passed in general
627 purpose registers, to cope with the fact that
628 LLVM incorrectly assumes that this will be done
629 (the x86-64 PS ABI does not specify this). */
630 switch (arg_types[i]->type)
631 {
632 case FFI_TYPE_SINT8:
633 reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
634 break;
635 case FFI_TYPE_SINT16:
636 reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
637 break;
638 case FFI_TYPE_SINT32:
639 reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
640 break;
641 default:
642 reg_args->gpr[gprcount] = 0;
643 memcpy (&reg_args->gpr[gprcount], a, size);
644 }
645 gprcount++;
646 break;
647 case X86_64_SSE_CLASS:
648 case X86_64_SSEDF_CLASS:
649 reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
650 break;
651 case X86_64_SSESF_CLASS:
652 reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
653 break;
654 default:
655 abort();
656 }
657 }
658 }
659 }
660 reg_args->rax = ssecount;
661
662 ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
663 flags, rvalue, fn);
664 }
665
666 extern void
667 ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
668
669 void
670 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
671 {
672 if (cif->abi == FFI_EFI64)
673 return ffi_call_efi64(cif, fn, rvalue, avalue);
674 ffi_call_int (cif, fn, rvalue, avalue, NULL);
675 }
676
677 extern void
678 ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue,
679 void **avalue, void *closure);
680
681 void
682 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
683 void **avalue, void *closure)
684 {
685 if (cif->abi == FFI_EFI64)
686 ffi_call_go_efi64(cif, fn, rvalue, avalue, closure);
687 ffi_call_int (cif, fn, rvalue, avalue, closure);
688 }
689
690
691 extern void ffi_closure_unix64(void) FFI_HIDDEN;
692 extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
693
694 extern ffi_status
695 ffi_prep_closure_loc_efi64(ffi_closure* closure,
696 ffi_cif* cif,
697 void (*fun)(ffi_cif*, void*, void**, void*),
698 void *user_data,
699 void *codeloc);
700
701 ffi_status
702 ffi_prep_closure_loc (ffi_closure* closure,
703 ffi_cif* cif,
704 void (*fun)(ffi_cif*, void*, void**, void*),
705 void *user_data,
706 void *codeloc)
707 {
708 static const unsigned char trampoline[16] = {
709 /* leaq -0x7(%rip),%r10 # 0x0 */
710 0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
711 /* jmpq *0x3(%rip) # 0x10 */
712 0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
713 /* nopl (%rax) */
714 0x0f, 0x1f, 0x00
715 };
716 void (*dest)(void);
717 char *tramp = closure->tramp;
718
719 if (cif->abi == FFI_EFI64)
720 return ffi_prep_closure_loc_efi64(closure, cif, fun, user_data, codeloc);
721 if (cif->abi != FFI_UNIX64)
722 return FFI_BAD_ABI;
723
724 if (cif->flags & UNIX64_FLAG_XMM_ARGS)
725 dest = ffi_closure_unix64_sse;
726 else
727 dest = ffi_closure_unix64;
728
729 memcpy (tramp, trampoline, sizeof(trampoline));
730 *(UINT64 *)(tramp + 16) = (uintptr_t)dest;
731
732 closure->cif = cif;
733 closure->fun = fun;
734 closure->user_data = user_data;
735
736 return FFI_OK;
737 }
738
739 int FFI_HIDDEN
740 ffi_closure_unix64_inner(ffi_cif *cif,
741 void (*fun)(ffi_cif*, void*, void**, void*),
742 void *user_data,
743 void *rvalue,
744 struct register_args *reg_args,
745 char *argp)
746 {
747 void **avalue;
748 ffi_type **arg_types;
749 long i, avn;
750 int gprcount, ssecount, ngpr, nsse;
751 int flags;
752
753 avn = cif->nargs;
754 flags = cif->flags;
755 avalue = alloca(avn * sizeof(void *));
756 gprcount = ssecount = 0;
757
758 if (flags & UNIX64_FLAG_RET_IN_MEM)
759 {
760 /* On return, %rax will contain the address that was passed
761 by the caller in %rdi. */
762 void *r = (void *)(uintptr_t)reg_args->gpr[gprcount++];
763 *(void **)rvalue = r;
764 rvalue = r;
765 flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
766 }
767
768 arg_types = cif->arg_types;
769 for (i = 0; i < avn; ++i)
770 {
771 enum x86_64_reg_class classes[MAX_CLASSES];
772 size_t n;
773
774 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
775 if (n == 0
776 || gprcount + ngpr > MAX_GPR_REGS
777 || ssecount + nsse > MAX_SSE_REGS)
778 {
779 long align = arg_types[i]->alignment;
780
781 /* Stack arguments are *always* at least 8 byte aligned. */
782 if (align < 8)
783 align = 8;
784
785 /* Pass this argument in memory. */
786 argp = (void *) ALIGN (argp, align);
787 avalue[i] = argp;
788 argp += arg_types[i]->size;
789 }
790 /* If the argument is in a single register, or two consecutive
791 integer registers, then we can use that address directly. */
792 else if (n == 1
793 || (n == 2 && !(SSE_CLASS_P (classes[0])
794 || SSE_CLASS_P (classes[1]))))
795 {
796 /* The argument is in a single register. */
797 if (SSE_CLASS_P (classes[0]))
798 {
799 avalue[i] = &reg_args->sse[ssecount];
800 ssecount += n;
801 }
802 else
803 {
804 avalue[i] = &reg_args->gpr[gprcount];
805 gprcount += n;
806 }
807 }
808 /* Otherwise, allocate space to make them consecutive. */
809 else
810 {
811 char *a = alloca (16);
812 unsigned int j;
813
814 avalue[i] = a;
815 for (j = 0; j < n; j++, a += 8)
816 {
817 if (SSE_CLASS_P (classes[j]))
818 memcpy (a, &reg_args->sse[ssecount++], 8);
819 else
820 memcpy (a, &reg_args->gpr[gprcount++], 8);
821 }
822 }
823 }
824
825 /* Invoke the closure. */
826 fun (cif, rvalue, avalue, user_data);
827
828 /* Tell assembly how to perform return type promotions. */
829 return flags;
830 }
831
832 extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
833 extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
834
835 extern ffi_status
836 ffi_prep_go_closure_efi64(ffi_go_closure* closure, ffi_cif* cif,
837 void (*fun)(ffi_cif*, void*, void**, void*));
838
839 ffi_status
840 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
841 void (*fun)(ffi_cif*, void*, void**, void*))
842 {
843 if (cif->abi == FFI_EFI64)
844 return ffi_prep_go_closure_efi64(closure, cif, fun);
845 if (cif->abi != FFI_UNIX64)
846 return FFI_BAD_ABI;
847
848 closure->tramp = (cif->flags & UNIX64_FLAG_XMM_ARGS
849 ? ffi_go_closure_unix64_sse
850 : ffi_go_closure_unix64);
851 closure->cif = cif;
852 closure->fun = fun;
853
854 return FFI_OK;
855 }
856
857 #endif /* __x86_64__ */