Restore execute permissions
[platform/upstream/libffi.git] / src / x86 / .svn / text-base / ffi64.c.svn-base
1 /* -----------------------------------------------------------------------
2    ffi64.c - Copyright (c) 2002, 2007  Bo Thorsen <bo@suse.de>
3              Copyright (c) 2008  Red Hat, Inc.
4    
5    x86-64 Foreign Function Interface 
6
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:
14
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
17
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    ----------------------------------------------------------------------- */
27
28 #include <ffi.h>
29 #include <ffi_common.h>
30
31 #include <stdlib.h>
32 #include <stdarg.h>
33
34 #ifdef __x86_64__
35
36 #define MAX_GPR_REGS 6
37 #define MAX_SSE_REGS 8
38
39 struct register_args
40 {
41   /* Registers for argument passing.  */
42   UINT64 gpr[MAX_GPR_REGS];
43   __int128_t sse[MAX_SSE_REGS];
44 };
45
46 extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
47                              void *raddr, void (*fnaddr)(void), unsigned ssecount);
48
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.  */
51
52 /* Register class used for passing given 64bit part of the argument.
53    These represent classes as documented by the PS ABI, with the exception
54    of SSESF, SSEDF classes, that are basically SSE class, just gcc will
55    use SF or DFmode move instead of DImode to avoid reformating penalties.
56
57    Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
58    whenever possible (upper half does contain padding).  */
59 enum x86_64_reg_class
60   {
61     X86_64_NO_CLASS,
62     X86_64_INTEGER_CLASS,
63     X86_64_INTEGERSI_CLASS,
64     X86_64_SSE_CLASS,
65     X86_64_SSESF_CLASS,
66     X86_64_SSEDF_CLASS,
67     X86_64_SSEUP_CLASS,
68     X86_64_X87_CLASS,
69     X86_64_X87UP_CLASS,
70     X86_64_COMPLEX_X87_CLASS,
71     X86_64_MEMORY_CLASS
72   };
73
74 #define MAX_CLASSES 4
75
76 #define SSE_CLASS_P(X)  ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
77
78 /* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
79    of this code is to classify each 8bytes of incoming argument by the register
80    class and assign registers accordingly.  */
81
82 /* Return the union class of CLASS1 and CLASS2.
83    See the x86-64 PS ABI for details.  */
84
85 static enum x86_64_reg_class
86 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
87 {
88   /* Rule #1: If both classes are equal, this is the resulting class.  */
89   if (class1 == class2)
90     return class1;
91
92   /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
93      the other class.  */
94   if (class1 == X86_64_NO_CLASS)
95     return class2;
96   if (class2 == X86_64_NO_CLASS)
97     return class1;
98
99   /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
100   if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
101     return X86_64_MEMORY_CLASS;
102
103   /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
104   if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
105       || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
106     return X86_64_INTEGERSI_CLASS;
107   if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
108       || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
109     return X86_64_INTEGER_CLASS;
110
111   /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
112      MEMORY is used.  */
113   if (class1 == X86_64_X87_CLASS
114       || class1 == X86_64_X87UP_CLASS
115       || class1 == X86_64_COMPLEX_X87_CLASS
116       || class2 == X86_64_X87_CLASS
117       || class2 == X86_64_X87UP_CLASS
118       || class2 == X86_64_COMPLEX_X87_CLASS)
119     return X86_64_MEMORY_CLASS;
120
121   /* Rule #6: Otherwise class SSE is used.  */
122   return X86_64_SSE_CLASS;
123 }
124
125 /* Classify the argument of type TYPE and mode MODE.
126    CLASSES will be filled by the register class used to pass each word
127    of the operand.  The number of words is returned.  In case the parameter
128    should be passed in memory, 0 is returned. As a special case for zero
129    sized containers, classes[0] will be NO_CLASS and 1 is returned.
130
131    See the x86-64 PS ABI for details.
132 */
133 static int
134 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
135                    size_t byte_offset)
136 {
137   switch (type->type)
138     {
139     case FFI_TYPE_UINT8:
140     case FFI_TYPE_SINT8:
141     case FFI_TYPE_UINT16:
142     case FFI_TYPE_SINT16:
143     case FFI_TYPE_UINT32:
144     case FFI_TYPE_SINT32:
145     case FFI_TYPE_UINT64:
146     case FFI_TYPE_SINT64:
147     case FFI_TYPE_POINTER:
148       {
149         int size = byte_offset + type->size;
150
151         if (size <= 4)
152           {
153             classes[0] = X86_64_INTEGERSI_CLASS;
154             return 1;
155           }
156         else if (size <= 8)
157           {
158             classes[0] = X86_64_INTEGER_CLASS;
159             return 1;
160           }
161         else if (size <= 12)
162           {
163             classes[0] = X86_64_INTEGER_CLASS;
164             classes[1] = X86_64_INTEGERSI_CLASS;
165             return 2;
166           }
167         else if (size <= 16)
168           {
169             classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
170             return 2;
171           }
172         else
173           FFI_ASSERT (0);
174       }
175     case FFI_TYPE_FLOAT:
176       if (!(byte_offset % 8))
177         classes[0] = X86_64_SSESF_CLASS;
178       else
179         classes[0] = X86_64_SSE_CLASS;
180       return 1;
181     case FFI_TYPE_DOUBLE:
182       classes[0] = X86_64_SSEDF_CLASS;
183       return 1;
184     case FFI_TYPE_LONGDOUBLE:
185       classes[0] = X86_64_X87_CLASS;
186       classes[1] = X86_64_X87UP_CLASS;
187       return 2;
188     case FFI_TYPE_STRUCT:
189       {
190         const int UNITS_PER_WORD = 8;
191         int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
192         ffi_type **ptr; 
193         int i;
194         enum x86_64_reg_class subclasses[MAX_CLASSES];
195
196         /* If the struct is larger than 32 bytes, pass it on the stack.  */
197         if (type->size > 32)
198           return 0;
199
200         for (i = 0; i < words; i++)
201           classes[i] = X86_64_NO_CLASS;
202
203         /* Zero sized arrays or structures are NO_CLASS.  We return 0 to
204            signalize memory class, so handle it as special case.  */
205         if (!words)
206           {
207             classes[0] = X86_64_NO_CLASS;
208             return 1;
209           }
210
211         /* Merge the fields of structure.  */
212         for (ptr = type->elements; *ptr != NULL; ptr++)
213           {
214             int num;
215
216             byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
217
218             num = classify_argument (*ptr, subclasses, byte_offset % 8);
219             if (num == 0)
220               return 0;
221             for (i = 0; i < num; i++)
222               {
223                 int pos = byte_offset / 8;
224                 classes[i + pos] =
225                   merge_classes (subclasses[i], classes[i + pos]);
226               }
227
228             byte_offset += (*ptr)->size;
229           }
230
231         if (words > 2)
232           {
233             /* When size > 16 bytes, if the first one isn't
234                X86_64_SSE_CLASS or any other ones aren't
235                X86_64_SSEUP_CLASS, everything should be passed in
236                memory.  */
237             if (classes[0] != X86_64_SSE_CLASS)
238               return 0;
239
240             for (i = 1; i < words; i++)
241               if (classes[i] != X86_64_SSEUP_CLASS)
242                 return 0;
243           }
244
245         /* Final merger cleanup.  */
246         for (i = 0; i < words; i++)
247           {
248             /* If one class is MEMORY, everything should be passed in
249                memory.  */
250             if (classes[i] == X86_64_MEMORY_CLASS)
251               return 0;
252
253             /* The X86_64_SSEUP_CLASS should be always preceded by
254                X86_64_SSE_CLASS or X86_64_SSEUP_CLASS.  */
255             if (classes[i] == X86_64_SSEUP_CLASS
256                 && classes[i - 1] != X86_64_SSE_CLASS
257                 && classes[i - 1] != X86_64_SSEUP_CLASS)
258               {
259                 /* The first one should never be X86_64_SSEUP_CLASS.  */
260                 FFI_ASSERT (i != 0);
261                 classes[i] = X86_64_SSE_CLASS;
262               }
263
264             /*  If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
265                 everything should be passed in memory.  */
266             if (classes[i] == X86_64_X87UP_CLASS
267                 && (classes[i - 1] != X86_64_X87_CLASS))
268               {
269                 /* The first one should never be X86_64_X87UP_CLASS.  */
270                 FFI_ASSERT (i != 0);
271                 return 0;
272               }
273           }
274         return words;
275       }
276
277     default:
278       FFI_ASSERT(0);
279     }
280   return 0; /* Never reached.  */
281 }
282
283 /* Examine the argument and return set number of register required in each
284    class.  Return zero iff parameter should be passed in memory, otherwise
285    the number of registers.  */
286
287 static int
288 examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
289                   _Bool in_return, int *pngpr, int *pnsse)
290 {
291   int i, n, ngpr, nsse;
292
293   n = classify_argument (type, classes, 0);
294   if (n == 0)
295     return 0;
296
297   ngpr = nsse = 0;
298   for (i = 0; i < n; ++i)
299     switch (classes[i])
300       {
301       case X86_64_INTEGER_CLASS:
302       case X86_64_INTEGERSI_CLASS:
303         ngpr++;
304         break;
305       case X86_64_SSE_CLASS:
306       case X86_64_SSESF_CLASS:
307       case X86_64_SSEDF_CLASS:
308         nsse++;
309         break;
310       case X86_64_NO_CLASS:
311       case X86_64_SSEUP_CLASS:
312         break;
313       case X86_64_X87_CLASS:
314       case X86_64_X87UP_CLASS:
315       case X86_64_COMPLEX_X87_CLASS:
316         return in_return != 0;
317       default:
318         abort ();
319       }
320
321   *pngpr = ngpr;
322   *pnsse = nsse;
323
324   return n;
325 }
326
327 /* Perform machine dependent cif processing.  */
328
329 ffi_status
330 ffi_prep_cif_machdep (ffi_cif *cif)
331 {
332   int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
333   enum x86_64_reg_class classes[MAX_CLASSES];
334   size_t bytes;
335
336   gprcount = ssecount = 0;
337
338   flags = cif->rtype->type;
339   if (flags != FFI_TYPE_VOID)
340     {
341       n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
342       if (n == 0)
343         {
344           /* The return value is passed in memory.  A pointer to that
345              memory is the first argument.  Allocate a register for it.  */
346           gprcount++;
347           /* We don't have to do anything in asm for the return.  */
348           flags = FFI_TYPE_VOID;
349         }
350       else if (flags == FFI_TYPE_STRUCT)
351         {
352           /* Mark which registers the result appears in.  */
353           _Bool sse0 = SSE_CLASS_P (classes[0]);
354           _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
355           if (sse0 && !sse1)
356             flags |= 1 << 8;
357           else if (!sse0 && sse1)
358             flags |= 1 << 9;
359           else if (sse0 && sse1)
360             flags |= 1 << 10;
361           /* Mark the true size of the structure.  */
362           flags |= cif->rtype->size << 12;
363         }
364     }
365
366   /* Go over all arguments and determine the way they should be passed.
367      If it's in a register and there is space for it, let that be so. If
368      not, add it's size to the stack byte count.  */
369   for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
370     {
371       if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
372           || gprcount + ngpr > MAX_GPR_REGS
373           || ssecount + nsse > MAX_SSE_REGS)
374         {
375           long align = cif->arg_types[i]->alignment;
376
377           if (align < 8)
378             align = 8;
379
380           bytes = ALIGN(bytes, align);
381           bytes += cif->arg_types[i]->size;
382         }
383       else
384         {
385           gprcount += ngpr;
386           ssecount += nsse;
387         }
388     }
389   if (ssecount)
390     flags |= 1 << 11;
391   cif->flags = flags;
392   cif->bytes = bytes;
393
394   return FFI_OK;
395 }
396
397 void
398 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
399 {
400   enum x86_64_reg_class classes[MAX_CLASSES];
401   char *stack, *argp;
402   ffi_type **arg_types;
403   int gprcount, ssecount, ngpr, nsse, i, avn;
404   _Bool ret_in_memory;
405   struct register_args *reg_args;
406
407   /* Can't call 32-bit mode from 64-bit mode.  */
408   FFI_ASSERT (cif->abi == FFI_UNIX64);
409
410   /* If the return value is a struct and we don't have a return value
411      address then we need to make one.  Note the setting of flags to
412      VOID above in ffi_prep_cif_machdep.  */
413   ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
414                    && (cif->flags & 0xff) == FFI_TYPE_VOID);
415   if (rvalue == NULL && ret_in_memory)
416     rvalue = alloca (cif->rtype->size);
417
418   /* Allocate the space for the arguments, plus 4 words of temp space.  */
419   stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
420   reg_args = (struct register_args *) stack;
421   argp = stack + sizeof (struct register_args);
422
423   gprcount = ssecount = 0;
424
425   /* If the return value is passed in memory, add the pointer as the
426      first integer argument.  */
427   if (ret_in_memory)
428     reg_args->gpr[gprcount++] = (long) rvalue;
429
430   avn = cif->nargs;
431   arg_types = cif->arg_types;
432
433   for (i = 0; i < avn; ++i)
434     {
435       size_t size = arg_types[i]->size;
436       int n;
437
438       n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
439       if (n == 0
440           || gprcount + ngpr > MAX_GPR_REGS
441           || ssecount + nsse > MAX_SSE_REGS)
442         {
443           long align = arg_types[i]->alignment;
444
445           /* Stack arguments are *always* at least 8 byte aligned.  */
446           if (align < 8)
447             align = 8;
448
449           /* Pass this argument in memory.  */
450           argp = (void *) ALIGN (argp, align);
451           memcpy (argp, avalue[i], size);
452           argp += size;
453         }
454       else
455         {
456           /* The argument is passed entirely in registers.  */
457           char *a = (char *) avalue[i];
458           int j;
459
460           for (j = 0; j < n; j++, a += 8, size -= 8)
461             {
462               switch (classes[j])
463                 {
464                 case X86_64_INTEGER_CLASS:
465                 case X86_64_INTEGERSI_CLASS:
466                   reg_args->gpr[gprcount] = 0;
467                   memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
468                   gprcount++;
469                   break;
470                 case X86_64_SSE_CLASS:
471                 case X86_64_SSEDF_CLASS:
472                   reg_args->sse[ssecount++] = *(UINT64 *) a;
473                   break;
474                 case X86_64_SSESF_CLASS:
475                   reg_args->sse[ssecount++] = *(UINT32 *) a;
476                   break;
477                 default:
478                   abort();
479                 }
480             }
481         }
482     }
483
484   ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
485                    cif->flags, rvalue, fn, ssecount);
486 }
487
488
489 extern void ffi_closure_unix64(void);
490
491 ffi_status
492 ffi_prep_closure_loc (ffi_closure* closure,
493                       ffi_cif* cif,
494                       void (*fun)(ffi_cif*, void*, void**, void*),
495                       void *user_data,
496                       void *codeloc)
497 {
498   volatile unsigned short *tramp;
499
500   tramp = (volatile unsigned short *) &closure->tramp[0];
501
502   tramp[0] = 0xbb49;            /* mov <code>, %r11     */
503   *(void * volatile *) &tramp[1] = ffi_closure_unix64;
504   tramp[5] = 0xba49;            /* mov <data>, %r10     */
505   *(void * volatile *) &tramp[6] = codeloc;
506
507   /* Set the carry bit iff the function uses any sse registers.
508      This is clc or stc, together with the first byte of the jmp.  */
509   tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
510
511   tramp[11] = 0xe3ff;                   /* jmp *%r11    */
512
513   closure->cif = cif;
514   closure->fun = fun;
515   closure->user_data = user_data;
516
517   return FFI_OK;
518 }
519
520 int
521 ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
522                          struct register_args *reg_args, char *argp)
523 {
524   ffi_cif *cif;
525   void **avalue;
526   ffi_type **arg_types;
527   long i, avn;
528   int gprcount, ssecount, ngpr, nsse;
529   int ret;
530
531   cif = closure->cif;
532   avalue = alloca(cif->nargs * sizeof(void *));
533   gprcount = ssecount = 0;
534
535   ret = cif->rtype->type;
536   if (ret != FFI_TYPE_VOID)
537     {
538       enum x86_64_reg_class classes[MAX_CLASSES];
539       int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
540       if (n == 0)
541         {
542           /* The return value goes in memory.  Arrange for the closure
543              return value to go directly back to the original caller.  */
544           rvalue = (void *) reg_args->gpr[gprcount++];
545           /* We don't have to do anything in asm for the return.  */
546           ret = FFI_TYPE_VOID;
547         }
548       else if (ret == FFI_TYPE_STRUCT && n == 2)
549         {
550           /* Mark which register the second word of the structure goes in.  */
551           _Bool sse0 = SSE_CLASS_P (classes[0]);
552           _Bool sse1 = SSE_CLASS_P (classes[1]);
553           if (!sse0 && sse1)
554             ret |= 1 << 8;
555           else if (sse0 && !sse1)
556             ret |= 1 << 9;
557         }
558     }
559
560   avn = cif->nargs;
561   arg_types = cif->arg_types;
562   
563   for (i = 0; i < avn; ++i)
564     {
565       enum x86_64_reg_class classes[MAX_CLASSES];
566       int n;
567
568       n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
569       if (n == 0
570           || gprcount + ngpr > MAX_GPR_REGS
571           || ssecount + nsse > MAX_SSE_REGS)
572         {
573           long align = arg_types[i]->alignment;
574
575           /* Stack arguments are *always* at least 8 byte aligned.  */
576           if (align < 8)
577             align = 8;
578
579           /* Pass this argument in memory.  */
580           argp = (void *) ALIGN (argp, align);
581           avalue[i] = argp;
582           argp += arg_types[i]->size;
583         }
584       /* If the argument is in a single register, or two consecutive
585          integer registers, then we can use that address directly.  */
586       else if (n == 1
587                || (n == 2 && !(SSE_CLASS_P (classes[0])
588                                || SSE_CLASS_P (classes[1]))))
589         {
590           /* The argument is in a single register.  */
591           if (SSE_CLASS_P (classes[0]))
592             {
593               avalue[i] = &reg_args->sse[ssecount];
594               ssecount += n;
595             }
596           else
597             {
598               avalue[i] = &reg_args->gpr[gprcount];
599               gprcount += n;
600             }
601         }
602       /* Otherwise, allocate space to make them consecutive.  */
603       else
604         {
605           char *a = alloca (16);
606           int j;
607
608           avalue[i] = a;
609           for (j = 0; j < n; j++, a += 8)
610             {
611               if (SSE_CLASS_P (classes[j]))
612                 memcpy (a, &reg_args->sse[ssecount++], 8);
613               else
614                 memcpy (a, &reg_args->gpr[gprcount++], 8);
615             }
616         }
617     }
618
619   /* Invoke the closure.  */
620   closure->fun (cif, rvalue, avalue, closure->user_data);
621
622   /* Tell assembly how to perform return type promotions.  */
623   return ret;
624 }
625
626 #endif /* __x86_64__ */