install.texi (*-*-linux-gnu): Mention glibc requirements for recent libstdc++.
[official-gcc.git] / libffi / src / ia64 / ffi.c
blob4338d34c4b0413afdf32661f1aeec60c22dfd0cf
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1998 Cygnus Solutions
3 Copyright (c) 2000 Hewlett Packard Company
5 IA64 Foreign Function Interface
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:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25 ----------------------------------------------------------------------- */
27 #include <ffi.h>
28 #include <ffi_common.h>
30 #include <stdlib.h>
32 #include "ia64_flags.h"
34 /* Memory image of fp register contents. Should eventually be an fp */
35 /* type long enough to hold an entire register. For now we use double. */
36 typedef double float80;
38 /* The stack layout at call to ffi_prep_args. Other_args will remain */
39 /* on the stack for the actual call. Everything else we be transferred */
40 /* to registers and popped by the assembly code. */
42 struct ia64_args {
43 long scratch[2]; /* Two scratch words at top of stack. */
44 /* Allows sp to be passed as arg pointer. */
45 void * r8_contents; /* Value to be passed in r8 */
46 long spare; /* Not used. */
47 float80 fp_regs[8]; /* Contents of 8 floating point argument */
48 /* registers. */
49 long out_regs[8]; /* Contents of the 8 out registers used */
50 /* for integer parameters. */
51 long other_args[0]; /* Arguments passed on stack, variable size */
52 /* Treated as continuation of out_regs. */
55 static size_t float_type_size(unsigned short tp)
57 switch(tp) {
58 case FFI_TYPE_FLOAT:
59 return sizeof(float);
60 case FFI_TYPE_DOUBLE:
61 return sizeof(double);
62 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
63 case FFI_TYPE_LONGDOUBLE:
64 return sizeof(long double);
65 #endif
66 default:
67 FFI_ASSERT(0);
72 * Is type a struct containing at most n floats, doubles, or extended
73 * doubles, all of the same fp type?
74 * If so, set *element_type to the fp type.
76 static bool is_homogeneous_fp_aggregate(ffi_type * type, int n,
77 unsigned short * element_type)
79 ffi_type **ptr;
80 unsigned short element, struct_element;
82 int type_set = 0;
84 FFI_ASSERT(type != NULL);
86 FFI_ASSERT(type->elements != NULL);
88 ptr = &(type->elements[0]);
90 while ((*ptr) != NULL)
92 switch((*ptr) -> type) {
93 case FFI_TYPE_FLOAT:
94 if (type_set && element != FFI_TYPE_FLOAT) return 0;
95 if (--n < 0) return FALSE;
96 type_set = 1;
97 element = FFI_TYPE_FLOAT;
98 break;
99 case FFI_TYPE_DOUBLE:
100 if (type_set && element != FFI_TYPE_DOUBLE) return 0;
101 if (--n < 0) return FALSE;
102 type_set = 1;
103 element = FFI_TYPE_DOUBLE;
104 break;
105 case FFI_TYPE_STRUCT:
106 if (!is_homogeneous_fp_aggregate(type, n, &struct_element))
107 return FALSE;
108 if (type_set && struct_element != element) return FALSE;
109 n -= (type -> size)/float_type_size(element);
110 element = struct_element;
111 if (n < 0) return FALSE;
112 break;
113 /* case FFI_TYPE_LONGDOUBLE:
114 Not yet implemented. */
115 default:
116 return FALSE;
118 ptr++;
120 *element_type = element;
121 return TRUE;
125 /* ffi_prep_args is called by the assembly routine once stack space
126 has been allocated for the function's arguments. It fills in
127 the arguments in the structure referenced by stack. Returns nonzero
128 if fp registers are used for arguments. */
130 static bool
131 ffi_prep_args(struct ia64_args *stack, extended_cif *ecif, int bytes)
133 register long i, avn;
134 register void **p_argv;
135 register long *argp = stack -> out_regs;
136 register float80 *fp_argp = stack -> fp_regs;
137 register ffi_type **p_arg;
139 /* For big return structs, r8 needs to contain the target address. */
140 /* Since r8 is otherwise dead, we set it unconditionally. */
141 stack -> r8_contents = ecif -> rvalue;
142 i = 0;
143 avn = ecif->cif->nargs;
144 p_arg = ecif->cif->arg_types;
145 p_argv = ecif->avalue;
146 while (i < avn)
148 size_t z; /* z is in units of arg slots or words, not bytes. */
150 switch ((*p_arg)->type)
152 case FFI_TYPE_SINT8:
153 z = 1;
154 *(SINT64 *) argp = *(SINT8 *)(* p_argv);
155 break;
157 case FFI_TYPE_UINT8:
158 z = 1;
159 *(UINT64 *) argp = *(UINT8 *)(* p_argv);
160 break;
162 case FFI_TYPE_SINT16:
163 z = 1;
164 *(SINT64 *) argp = *(SINT16 *)(* p_argv);
165 break;
167 case FFI_TYPE_UINT16:
168 z = 1;
169 *(UINT64 *) argp = *(UINT16 *)(* p_argv);
170 break;
172 case FFI_TYPE_SINT32:
173 z = 1;
174 *(SINT64 *) argp = *(SINT32 *)(* p_argv);
175 break;
177 case FFI_TYPE_UINT32:
178 z = 1;
179 *(UINT64 *) argp = *(UINT32 *)(* p_argv);
180 break;
182 case FFI_TYPE_SINT64:
183 case FFI_TYPE_UINT64:
184 case FFI_TYPE_POINTER:
185 z = 1;
186 *(UINT64 *) argp = *(UINT64 *)(* p_argv);
187 break;
189 case FFI_TYPE_FLOAT:
190 z = 1;
191 if (fp_argp - stack->fp_regs < 8)
193 /* Note the conversion -- all the fp regs are loaded as
194 doubles. */
195 *fp_argp++ = *(float *)(* p_argv);
197 /* Also put it into the integer registers or memory: */
198 *(UINT64 *) argp = *(UINT32 *)(* p_argv);
199 break;
201 case FFI_TYPE_DOUBLE:
202 z = 1;
203 if (fp_argp - stack->fp_regs < 8)
204 *fp_argp++ = *(double *)(* p_argv);
205 /* Also put it into the integer registers or memory: */
206 *(double *) argp = *(double *)(* p_argv);
207 break;
209 case FFI_TYPE_STRUCT:
211 size_t sz = (*p_arg)->size;
212 unsigned short element_type;
213 z = ((*p_arg)->size + SIZEOF_ARG - 1)/SIZEOF_ARG;
214 if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) {
215 int i;
216 int nelements = sz/float_type_size(element_type);
217 for (i = 0; i < nelements; ++i) {
218 switch (element_type) {
219 case FFI_TYPE_FLOAT:
220 if (fp_argp - stack->fp_regs < 8)
221 *fp_argp++ = ((float *)(* p_argv))[i];
222 break;
223 case FFI_TYPE_DOUBLE:
224 if (fp_argp - stack->fp_regs < 8)
225 *fp_argp++ = ((double *)(* p_argv))[i];
226 break;
227 default:
228 /* Extended precision not yet implemented. */
229 abort();
233 /* And pass it in integer registers as a struct, with */
234 /* its actual field sizes packed into registers. */
235 memcpy(argp, *p_argv, (*p_arg)->size);
237 break;
239 default:
240 FFI_ASSERT(0);
243 argp += z;
244 i++, p_arg++, p_argv++;
246 return (fp_argp != stack -> fp_regs);
249 /* Perform machine dependent cif processing */
250 ffi_status
251 ffi_prep_cif_machdep(ffi_cif *cif)
253 long i, avn;
254 bool is_simple = TRUE;
255 long simple_flag = FFI_SIMPLE_V;
256 /* Adjust cif->bytes to include space for the 2 scratch words,
257 r8 register contents, spare word,
258 the 8 fp register contents, and all 8 integer register contents.
259 This will be removed before the call, though 2 scratch words must
260 remain. */
262 cif->bytes += 4*sizeof(long) + 8 *sizeof(float80);
263 if (cif->bytes < sizeof(struct ia64_args))
264 cif->bytes = sizeof(struct ia64_args);
266 /* The stack must be double word aligned, so round bytes up
267 appropriately. */
269 cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
271 avn = cif->nargs;
272 if (avn <= 2) {
273 for (i = 0; i < avn; ++i) {
274 switch(cif -> arg_types[i] -> type) {
275 case FFI_TYPE_SINT32:
276 simple_flag = FFI_ADD_INT_ARG(simple_flag);
277 break;
278 case FFI_TYPE_SINT64:
279 case FFI_TYPE_UINT64:
280 case FFI_TYPE_POINTER:
281 simple_flag = FFI_ADD_LONG_ARG(simple_flag);
282 break;
283 default:
284 is_simple = FALSE;
287 } else {
288 is_simple = FALSE;
291 /* Set the return type flag */
292 switch (cif->rtype->type)
294 case FFI_TYPE_VOID:
295 cif->flags = FFI_TYPE_VOID;
296 break;
298 case FFI_TYPE_STRUCT:
300 size_t sz = cif -> rtype -> size;
301 unsigned short element_type;
303 is_simple = FALSE;
304 if (is_homogeneous_fp_aggregate(cif -> rtype, 8, &element_type)) {
305 int nelements = sz/float_type_size(element_type);
306 if (nelements <= 1) {
307 if (0 == nelements) {
308 cif -> flags = FFI_TYPE_VOID;
309 } else {
310 cif -> flags = element_type;
312 } else {
313 switch(element_type) {
314 case FFI_TYPE_FLOAT:
315 cif -> flags = FFI_IS_FLOAT_FP_AGGREGATE | nelements;
316 break;
317 case FFI_TYPE_DOUBLE:
318 cif -> flags = FFI_IS_DOUBLE_FP_AGGREGATE | nelements;
319 break;
320 default:
321 /* long double NYI */
322 abort();
325 break;
327 if (sz <= 32) {
328 if (sz <= 8) {
329 cif->flags = FFI_TYPE_INT;
330 } else if (sz <= 16) {
331 cif->flags = FFI_IS_SMALL_STRUCT2;
332 } else if (sz <= 24) {
333 cif->flags = FFI_IS_SMALL_STRUCT3;
334 } else {
335 cif->flags = FFI_IS_SMALL_STRUCT4;
337 } else {
338 cif->flags = FFI_TYPE_STRUCT;
341 break;
343 case FFI_TYPE_FLOAT:
344 is_simple = FALSE;
345 cif->flags = FFI_TYPE_FLOAT;
346 break;
348 case FFI_TYPE_DOUBLE:
349 is_simple = FALSE;
350 cif->flags = FFI_TYPE_DOUBLE;
351 break;
353 default:
354 cif->flags = FFI_TYPE_INT;
355 /* This seems to depend on little endian mode, and the fact that */
356 /* the return pointer always points to at least 8 bytes. But */
357 /* that also seems to be true for other platforms. */
358 break;
361 if (is_simple) cif -> flags |= simple_flag;
362 return FFI_OK;
365 extern int ffi_call_unix(bool (*)(struct ia64_args *, extended_cif *, int),
366 extended_cif *, unsigned,
367 unsigned, unsigned *, void (*)());
369 void
370 ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
372 extended_cif ecif;
373 long simple = cif -> flags & FFI_SIMPLE;
375 /* Should this also check for Unix ABI? */
376 /* This is almost, but not quite, machine independent. Note that */
377 /* we can get away with not caring about length of the result because */
378 /* we assume we are little endian, and the result buffer is large */
379 /* enough. */
380 /* This needs work for HP/UX. */
381 if (simple) {
382 long (*lfn)() = (long (*)())fn;
383 long result;
384 switch(simple) {
385 case FFI_SIMPLE_V:
386 result = lfn();
387 break;
388 case FFI_SIMPLE_I:
389 result = lfn(*(int *)avalue[0]);
390 break;
391 case FFI_SIMPLE_L:
392 result = lfn(*(long *)avalue[0]);
393 break;
394 case FFI_SIMPLE_II:
395 result = lfn(*(int *)avalue[0], *(int *)avalue[1]);
396 break;
397 case FFI_SIMPLE_IL:
398 result = lfn(*(int *)avalue[0], *(long *)avalue[1]);
399 break;
400 case FFI_SIMPLE_LI:
401 result = lfn(*(long *)avalue[0], *(int *)avalue[1]);
402 break;
403 case FFI_SIMPLE_LL:
404 result = lfn(*(long *)avalue[0], *(long *)avalue[1]);
405 break;
407 if ((cif->flags & ~FFI_SIMPLE) != FFI_TYPE_VOID && 0 != rvalue) {
408 * (long *)rvalue = result;
410 return;
412 ecif.cif = cif;
413 ecif.avalue = avalue;
415 /* If the return value is a struct and we don't have a return
416 value address then we need to make one. */
418 if (rvalue == NULL && cif->rtype->type == FFI_TYPE_STRUCT)
419 ecif.rvalue = alloca(cif->rtype->size);
420 else
421 ecif.rvalue = rvalue;
423 switch (cif->abi)
425 case FFI_UNIX:
426 ffi_call_unix(ffi_prep_args, &ecif, cif->bytes,
427 cif->flags, rvalue, fn);
428 break;
430 default:
431 FFI_ASSERT(0);
432 break;
437 * Closures represent a pair consisting of a function pointer, and
438 * some user data. A closure is invoked by reinterpreting the closure
439 * as a function pointer, and branching to it. Thus we can make an
440 * interpreted function callable as a C function: We turn the interpreter
441 * itself, together with a pointer specifying the interpreted procedure,
442 * into a closure.
443 * On X86, the first few words of the closure structure actually contain code,
444 * which will do the right thing. On most other architectures, this
445 * would raise some Icache/Dcache coherence issues (which can be solved, but
446 * often not cheaply).
447 * For IA64, function pointer are already pairs consisting of a code
448 * pointer, and a gp pointer. The latter is needed to access global variables.
449 * Here we set up such a pair as the first two words of the closure (in
450 * the "trampoline" area), but we replace the gp pointer with a pointer
451 * to the closure itself. We also add the real gp pointer to the
452 * closure. This allows the function entry code to both retrieve the
453 * user data, and to restire the correct gp pointer.
456 static void
457 ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue,
458 void **avalue, ffi_cif *cif);
460 /* This function is entered with the doctored gp (r1) value.
461 * This code is extremely gcc specific. There is some argument that
462 * it should really be written in assembly code, since it depends on
463 * gcc properties that might change over time.
466 /* ffi_closure_UNIX is an assembly routine, which copies the register */
467 /* state into a struct ia64_args, and then invokes */
468 /* ffi_closure_UNIX_inner. It also recovers the closure pointer */
469 /* from its fake gp pointer. */
470 void ffi_closure_UNIX();
472 #ifndef __GNUC__
473 # error This requires gcc
474 #endif
475 void
476 ffi_closure_UNIX_inner (ffi_closure *closure, struct ia64_args * args)
477 /* Hopefully declaring this as a varargs function will force all args */
478 /* to memory. */
480 // this is our return value storage
481 long double res;
483 // our various things...
484 ffi_cif *cif;
485 unsigned short rtype;
486 void *resp;
487 void **arg_area;
489 resp = (void*)&res;
490 cif = closure->cif;
491 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
493 /* this call will initialize ARG_AREA, such that each
494 * element in that array points to the corresponding
495 * value on the stack; and if the function returns
496 * a structure, it will re-set RESP to point to the
497 * structure return address. */
499 ffi_prep_incoming_args_UNIX(args, (void**)&resp, arg_area, cif);
501 (closure->fun) (cif, resp, arg_area, closure->user_data);
503 rtype = cif->flags;
505 /* now, do a generic return based on the value of rtype */
506 if (rtype == FFI_TYPE_INT)
508 asm volatile ("ld8 r8=[%0]" : : "r" (resp) : "r8");
510 else if (rtype == FFI_TYPE_FLOAT)
512 asm volatile ("ldfs f8=[%0]" : : "r" (resp) : "f8");
514 else if (rtype == FFI_TYPE_DOUBLE)
516 asm volatile ("ldfd f8=[%0]" : : "r" (resp) : "f8");
518 else if (rtype == FFI_IS_SMALL_STRUCT2)
520 asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]"
521 : : "r" (resp), "r" (resp+8) : "r8","r9");
523 else if (rtype == FFI_IS_SMALL_STRUCT3)
525 asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]"
526 : : "r" (resp), "r" (resp+8), "r" (resp+16)
527 : "r8","r9","r10");
529 else if (rtype == FFI_IS_SMALL_STRUCT4)
531 asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]; ld8 r11=[%3]"
532 : : "r" (resp), "r" (resp+8), "r" (resp+16), "r" (resp+24)
533 : "r8","r9","r10","r11");
535 else if (rtype != FFI_TYPE_VOID && rtype != FFI_TYPE_STRUCT)
537 /* Can only happen for homogeneous FP aggregates? */
538 abort();
542 static void
543 ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue,
544 void **avalue, ffi_cif *cif)
546 register unsigned int i;
547 register unsigned int avn;
548 register void **p_argv;
549 register unsigned long *argp = args -> out_regs;
550 unsigned fp_reg_num = 0;
551 register ffi_type **p_arg;
553 avn = cif->nargs;
554 p_argv = avalue;
556 for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
558 size_t z; /* In units of words or argument slots. */
560 switch ((*p_arg)->type)
562 case FFI_TYPE_SINT8:
563 case FFI_TYPE_UINT8:
564 case FFI_TYPE_SINT16:
565 case FFI_TYPE_UINT16:
566 case FFI_TYPE_SINT32:
567 case FFI_TYPE_UINT32:
568 case FFI_TYPE_SINT64:
569 case FFI_TYPE_UINT64:
570 case FFI_TYPE_POINTER:
571 z = 1;
572 *p_argv = (void *)argp;
573 break;
575 case FFI_TYPE_FLOAT:
576 z = 1;
577 /* Convert argument back to float in place from the saved value */
578 if (fp_reg_num < 8) {
579 *(float *)argp = args -> fp_regs[fp_reg_num++];
580 } else {
581 *(float *)argp = *(double *)argp;
583 *p_argv = (void *)argp;
584 break;
586 case FFI_TYPE_DOUBLE:
587 z = 1;
588 if (fp_reg_num < 8) {
589 *p_argv = args -> fp_regs + fp_reg_num++;
590 } else {
591 *p_argv = (void *)argp;
593 break;
595 case FFI_TYPE_STRUCT:
597 size_t sz = (*p_arg)->size;
598 unsigned short element_type;
599 z = ((*p_arg)->size + SIZEOF_ARG - 1)/SIZEOF_ARG;
600 if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) {
601 int nelements = sz/float_type_size(element_type);
602 if (nelements + fp_reg_num >= 8) {
603 /* hard case NYI. */
604 abort();
606 if (element_type == FFI_TYPE_DOUBLE) {
607 *p_argv = args -> fp_regs + fp_reg_num;
608 fp_reg_num += nelements;
609 break;
611 if (element_type == FFI_TYPE_FLOAT) {
612 int j;
613 for (j = 0; j < nelements; ++ j) {
614 ((float *)argp)[j] = args -> fp_regs[fp_reg_num + j];
616 *p_argv = (void *)argp;
617 fp_reg_num += nelements;
618 break;
620 abort(); /* Other fp types NYI */
623 break;
625 default:
626 FFI_ASSERT(0);
629 argp += z;
630 p_argv++;
634 return;
638 /* Fill in a closure to refer to the specified fun and user_data. */
639 /* cif specifies the argument and result types for fun. */
640 /* the cif must already be prep'ed */
642 /* The layout of a function descriptor. A C function pointer really */
643 /* points to one of these. */
644 typedef struct ia64_fd_struct {
645 void *code_pointer;
646 void *gp;
647 } ia64_fd;
649 ffi_status
650 ffi_prep_closure (ffi_closure* closure,
651 ffi_cif* cif,
652 void (*fun)(ffi_cif*,void*,void**,void*),
653 void *user_data)
655 struct ffi_ia64_trampoline_struct *tramp =
656 (struct ffi_ia64_trampoline_struct *) (closure -> tramp);
657 ia64_fd *fd = (ia64_fd *)(void *)ffi_closure_UNIX;
659 FFI_ASSERT (cif->abi == FFI_UNIX);
661 tramp -> code_pointer = fd -> code_pointer;
662 tramp -> real_gp = fd -> gp;
663 tramp -> fake_gp = closure;
664 closure->cif = cif;
665 closure->user_data = user_data;
666 closure->fun = fun;
668 return FFI_OK;