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
merge_classes(enum x86_64_reg_class class1,enum x86_64_reg_class class2)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
classify_argument(ffi_type * type,enum x86_64_reg_class classes[],size_t byte_offset)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 	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
examine_argument(ffi_type * type,enum x86_64_reg_class classes[MAX_CLASSES],_Bool in_return,int * pngpr,int * pnsse)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   int i, ngpr, nsse;
354 
355   n = classify_argument (type, classes, 0);
356   if (n == 0)
357     return 0;
358 
359   ngpr = nsse = 0;
360   for (i = 0; i < n; ++i)
361     switch (classes[i])
362       {
363       case X86_64_INTEGER_CLASS:
364       case X86_64_INTEGERSI_CLASS:
365 	ngpr++;
366 	break;
367       case X86_64_SSE_CLASS:
368       case X86_64_SSESF_CLASS:
369       case X86_64_SSEDF_CLASS:
370 	nsse++;
371 	break;
372       case X86_64_NO_CLASS:
373       case X86_64_SSEUP_CLASS:
374 	break;
375       case X86_64_X87_CLASS:
376       case X86_64_X87UP_CLASS:
377       case X86_64_COMPLEX_X87_CLASS:
378 	return in_return != 0;
379       default:
380 	abort ();
381       }
382 
383   *pngpr = ngpr;
384   *pnsse = nsse;
385 
386   return n;
387 }
388 
389 /* Perform machine dependent cif processing.  */
390 
391 ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)392 ffi_prep_cif_machdep (ffi_cif *cif)
393 {
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;
397   ffi_type *rtype;
398 
399   if (cif->abi != FFI_UNIX64)
400     return FFI_BAD_ABI;
401 
402   gprcount = ssecount = 0;
403 
404   rtype = cif->rtype;
405   rtype_size = rtype->size;
406   switch (rtype->type)
407     {
408     case FFI_TYPE_VOID:
409       flags = UNIX64_RET_VOID;
410       break;
411     case FFI_TYPE_UINT8:
412       flags = UNIX64_RET_UINT8;
413       break;
414     case FFI_TYPE_SINT8:
415       flags = UNIX64_RET_SINT8;
416       break;
417     case FFI_TYPE_UINT16:
418       flags = UNIX64_RET_UINT16;
419       break;
420     case FFI_TYPE_SINT16:
421       flags = UNIX64_RET_SINT16;
422       break;
423     case FFI_TYPE_UINT32:
424       flags = UNIX64_RET_UINT32;
425       break;
426     case FFI_TYPE_INT:
427     case FFI_TYPE_SINT32:
428       flags = UNIX64_RET_SINT32;
429       break;
430     case FFI_TYPE_UINT64:
431     case FFI_TYPE_SINT64:
432       flags = UNIX64_RET_INT64;
433       break;
434     case FFI_TYPE_POINTER:
435       flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
436       break;
437     case FFI_TYPE_FLOAT:
438       flags = UNIX64_RET_XMM32;
439       break;
440     case FFI_TYPE_DOUBLE:
441       flags = UNIX64_RET_XMM64;
442       break;
443     case FFI_TYPE_LONGDOUBLE:
444       flags = UNIX64_RET_X87;
445       break;
446     case FFI_TYPE_STRUCT:
447       n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
448       if (n == 0)
449 	{
450 	  /* The return value is passed in memory.  A pointer to that
451 	     memory is the first argument.  Allocate a register for it.  */
452 	  gprcount++;
453 	  /* We don't have to do anything in asm for the return.  */
454 	  flags = UNIX64_RET_VOID | UNIX64_FLAG_RET_IN_MEM;
455 	}
456       else
457 	{
458 	  _Bool sse0 = SSE_CLASS_P (classes[0]);
459 
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;
464 	  else
465 	    {
466 	      _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
467 	      if (sse0 && sse1)
468 		flags = UNIX64_RET_ST_XMM0_XMM1;
469 	      else if (sse0)
470 		flags = UNIX64_RET_ST_XMM0_RAX;
471 	      else if (sse1)
472 		flags = UNIX64_RET_ST_RAX_XMM0;
473 	      else
474 		flags = UNIX64_RET_ST_RAX_RDX;
475 	      flags |= rtype_size << UNIX64_SIZE_SHIFT;
476 	    }
477 	}
478       break;
479     case FFI_TYPE_COMPLEX:
480       switch (rtype->elements[0]->type)
481 	{
482 	case FFI_TYPE_UINT8:
483 	case FFI_TYPE_SINT8:
484 	case FFI_TYPE_UINT16:
485 	case FFI_TYPE_SINT16:
486 	case FFI_TYPE_INT:
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);
492 	  break;
493 	case FFI_TYPE_FLOAT:
494 	  flags = UNIX64_RET_XMM64;
495 	  break;
496 	case FFI_TYPE_DOUBLE:
497 	  flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT);
498 	  break;
499 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
500 	case FFI_TYPE_LONGDOUBLE:
501 	  flags = UNIX64_RET_X87_2;
502 	  break;
503 #endif
504 	default:
505 	  return FFI_BAD_TYPEDEF;
506 	}
507       break;
508     default:
509       return FFI_BAD_TYPEDEF;
510     }
511 
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++)
516     {
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)
520 	{
521 	  long align = cif->arg_types[i]->alignment;
522 
523 	  if (align < 8)
524 	    align = 8;
525 
526 	  bytes = ALIGN (bytes, align);
527 	  bytes += cif->arg_types[i]->size;
528 	}
529       else
530 	{
531 	  gprcount += ngpr;
532 	  ssecount += nsse;
533 	}
534     }
535   if (ssecount)
536     flags |= UNIX64_FLAG_XMM_ARGS;
537 
538   cif->flags = flags;
539   cif->bytes = ALIGN (bytes, 8);
540 
541   return FFI_OK;
542 }
543 
544 static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)545 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
546 	      void **avalue, void *closure)
547 {
548   enum x86_64_reg_class classes[MAX_CLASSES];
549   char *stack, *argp;
550   ffi_type **arg_types;
551   int gprcount, ssecount, ngpr, nsse, i, avn, flags;
552   struct register_args *reg_args;
553 
554   /* Can't call 32-bit mode from 64-bit mode.  */
555   FFI_ASSERT (cif->abi == FFI_UNIX64);
556 
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.  */
559   flags = cif->flags;
560   if (rvalue == NULL)
561     {
562       if (flags & UNIX64_FLAG_RET_IN_MEM)
563 	rvalue = alloca (cif->rtype->size);
564       else
565 	flags = UNIX64_RET_VOID;
566     }
567 
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);
572 
573   reg_args->r10 = (uintptr_t) closure;
574 
575   gprcount = ssecount = 0;
576 
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;
581 
582   avn = cif->nargs;
583   arg_types = cif->arg_types;
584 
585   for (i = 0; i < avn; ++i)
586     {
587       size_t n, size = arg_types[i]->size;
588 
589       n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
590       if (n == 0
591 	  || gprcount + ngpr > MAX_GPR_REGS
592 	  || ssecount + nsse > MAX_SSE_REGS)
593 	{
594 	  long align = arg_types[i]->alignment;
595 
596 	  /* Stack arguments are *always* at least 8 byte aligned.  */
597 	  if (align < 8)
598 	    align = 8;
599 
600 	  /* Pass this argument in memory.  */
601 	  argp = (void *) ALIGN (argp, align);
602 	  memcpy (argp, avalue[i], size);
603 	  argp += size;
604 	}
605       else
606 	{
607 	  /* The argument is passed entirely in registers.  */
608 	  char *a = (char *) avalue[i];
609 	  int j;
610 
611 	  for (j = 0; j < n; j++, a += 8, size -= 8)
612 	    {
613 	      switch (classes[j])
614 		{
615 		case X86_64_NO_CLASS:
616 		case X86_64_SSEUP_CLASS:
617 		  break;
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)
625 		    {
626 		    case FFI_TYPE_SINT8:
627 		      reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
628 		      break;
629 		    case FFI_TYPE_SINT16:
630 		      reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
631 		      break;
632 		    case FFI_TYPE_SINT32:
633 		      reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
634 		      break;
635 		    default:
636 		      reg_args->gpr[gprcount] = 0;
637 		      memcpy (&reg_args->gpr[gprcount], a, size);
638 		    }
639 		  gprcount++;
640 		  break;
641 		case X86_64_SSE_CLASS:
642 		case X86_64_SSEDF_CLASS:
643 		  reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
644 		  break;
645 		case X86_64_SSESF_CLASS:
646 		  reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
647 		  break;
648 		default:
649 		  abort();
650 		}
651 	    }
652 	}
653     }
654   reg_args->rax = ssecount;
655 
656   ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
657 		   flags, rvalue, fn);
658 }
659 
660 void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)661 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
662 {
663   ffi_call_int (cif, fn, rvalue, avalue, NULL);
664 }
665 
666 void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)667 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
668 	     void **avalue, void *closure)
669 {
670   ffi_call_int (cif, fn, rvalue, avalue, closure);
671 }
672 
673 extern void ffi_closure_unix64(void) FFI_HIDDEN;
674 extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
675 
676 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)677 ffi_prep_closure_loc (ffi_closure* closure,
678 		      ffi_cif* cif,
679 		      void (*fun)(ffi_cif*, void*, void**, void*),
680 		      void *user_data,
681 		      void *codeloc)
682 {
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,
688     /* nopl  (%rax) */
689     0x0f, 0x1f, 0x00
690   };
691   void (*dest)(void);
692   char *tramp = closure->tramp;
693 
694   if (cif->abi != FFI_UNIX64)
695     return FFI_BAD_ABI;
696 
697   if (cif->flags & UNIX64_FLAG_XMM_ARGS)
698     dest = ffi_closure_unix64_sse;
699   else
700     dest = ffi_closure_unix64;
701 
702   memcpy (tramp, trampoline, sizeof(trampoline));
703   *(UINT64 *)(tramp + 16) = (uintptr_t)dest;
704 
705   closure->cif = cif;
706   closure->fun = fun;
707   closure->user_data = user_data;
708 
709   return FFI_OK;
710 }
711 
712 int FFI_HIDDEN
ffi_closure_unix64_inner(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,struct register_args * reg_args,char * argp)713 ffi_closure_unix64_inner(ffi_cif *cif,
714 			 void (*fun)(ffi_cif*, void*, void**, void*),
715 			 void *user_data,
716 			 void *rvalue,
717 			 struct register_args *reg_args,
718 			 char *argp)
719 {
720   void **avalue;
721   ffi_type **arg_types;
722   long i, avn;
723   int gprcount, ssecount, ngpr, nsse;
724   int flags;
725 
726   avn = cif->nargs;
727   flags = cif->flags;
728   avalue = alloca(avn * sizeof(void *));
729   gprcount = ssecount = 0;
730 
731   if (flags & UNIX64_FLAG_RET_IN_MEM)
732     {
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;
737       rvalue = r;
738       flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
739     }
740 
741   arg_types = cif->arg_types;
742   for (i = 0; i < avn; ++i)
743     {
744       enum x86_64_reg_class classes[MAX_CLASSES];
745       size_t n;
746 
747       n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
748       if (n == 0
749 	  || gprcount + ngpr > MAX_GPR_REGS
750 	  || ssecount + nsse > MAX_SSE_REGS)
751 	{
752 	  long align = arg_types[i]->alignment;
753 
754 	  /* Stack arguments are *always* at least 8 byte aligned.  */
755 	  if (align < 8)
756 	    align = 8;
757 
758 	  /* Pass this argument in memory.  */
759 	  argp = (void *) ALIGN (argp, align);
760 	  avalue[i] = argp;
761 	  argp += arg_types[i]->size;
762 	}
763       /* If the argument is in a single register, or two consecutive
764 	 integer registers, then we can use that address directly.  */
765       else if (n == 1
766 	       || (n == 2 && !(SSE_CLASS_P (classes[0])
767 			       || SSE_CLASS_P (classes[1]))))
768 	{
769 	  /* The argument is in a single register.  */
770 	  if (SSE_CLASS_P (classes[0]))
771 	    {
772 	      avalue[i] = &reg_args->sse[ssecount];
773 	      ssecount += n;
774 	    }
775 	  else
776 	    {
777 	      avalue[i] = &reg_args->gpr[gprcount];
778 	      gprcount += n;
779 	    }
780 	}
781       /* Otherwise, allocate space to make them consecutive.  */
782       else
783 	{
784 	  char *a = alloca (16);
785 	  int j;
786 
787 	  avalue[i] = a;
788 	  for (j = 0; j < n; j++, a += 8)
789 	    {
790 	      if (SSE_CLASS_P (classes[j]))
791 		memcpy (a, &reg_args->sse[ssecount++], 8);
792 	      else
793 		memcpy (a, &reg_args->gpr[gprcount++], 8);
794 	    }
795 	}
796     }
797 
798   /* Invoke the closure.  */
799   fun (cif, rvalue, avalue, user_data);
800 
801   /* Tell assembly how to perform return type promotions.  */
802   return flags;
803 }
804 
805 extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
806 extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
807 
808 ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))809 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
810 		     void (*fun)(ffi_cif*, void*, void**, void*))
811 {
812   if (cif->abi != FFI_UNIX64)
813     return FFI_BAD_ABI;
814 
815   closure->tramp = (cif->flags & UNIX64_FLAG_XMM_ARGS
816 		    ? ffi_go_closure_unix64_sse
817 		    : ffi_go_closure_unix64);
818   closure->cif = cif;
819   closure->fun = fun;
820 
821   return FFI_OK;
822 }
823 
824 #endif /* __x86_64__ */
825