FSF GCC merge 02/23/03
[official-gcc.git] / libffi / src / x86 / ffi64.c
blob9427a37c8b59a94445b83ef94401b0916e579c6c
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
4 x86-64 Foreign Function Interface
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:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
26 #include <ffi.h>
27 #include <ffi_common.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
32 /* ffi_prep_args is called by the assembly routine once stack space
33 has been allocated for the function's arguments */
35 #ifdef __x86_64__
37 #define MAX_GPR_REGS 6
38 #define MAX_SSE_REGS 8
39 typedef struct
41 /* Registers for argument passing. */
42 long gpr[MAX_GPR_REGS];
43 __int128_t sse[MAX_SSE_REGS];
45 /* Stack space for arguments. */
46 char argspace[0];
47 } stackLayout;
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. */
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.
57 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
58 whenever possible (upper half does contain padding).
60 enum x86_64_reg_class
62 X86_64_NO_CLASS,
63 X86_64_INTEGER_CLASS,
64 X86_64_INTEGERSI_CLASS,
65 X86_64_SSE_CLASS,
66 X86_64_SSESF_CLASS,
67 X86_64_SSEDF_CLASS,
68 X86_64_SSEUP_CLASS,
69 X86_64_X87_CLASS,
70 X86_64_X87UP_CLASS,
71 X86_64_MEMORY_CLASS
74 #define MAX_CLASSES 4
76 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
77 of this code is to classify each 8bytes of incoming argument by the register
78 class and assign registers accordingly. */
80 /* Return the union class of CLASS1 and CLASS2.
81 See the x86-64 PS ABI for details. */
83 static enum x86_64_reg_class
84 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
86 /* Rule #1: If both classes are equal, this is the resulting class. */
87 if (class1 == class2)
88 return class1;
90 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
91 the other class. */
92 if (class1 == X86_64_NO_CLASS)
93 return class2;
94 if (class2 == X86_64_NO_CLASS)
95 return class1;
97 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
98 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
99 return X86_64_MEMORY_CLASS;
101 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
102 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
103 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
104 return X86_64_INTEGERSI_CLASS;
105 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
106 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
107 return X86_64_INTEGER_CLASS;
109 /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */
110 if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
111 || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
112 return X86_64_MEMORY_CLASS;
114 /* Rule #6: Otherwise class SSE is used. */
115 return X86_64_SSE_CLASS;
118 /* Classify the argument of type TYPE and mode MODE.
119 CLASSES will be filled by the register class used to pass each word
120 of the operand. The number of words is returned. In case the parameter
121 should be passed in memory, 0 is returned. As a special case for zero
122 sized containers, classes[0] will be NO_CLASS and 1 is returned.
124 See the x86-64 PS ABI for details.
126 static int
127 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
128 int *byte_offset)
130 /* First, align to the right place. */
131 *byte_offset = ALIGN(*byte_offset, type->alignment);
133 switch (type->type)
135 case FFI_TYPE_UINT8:
136 case FFI_TYPE_SINT8:
137 case FFI_TYPE_UINT16:
138 case FFI_TYPE_SINT16:
139 case FFI_TYPE_UINT32:
140 case FFI_TYPE_SINT32:
141 case FFI_TYPE_UINT64:
142 case FFI_TYPE_SINT64:
143 case FFI_TYPE_POINTER:
144 if (((*byte_offset) % 8 + type->size) <= 4)
145 classes[0] = X86_64_INTEGERSI_CLASS;
146 else
147 classes[0] = X86_64_INTEGER_CLASS;
148 return 1;
149 case FFI_TYPE_FLOAT:
150 if (((*byte_offset) % 8) == 0)
151 classes[0] = X86_64_SSESF_CLASS;
152 else
153 classes[0] = X86_64_SSE_CLASS;
154 return 1;
155 case FFI_TYPE_DOUBLE:
156 classes[0] = X86_64_SSEDF_CLASS;
157 return 1;
158 case FFI_TYPE_LONGDOUBLE:
159 classes[0] = X86_64_X87_CLASS;
160 classes[1] = X86_64_X87UP_CLASS;
161 return 2;
162 case FFI_TYPE_STRUCT:
164 const int UNITS_PER_WORD = 8;
165 int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
166 ffi_type **ptr;
167 int i;
168 enum x86_64_reg_class subclasses[MAX_CLASSES];
170 /* If the struct is larger than 16 bytes, pass it on the stack. */
171 if (type->size > 16)
172 return 0;
174 for (i = 0; i < words; i++)
175 classes[i] = X86_64_NO_CLASS;
177 /* Merge the fields of structure. */
178 for (ptr=type->elements; (*ptr)!=NULL; ptr++)
180 int num;
182 num = classify_argument (*ptr, subclasses, byte_offset);
183 if (num == 0)
184 return 0;
185 for (i = 0; i < num; i++)
187 int pos = *byte_offset / 8;
188 classes[i + pos] =
189 merge_classes (subclasses[i], classes[i + pos]);
192 if ((*ptr)->type != FFI_TYPE_STRUCT)
193 *byte_offset += (*ptr)->size;
196 /* Final merger cleanup. */
197 for (i = 0; i < words; i++)
199 /* If one class is MEMORY, everything should be passed in
200 memory. */
201 if (classes[i] == X86_64_MEMORY_CLASS)
202 return 0;
204 /* The X86_64_SSEUP_CLASS should be always preceded by
205 X86_64_SSE_CLASS. */
206 if (classes[i] == X86_64_SSEUP_CLASS
207 && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
208 classes[i] = X86_64_SSE_CLASS;
210 /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
211 if (classes[i] == X86_64_X87UP_CLASS
212 && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
213 classes[i] = X86_64_SSE_CLASS;
215 return words;
218 default:
219 FFI_ASSERT(0);
221 return 0; /* Never reached. */
224 /* Examine the argument and return set number of register required in each
225 class. Return 0 iff parameter should be passed in memory. */
226 static int
227 examine_argument (ffi_type *type, int in_return, int *int_nregs,int *sse_nregs)
229 enum x86_64_reg_class class[MAX_CLASSES];
230 int offset = 0;
231 int n;
233 n = classify_argument (type, class, &offset);
235 if (n == 0)
236 return 0;
238 *int_nregs = 0;
239 *sse_nregs = 0;
240 for (n--; n>=0; n--)
241 switch (class[n])
243 case X86_64_INTEGER_CLASS:
244 case X86_64_INTEGERSI_CLASS:
245 (*int_nregs)++;
246 break;
247 case X86_64_SSE_CLASS:
248 case X86_64_SSESF_CLASS:
249 case X86_64_SSEDF_CLASS:
250 (*sse_nregs)++;
251 break;
252 case X86_64_NO_CLASS:
253 case X86_64_SSEUP_CLASS:
254 break;
255 case X86_64_X87_CLASS:
256 case X86_64_X87UP_CLASS:
257 if (!in_return)
258 return 0;
259 break;
260 default:
261 abort ();
263 return 1;
266 /* Functions to load floats and double to an SSE register placeholder. */
267 extern void float2sse (float, __int128_t *);
268 extern void double2sse (double, __int128_t *);
269 extern void floatfloat2sse (void *, __int128_t *);
271 /* Functions to put the floats and doubles back. */
272 extern float sse2float (__int128_t *);
273 extern double sse2double (__int128_t *);
274 extern void sse2floatfloat(__int128_t *, void *);
276 /*@-exportheader@*/
277 void
278 ffi_prep_args (stackLayout *stack, extended_cif *ecif)
279 /*@=exportheader@*/
281 int gprcount, ssecount, i, g, s;
282 void **p_argv;
283 void *argp = &stack->argspace;
284 ffi_type **p_arg;
286 /* First check if the return value should be passed in memory. If so,
287 pass the pointer as the first argument. */
288 gprcount = ssecount = 0;
289 if (ecif->cif->rtype->type != FFI_TYPE_VOID
290 && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
291 (void *)stack->gpr[gprcount++] = ecif->rvalue;
293 for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
294 i!=0; i--, p_arg++, p_argv++)
296 int in_register = 0;
298 switch ((*p_arg)->type)
300 case FFI_TYPE_SINT8:
301 case FFI_TYPE_SINT16:
302 case FFI_TYPE_SINT32:
303 case FFI_TYPE_SINT64:
304 case FFI_TYPE_UINT8:
305 case FFI_TYPE_UINT16:
306 case FFI_TYPE_UINT32:
307 case FFI_TYPE_UINT64:
308 case FFI_TYPE_POINTER:
309 if (gprcount < MAX_GPR_REGS)
311 stack->gpr[gprcount] = 0;
312 stack->gpr[gprcount++] = *(long long *)(*p_argv);
313 in_register = 1;
315 break;
317 case FFI_TYPE_FLOAT:
318 if (ssecount < MAX_SSE_REGS)
320 float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
321 in_register = 1;
323 break;
325 case FFI_TYPE_DOUBLE:
326 if (ssecount < MAX_SSE_REGS)
328 double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
329 in_register = 1;
331 break;
334 if (in_register)
335 continue;
337 /* Either all places in registers where filled, or this is a
338 type that potentially goes into a memory slot. */
339 if (examine_argument (*p_arg, 0, &g, &s) == 0
340 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
342 /* Pass this argument in memory. */
343 argp = (void *)ALIGN(argp, (*p_arg)->alignment);
344 memcpy (argp, *p_argv, (*p_arg)->size);
345 argp += (*p_arg)->size;
347 else
349 /* All easy cases are eliminated. Now fire the big guns. */
351 enum x86_64_reg_class classes[MAX_CLASSES];
352 int offset = 0, j, num;
353 void *a;
355 num = classify_argument (*p_arg, classes, &offset);
356 for (j=0, a=*p_argv; j<num; j++, a+=8)
358 switch (classes[j])
360 case X86_64_INTEGER_CLASS:
361 case X86_64_INTEGERSI_CLASS:
362 stack->gpr[gprcount++] = *(long long *)a;
363 break;
364 case X86_64_SSE_CLASS:
365 floatfloat2sse (a, &stack->sse[ssecount++]);
366 break;
367 case X86_64_SSESF_CLASS:
368 float2sse (*(float *)a, &stack->sse[ssecount++]);
369 break;
370 case X86_64_SSEDF_CLASS:
371 double2sse (*(double *)a, &stack->sse[ssecount++]);
372 break;
373 default:
374 abort();
381 /* Perform machine dependent cif processing. */
382 ffi_status
383 ffi_prep_cif_machdep (ffi_cif *cif)
385 int gprcount, ssecount, i, g, s;
387 gprcount = ssecount = 0;
389 /* Reset the byte count. We handle this size estimation here. */
390 cif->bytes = 0;
392 /* If the return value should be passed in memory, pass the pointer
393 as the first argument. The actual memory isn't allocated here. */
394 if (cif->rtype->type != FFI_TYPE_VOID
395 && examine_argument (cif->rtype, 1, &g, &s) == 0)
396 gprcount = 1;
398 /* Go over all arguments and determine the way they should be passed.
399 If it's in a register and there is space for it, let that be so. If
400 not, add it's size to the stack byte count. */
401 for (i=0; i<cif->nargs; i++)
403 if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
404 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
406 /* This is passed in memory. First align to the basic type. */
407 cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
409 /* Stack arguments are *always* at least 8 byte aligned. */
410 cif->bytes = ALIGN(cif->bytes, 8);
412 /* Now add the size of this argument. */
413 cif->bytes += cif->arg_types[i]->size;
415 else
417 gprcount += g;
418 ssecount += s;
422 /* Set the flag for the closures return. */
423 switch (cif->rtype->type)
425 case FFI_TYPE_VOID:
426 case FFI_TYPE_STRUCT:
427 case FFI_TYPE_SINT64:
428 case FFI_TYPE_FLOAT:
429 case FFI_TYPE_DOUBLE:
430 case FFI_TYPE_LONGDOUBLE:
431 cif->flags = (unsigned) cif->rtype->type;
432 break;
434 case FFI_TYPE_UINT64:
435 cif->flags = FFI_TYPE_SINT64;
436 break;
438 default:
439 cif->flags = FFI_TYPE_INT;
440 break;
443 return FFI_OK;
446 typedef struct
448 long gpr[2];
449 __int128_t sse[2];
450 long double st0;
451 } return_value;
453 void
454 ffi_fill_return_value (return_value *rv, extended_cif *ecif)
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;
463 /* This is needed because of the way x86-64 handles signed short
464 integers. */
465 switch (ecif->cif->rtype->type)
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. */
480 num = classify_argument (ecif->cif->rtype, classes, &i);
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
492 void *a;
494 for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
496 switch (classes[i])
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();
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@*/
528 void ffi_call(/*@dependent@*/ ffi_cif *cif,
529 void (*fn)(),
530 /*@out@*/ void *rvalue,
531 /*@dependent@*/ void **avalue)
533 extended_cif ecif;
534 int dummy;
536 ecif.cif = cif;
537 ecif.avalue = avalue;
539 /* If the return value is a struct and we don't have a return */
540 /* value address then we need to make one */
542 if ((rvalue == NULL) &&
543 (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
545 /*@-sysunrecog@*/
546 ecif.rvalue = alloca(cif->rtype->size);
547 /*@=sysunrecog@*/
549 else
550 ecif.rvalue = rvalue;
552 /* Stack must always be 16byte aligned. Make it so. */
553 cif->bytes = ALIGN(cif->bytes, 16);
555 switch (cif->abi)
557 case FFI_SYSV:
558 /* Calling 32bit code from 64bit is not possible */
559 FFI_ASSERT(0);
560 break;
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;
569 default:
570 FFI_ASSERT(0);
571 break;
575 extern void ffi_closure_UNIX64(void);
577 ffi_status
578 ffi_prep_closure (ffi_closure* closure,
579 ffi_cif* cif,
580 void (*fun)(ffi_cif*, void*, void**, void*),
581 void *user_data)
583 volatile unsigned short *tramp;
585 /* FFI_ASSERT (cif->abi == FFI_OSF); */
587 tramp = (volatile unsigned short *) &closure->tramp[0];
588 tramp[0] = 0xbb49; /* mov <code>, %r11 */
589 tramp[5] = 0xba49; /* mov <data>, %r10 */
590 tramp[10] = 0xff49; /* jmp *%r11 */
591 tramp[11] = 0x00e3;
592 *(void * volatile *) &tramp[1] = ffi_closure_UNIX64;
593 *(void * volatile *) &tramp[6] = closure;
595 closure->cif = cif;
596 closure->fun = fun;
597 closure->user_data = user_data;
599 return FFI_OK;
603 ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp)
605 ffi_cif *cif;
606 void **avalue;
607 ffi_type **arg_types;
608 long i, avn, argn;
610 cif = closure->cif;
611 avalue = alloca(cif->nargs * sizeof(void *));
613 argn = 0;
615 i = 0;
616 avn = cif->nargs;
617 arg_types = cif->arg_types;
619 /* Grab the addresses of the arguments from the stack frame. */
620 while (i < avn)
622 switch (arg_types[i]->type)
624 case FFI_TYPE_SINT8:
625 case FFI_TYPE_UINT8:
626 case FFI_TYPE_SINT16:
627 case FFI_TYPE_UINT16:
628 case FFI_TYPE_SINT32:
629 case FFI_TYPE_UINT32:
630 case FFI_TYPE_SINT64:
631 case FFI_TYPE_UINT64:
632 case FFI_TYPE_POINTER:
634 if (l->gp_offset > 48-8)
636 avalue[i] = l->overflow_arg_area;
637 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
639 else
641 avalue[i] = (char *)l->reg_save_area + l->gp_offset;
642 l->gp_offset += 8;
645 break;
647 case FFI_TYPE_STRUCT:
648 /* FIXME */
649 FFI_ASSERT(0);
650 break;
652 case FFI_TYPE_DOUBLE:
654 if (l->fp_offset > 176-16)
656 avalue[i] = l->overflow_arg_area;
657 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
659 else
661 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
662 l->fp_offset += 16;
665 #if DEBUG_FFI
666 fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);
667 #endif
668 break;
670 case FFI_TYPE_FLOAT:
672 if (l->fp_offset > 176-16)
674 avalue[i] = l->overflow_arg_area;
675 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
677 else
679 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
680 l->fp_offset += 16;
683 #if DEBUG_FFI
684 fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);
685 #endif
686 break;
688 default:
689 FFI_ASSERT(0);
692 argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
693 i++;
696 /* Invoke the closure. */
697 (closure->fun) (cif, rp, avalue, closure->user_data);
699 /* FIXME: Structs not supported. */
700 FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);
702 /* Tell ffi_closure_UNIX64 how to perform return type promotions. */
704 return cif->rtype->type;
706 #endif /* ifndef __x86_64__ */