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