OSDN Git Service

2002-07-16 Bo Thorsen <bo@suse.de>
[pf3gnuchains/gcc-fork.git] / libffi / src / x86 / ffi64.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
3    
4    x86-64 Foreign Function Interface 
5
6    Permission is hereby granted, free of charge, to any person obtaining
7    a copy of this software and associated documentation files (the
8    ``Software''), to deal in the Software without restriction, including
9    without limitation the rights to use, copy, modify, merge, publish,
10    distribute, sublicense, and/or sell copies of the Software, and to
11    permit persons to whom the Software is furnished to do so, subject to
12    the following conditions:
13
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
16
17    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23    OTHER DEALINGS IN THE SOFTWARE.
24    ----------------------------------------------------------------------- */
25
26 #include <ffi.h>
27 #include <ffi_common.h>
28
29 #include <stdlib.h>
30
31 /* ffi_prep_args is called by the assembly routine once stack space
32    has been allocated for the function's arguments */
33
34 #ifdef __x86_64__
35
36 #define MAX_GPR_REGS 6
37 #define MAX_SSE_REGS 8
38 typedef struct
39 {
40   /* Registers for argument passing.  */
41   long gpr[MAX_GPR_REGS];
42   __int128_t sse[MAX_SSE_REGS];
43
44   /* Stack space for arguments.  */
45   char argspace[0];
46 } stackLayout;
47
48 /* All reference to register classes here is identical to the code in
49    gcc/config/i386/i386.c. Do *not* change one without the other.  */
50
51 /* Register class used for passing given 64bit part of the argument.
52    These represent classes as documented by the PS ABI, with the exception
53    of SSESF, SSEDF classes, that are basically SSE class, just gcc will
54    use SF or DFmode move instead of DImode to avoid reformating penalties.
55
56    Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
57    whenever possible (upper half does contain padding).
58  */
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_MEMORY_CLASS
71   };
72
73 #define MAX_CLASSES 4
74
75 /* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
76    of this code is to classify each 8bytes of incoming argument by the register
77    class and assign registers accordingly.  */
78
79 /* Return the union class of CLASS1 and CLASS2.
80    See the x86-64 PS ABI for details.  */
81
82 static enum x86_64_reg_class
83 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
84 {
85   /* Rule #1: If both classes are equal, this is the resulting class.  */
86   if (class1 == class2)
87     return class1;
88
89   /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
90      the other class.  */
91   if (class1 == X86_64_NO_CLASS)
92     return class2;
93   if (class2 == X86_64_NO_CLASS)
94     return class1;
95
96   /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
97   if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
98     return X86_64_MEMORY_CLASS;
99
100   /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
101   if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
102       || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
103     return X86_64_INTEGERSI_CLASS;
104   if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
105       || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
106     return X86_64_INTEGER_CLASS;
107
108   /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used.  */
109   if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
110       || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
111     return X86_64_MEMORY_CLASS;
112
113   /* Rule #6: Otherwise class SSE is used.  */
114   return X86_64_SSE_CLASS;
115 }
116
117 /* Classify the argument of type TYPE and mode MODE.
118    CLASSES will be filled by the register class used to pass each word
119    of the operand.  The number of words is returned.  In case the parameter
120    should be passed in memory, 0 is returned. As a special case for zero
121    sized containers, classes[0] will be NO_CLASS and 1 is returned.
122
123    See the x86-64 PS ABI for details.
124 */
125 static int
126 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
127                    int *byte_offset)
128 {
129   /* First, align to the right place.  */
130   *byte_offset = ALIGN(*byte_offset, type->alignment);
131
132   switch (type->type)
133     {
134     case FFI_TYPE_UINT8:
135     case FFI_TYPE_SINT8:
136     case FFI_TYPE_UINT16:
137     case FFI_TYPE_SINT16:
138     case FFI_TYPE_UINT32:
139     case FFI_TYPE_SINT32:
140     case FFI_TYPE_UINT64:
141     case FFI_TYPE_SINT64:
142     case FFI_TYPE_POINTER:
143       if (((*byte_offset) % 8 + type->size) <= 4)
144         classes[0] = X86_64_INTEGERSI_CLASS;
145       else
146         classes[0] = X86_64_INTEGER_CLASS;
147       return 1;
148     case FFI_TYPE_FLOAT:
149       if (((*byte_offset) % 8) == 0)
150         classes[0] = X86_64_SSESF_CLASS;
151       else
152         classes[0] = X86_64_SSE_CLASS;
153       return 1;
154     case FFI_TYPE_DOUBLE:
155       classes[0] = X86_64_SSEDF_CLASS;
156       return 1;
157     case FFI_TYPE_LONGDOUBLE:
158       classes[0] = X86_64_X87_CLASS;
159       classes[1] = X86_64_X87UP_CLASS;
160       return 2;
161     case FFI_TYPE_STRUCT:
162       {
163         const int UNITS_PER_WORD = 8;
164         int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
165         ffi_type **ptr; 
166         int i;
167         enum x86_64_reg_class subclasses[MAX_CLASSES];
168
169         /* If the struct is larger than 16 bytes, pass it on the stack.  */
170         if (type->size > 16)
171           return 0;
172
173         for (i = 0; i < words; i++)
174           classes[i] = X86_64_NO_CLASS;
175
176         /* Merge the fields of structure.  */
177         for (ptr=type->elements; (*ptr)!=NULL; ptr++)
178           {
179             int num;
180
181             num = classify_argument (*ptr, subclasses, byte_offset);
182             if (num == 0)
183               return 0;
184             for (i = 0; i < num; i++)
185               {
186                 int pos = *byte_offset / 8;
187                 classes[i + pos] =
188                   merge_classes (subclasses[i], classes[i + pos]);
189               }
190
191             if ((*ptr)->type != FFI_TYPE_STRUCT)
192               *byte_offset += (*ptr)->size;
193           }
194
195         /* Final merger cleanup.  */
196         for (i = 0; i < words; i++)
197           {
198             /* If one class is MEMORY, everything should be passed in
199                memory.  */
200             if (classes[i] == X86_64_MEMORY_CLASS)
201               return 0;
202
203             /* The X86_64_SSEUP_CLASS should be always preceded by
204                X86_64_SSE_CLASS.  */
205             if (classes[i] == X86_64_SSEUP_CLASS
206                 && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
207               classes[i] = X86_64_SSE_CLASS;
208
209             /*  X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS.  */
210             if (classes[i] == X86_64_X87UP_CLASS
211                 && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
212               classes[i] = X86_64_SSE_CLASS;
213           }
214         return words;
215       }
216
217     default:
218       FFI_ASSERT(0);
219     }
220   return 0; /* Never reached.  */
221 }
222
223 /* Examine the argument and return set number of register required in each
224    class.  Return 0 iff parameter should be passed in memory.  */
225 static int
226 examine_argument (ffi_type *type, int in_return, int *int_nregs,int *sse_nregs)
227 {
228   enum x86_64_reg_class class[MAX_CLASSES];
229   int offset = 0;
230   int n;
231
232   n = classify_argument (type, class, &offset);
233
234   if (n == 0)
235     return 0;
236
237   *int_nregs = 0;
238   *sse_nregs = 0;
239   for (n--; n>=0; n--)
240     switch (class[n])
241       {
242       case X86_64_INTEGER_CLASS:
243       case X86_64_INTEGERSI_CLASS:
244         (*int_nregs)++;
245         break;
246       case X86_64_SSE_CLASS:
247       case X86_64_SSESF_CLASS:
248       case X86_64_SSEDF_CLASS:
249         (*sse_nregs)++;
250         break;
251       case X86_64_NO_CLASS:
252       case X86_64_SSEUP_CLASS:
253         break;
254       case X86_64_X87_CLASS:
255       case X86_64_X87UP_CLASS:
256         if (!in_return)
257           return 0;
258         break;
259       default:
260         abort ();
261       }
262   return 1;
263 }
264
265 /* Functions to load floats and double to an SSE register placeholder.  */
266 extern void float2sse (float, __int128_t *);
267 extern void double2sse (double, __int128_t *);
268 extern void floatfloat2sse (void *, __int128_t *);
269
270 /* Functions to put the floats and doubles back.  */
271 extern float sse2float (__int128_t *);
272 extern double sse2double (__int128_t *);
273 extern void sse2floatfloat(__int128_t *, void *);
274
275 /*@-exportheader@*/
276 void
277 ffi_prep_args (stackLayout *stack, extended_cif *ecif)
278 /*@=exportheader@*/
279 {
280   int gprcount, ssecount, i, g, s;
281   void **p_argv;
282   void *argp = &stack->argspace;
283   ffi_type **p_arg;
284
285   /* First check if the return value should be passed in memory. If so,
286      pass the pointer as the first argument.  */
287   gprcount = ssecount = 0;
288   if (examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
289     (void *)stack->gpr[gprcount++] = ecif->rvalue;
290
291   for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
292        i!=0; i--, p_arg++, p_argv++)
293     {
294       int in_register = 0;
295
296       switch ((*p_arg)->type)
297         {
298         case FFI_TYPE_SINT8:
299         case FFI_TYPE_SINT16:
300         case FFI_TYPE_SINT32:
301         case FFI_TYPE_SINT64:
302         case FFI_TYPE_UINT8:
303         case FFI_TYPE_UINT16:
304         case FFI_TYPE_UINT32:
305         case FFI_TYPE_UINT64:
306         case FFI_TYPE_POINTER:
307           if (gprcount < MAX_GPR_REGS)
308             {
309               stack->gpr[gprcount] = 0;
310               stack->gpr[gprcount++] = *(long long *)(*p_argv);
311               in_register = 1;
312             }
313           break;
314
315         case FFI_TYPE_FLOAT:
316           if (ssecount < MAX_SSE_REGS)
317             {
318               float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
319               in_register = 1;
320             }
321           break;
322
323         case FFI_TYPE_DOUBLE:
324           if (ssecount < MAX_SSE_REGS)
325             {
326               double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
327               in_register = 1;
328             }
329           break;
330         }
331
332       if (in_register)
333         continue;
334
335       /* Either all places in registers where filled, or this is a
336          type that potentially goes into a memory slot.  */
337       if (examine_argument (*p_arg, 0, &g, &s) == 0
338           || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
339         {
340           /* Pass this argument in memory.  */
341           argp = (void *)ALIGN(argp, (*p_arg)->alignment);
342           memcpy (argp, *p_argv, (*p_arg)->size);
343           argp += (*p_arg)->size;
344         }
345       else
346         {
347           /* All easy cases are eliminated. Now fire the big guns.  */
348
349           enum x86_64_reg_class classes[MAX_CLASSES];
350           int offset = 0, j, num;
351           void *a;
352
353           num = classify_argument (*p_arg, classes, &offset);
354           for (j=0, a=*p_argv; j<num; j++, a+=8)
355             {
356               switch (classes[j])
357                 {
358                 case X86_64_INTEGER_CLASS:
359                 case X86_64_INTEGERSI_CLASS:
360                   stack->gpr[gprcount++] = *(long long *)a;
361                   break;
362                 case X86_64_SSE_CLASS:
363                   floatfloat2sse (a, &stack->sse[ssecount++]);
364                   break;
365                 case X86_64_SSESF_CLASS:
366                   float2sse (*(float *)a, &stack->sse[ssecount++]);
367                   break;
368                 case X86_64_SSEDF_CLASS:
369                   double2sse (*(double *)a, &stack->sse[ssecount++]);
370                   break;
371                 default:
372                   abort();
373                 }
374             }
375         }
376     }
377 }
378
379 /* Perform machine dependent cif processing.  */
380 ffi_status
381 ffi_prep_cif_machdep (ffi_cif *cif)
382 {
383   int gprcount, ssecount, i, g, s;
384
385   gprcount = ssecount = 0;
386
387   /* Reset the byte count. We handle this size estimation here.  */
388   cif->bytes = 0;
389
390   /* If the return value should be passed in memory, pass the pointer
391      as the first argument. The actual memory isn't allocated here.  */
392
393   if (examine_argument (cif->rtype, 1, &g, &s) == 0)
394     gprcount = 1;
395
396   /* Go over all arguments and determine the way they should be passed.
397      If it's in a register and there is space for it, let that be so. If
398      not, add it's size to the stack byte count.  */
399   for (i=0; i<cif->nargs; i++)
400     {
401       if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
402           || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
403         {
404           /* This is passed in memory. First align to the basic type.  */
405           cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
406
407           /* Stack arguments are *always* at least 8 byte aligned.  */
408           cif->bytes = ALIGN(cif->bytes, 8);
409
410           /* Now add the size of this argument.  */
411           cif->bytes += cif->arg_types[i]->size;
412         }
413       else
414         {
415           gprcount += g;
416           ssecount += s;
417         }
418     }
419
420   /* Set the flag for the closures return.  */
421     switch (cif->rtype->type)
422     {
423     case FFI_TYPE_VOID:
424     case FFI_TYPE_STRUCT:
425     case FFI_TYPE_SINT64:
426     case FFI_TYPE_FLOAT:
427     case FFI_TYPE_DOUBLE:
428     case FFI_TYPE_LONGDOUBLE:
429       cif->flags = (unsigned) cif->rtype->type;
430       break;
431
432     case FFI_TYPE_UINT64:
433       cif->flags = FFI_TYPE_SINT64;
434       break;
435
436     default:
437       cif->flags = FFI_TYPE_INT;
438       break;
439     }
440
441   puts ("prep_machdep\n");
442
443   return FFI_OK;
444 }
445
446 typedef struct
447 {
448   long gpr[2];
449   __int128_t sse[2];
450   long double st0;
451 } return_value;
452
453 void
454 ffi_fill_return_value (return_value *rv, extended_cif *ecif)
455 {
456   enum x86_64_reg_class classes[MAX_CLASSES];
457   int i = 0, num;
458   long *gpr = rv->gpr;
459   __int128_t *sse = rv->sse;
460   signed char sc;
461   signed short ss;
462
463   /* This is needed because of the way x86-64 handles signed short
464      integers.  */
465   switch (ecif->cif->rtype->type)
466     {
467     case FFI_TYPE_SINT8:
468       sc = *(signed char *)gpr;
469       *(long long *)ecif->rvalue = (long long)sc;
470       return;
471     case FFI_TYPE_SINT16:
472       ss = *(signed short *)gpr;
473       *(long long *)ecif->rvalue = (long long)ss;
474       return;
475     default:
476       /* Just continue.  */
477       ;
478     }
479
480   num = classify_argument (ecif->cif->rtype, classes, &i);
481
482   if (num == 0)
483     /* Return in memory.  */
484     ecif->rvalue = (void *) rv->gpr[0];
485   else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
486         classes[1] == X86_64_X87UP_CLASS)
487     /* This is a long double (this is easiest to handle this way instead
488        of an eightbyte at a time as in the loop below.  */
489     *((long double *)ecif->rvalue) = rv->st0;
490   else
491     {
492       void *a;
493
494       for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
495         {
496           switch (classes[i])
497             {
498             case X86_64_INTEGER_CLASS:
499             case X86_64_INTEGERSI_CLASS:
500               *(long long *)a = *gpr;
501               gpr++;
502               break;
503             case X86_64_SSE_CLASS:
504               sse2floatfloat (sse++, a);
505               break;
506             case X86_64_SSESF_CLASS:
507               *(float *)a = sse2float (sse++);
508               break;
509             case X86_64_SSEDF_CLASS:
510               *(double *)a = sse2double (sse++);
511               break;
512             default:
513               abort();
514             }
515         }
516     }
517 }
518
519 /*@-declundef@*/
520 /*@-exportheader@*/
521 extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
522                             void (*) (return_value *, extended_cif *),
523                             /*@out@*/ extended_cif *, 
524                             unsigned, /*@out@*/ unsigned *, void (*fn)());
525 /*@=declundef@*/
526 /*@=exportheader@*/
527
528 void ffi_call(/*@dependent@*/ ffi_cif *cif, 
529               void (*fn)(), 
530               /*@out@*/ void *rvalue, 
531               /*@dependent@*/ void **avalue)
532 {
533   extended_cif ecif;
534   int dummy;
535
536   ecif.cif = cif;
537   ecif.avalue = avalue;
538   
539   /* If the return value is a struct and we don't have a return */
540   /* value address then we need to make one                     */
541
542   if ((rvalue == NULL) && 
543       (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
544     {
545       /*@-sysunrecog@*/
546       ecif.rvalue = alloca(cif->rtype->size);
547       /*@=sysunrecog@*/
548     }
549   else
550     ecif.rvalue = rvalue;
551     
552   /* Stack must always be 16byte aligned. Make it so.  */
553   cif->bytes = ALIGN(cif->bytes, 16);
554   
555   switch (cif->abi) 
556     {
557     case FFI_SYSV:
558       /* Calling 32bit code from 64bit is not possible  */
559       FFI_ASSERT(0);
560       break;
561
562     case FFI_UNIX64:
563       /*@-usedef@*/
564       ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
565                        cif->bytes, ecif.rvalue, fn);
566       /*@=usedef@*/
567       break;
568
569     default:
570       FFI_ASSERT(0);
571       break;
572     }
573 }
574
575 #endif /* ifndef __x86_64__ */