This commit was manufactured by cvs2svn to create branch
[official-gcc.git] / libffi / src / powerpc / ffi.c
blob454c7ac35e58a8dd7e5967130750138d5c7a1a47
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1998 Geoffrey Keating
4 PowerPC Foreign Function Interface
6 $Id: ffi.c,v 1.1.1.1 1998/11/29 16:48:16 green Exp $
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 ``Software''), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice shall be included
17 in all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
28 #include <ffi.h>
29 #include <ffi_common.h>
31 #include <stdlib.h>
32 #include <stdio.h>
34 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 1)
35 # define hidden __attribute__ ((visibility ("hidden")))
36 #else
37 # define hidden
38 #endif
41 extern void ffi_closure_SYSV(void);
42 extern void hidden ffi_closure_LINUX64(void);
44 enum {
45 /* The assembly depends on these exact flags. */
46 FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
47 FLAG_RETURNS_FP = 1 << (31-29),
48 FLAG_RETURNS_64BITS = 1 << (31-28),
50 FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
51 FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
52 FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
53 FLAG_RETVAL_REFERENCE = 1 << (31- 4)
56 /* About the SYSV ABI. */
57 enum {
58 NUM_GPR_ARG_REGISTERS = 8,
59 NUM_FPR_ARG_REGISTERS = 8
61 enum { ASM_NEEDS_REGISTERS = 4 };
63 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
64 has been allocated for the function's arguments.
66 The stack layout we want looks like this:
68 | Return address from ffi_call_SYSV 4bytes | higher addresses
69 |--------------------------------------------|
70 | Previous backchain pointer 4 | stack pointer here
71 |--------------------------------------------|<+ <<< on entry to
72 | Saved r28-r31 4*4 | | ffi_call_SYSV
73 |--------------------------------------------| |
74 | GPR registers r3-r10 8*4 | | ffi_call_SYSV
75 |--------------------------------------------| |
76 | FPR registers f1-f8 (optional) 8*8 | |
77 |--------------------------------------------| | stack |
78 | Space for copied structures | | grows |
79 |--------------------------------------------| | down V
80 | Parameters that didn't fit in registers | |
81 |--------------------------------------------| | lower addresses
82 | Space for callee's LR 4 | |
83 |--------------------------------------------| | stack pointer here
84 | Current backchain pointer 4 |-/ during
85 |--------------------------------------------| <<< ffi_call_SYSV
89 /*@-exportheader@*/
90 void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack)
91 /*@=exportheader@*/
93 const unsigned bytes = ecif->cif->bytes;
94 const unsigned flags = ecif->cif->flags;
96 /* 'stacktop' points at the previous backchain pointer. */
97 unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
99 /* 'gpr_base' points at the space for gpr3, and grows upwards as
100 we use GPR registers. */
101 unsigned *gpr_base = stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
102 int intarg_count = 0;
104 /* 'fpr_base' points at the space for fpr1, and grows upwards as
105 we use FPR registers. */
106 double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS;
107 int fparg_count = 0;
109 /* 'copy_space' grows down as we put structures in it. It should
110 stay 16-byte aligned. */
111 char *copy_space = ((flags & FLAG_FP_ARGUMENTS)
112 ? (char *)fpr_base
113 : (char *)gpr_base);
115 /* 'next_arg' grows up as we put parameters in it. */
116 unsigned *next_arg = stack + 2;
118 int i;
119 ffi_type **ptr;
120 double double_tmp;
121 void **p_argv;
122 size_t struct_copy_size;
123 unsigned gprvalue;
125 /* Check that everything starts aligned properly. */
126 FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
127 FFI_ASSERT(((unsigned)(char *)copy_space & 0xF) == 0);
128 FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
129 FFI_ASSERT((bytes & 0xF) == 0);
130 FFI_ASSERT(copy_space >= (char *)next_arg);
132 /* Deal with return values that are actually pass-by-reference. */
133 if (flags & FLAG_RETVAL_REFERENCE)
135 *gpr_base++ = (unsigned long)(char *)ecif->rvalue;
136 intarg_count++;
139 /* Now for the arguments. */
140 p_argv = ecif->avalue;
141 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
142 i > 0;
143 i--, ptr++, p_argv++)
145 switch ((*ptr)->type)
147 case FFI_TYPE_FLOAT:
148 double_tmp = *(float *)*p_argv;
149 if (fparg_count >= NUM_FPR_ARG_REGISTERS)
151 *(float *)next_arg = (float)double_tmp;
152 next_arg += 1;
154 else
155 *fpr_base++ = double_tmp;
156 fparg_count++;
157 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
158 break;
160 case FFI_TYPE_DOUBLE:
161 double_tmp = *(double *)*p_argv;
163 if (fparg_count >= NUM_FPR_ARG_REGISTERS)
165 if (intarg_count%2 != 0)
167 intarg_count++;
168 next_arg++;
170 *(double *)next_arg = double_tmp;
171 next_arg += 2;
173 else
174 *fpr_base++ = double_tmp;
175 fparg_count++;
176 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
177 break;
179 case FFI_TYPE_UINT64:
180 case FFI_TYPE_SINT64:
181 if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
182 intarg_count++;
183 if (intarg_count >= NUM_GPR_ARG_REGISTERS)
185 if (intarg_count%2 != 0)
187 intarg_count++;
188 next_arg++;
190 *(long long *)next_arg = *(long long *)*p_argv;
191 next_arg += 2;
193 else
195 /* whoops: abi states only certain register pairs
196 * can be used for passing long long int
197 * specifically (r3,r4), (r5,r6), (r7,r8),
198 * (r9,r10) and if next arg is long long but
199 * not correct starting register of pair then skip
200 * until the proper starting register
202 if (intarg_count%2 != 0)
204 intarg_count ++;
205 gpr_base++;
207 *(long long *)gpr_base = *(long long *)*p_argv;
208 gpr_base += 2;
210 intarg_count += 2;
211 break;
213 case FFI_TYPE_STRUCT:
214 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
215 case FFI_TYPE_LONGDOUBLE:
216 #endif
217 struct_copy_size = ((*ptr)->size + 15) & ~0xF;
218 copy_space -= struct_copy_size;
219 memcpy(copy_space, (char *)*p_argv, (*ptr)->size);
221 gprvalue = (unsigned long)copy_space;
223 FFI_ASSERT(copy_space > (char *)next_arg);
224 FFI_ASSERT(flags & FLAG_ARG_NEEDS_COPY);
225 goto putgpr;
227 case FFI_TYPE_UINT8:
228 gprvalue = *(unsigned char *)*p_argv;
229 goto putgpr;
230 case FFI_TYPE_SINT8:
231 gprvalue = *(signed char *)*p_argv;
232 goto putgpr;
233 case FFI_TYPE_UINT16:
234 gprvalue = *(unsigned short *)*p_argv;
235 goto putgpr;
236 case FFI_TYPE_SINT16:
237 gprvalue = *(signed short *)*p_argv;
238 goto putgpr;
240 case FFI_TYPE_INT:
241 case FFI_TYPE_UINT32:
242 case FFI_TYPE_SINT32:
243 case FFI_TYPE_POINTER:
244 gprvalue = *(unsigned *)*p_argv;
245 putgpr:
246 if (intarg_count >= NUM_GPR_ARG_REGISTERS)
247 *next_arg++ = gprvalue;
248 else
249 *gpr_base++ = gprvalue;
250 intarg_count++;
251 break;
255 /* Check that we didn't overrun the stack... */
256 FFI_ASSERT(copy_space >= (char *)next_arg);
257 FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
258 FFI_ASSERT((unsigned *)fpr_base
259 <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
260 FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
263 /* About the LINUX64 ABI. */
264 enum {
265 NUM_GPR_ARG_REGISTERS64 = 8,
266 NUM_FPR_ARG_REGISTERS64 = 13
268 enum { ASM_NEEDS_REGISTERS64 = 4 };
270 /* ffi_prep_args64 is called by the assembly routine once stack space
271 has been allocated for the function's arguments.
273 The stack layout we want looks like this:
275 | Ret addr from ffi_call_LINUX64 8bytes | higher addresses
276 |--------------------------------------------|
277 | CR save area 8bytes |
278 |--------------------------------------------|
279 | Previous backchain pointer 8 | stack pointer here
280 |--------------------------------------------|<+ <<< on entry to
281 | Saved r28-r31 4*8 | | ffi_call_LINUX64
282 |--------------------------------------------| |
283 | GPR registers r3-r10 8*8 | |
284 |--------------------------------------------| |
285 | FPR registers f1-f13 (optional) 13*8 | |
286 |--------------------------------------------| |
287 | Parameter save area | |
288 |--------------------------------------------| |
289 | TOC save area 8 | |
290 |--------------------------------------------| | stack |
291 | Linker doubleword 8 | | grows |
292 |--------------------------------------------| | down V
293 | Compiler doubleword 8 | |
294 |--------------------------------------------| | lower addresses
295 | Space for callee's LR 8 | |
296 |--------------------------------------------| |
297 | CR save area 8 | |
298 |--------------------------------------------| | stack pointer here
299 | Current backchain pointer 8 |-/ during
300 |--------------------------------------------| <<< ffi_call_LINUX64
304 /*@-exportheader@*/
305 void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack)
306 /*@=exportheader@*/
308 const unsigned long bytes = ecif->cif->bytes;
309 const unsigned long flags = ecif->cif->flags;
311 /* 'stacktop' points at the previous backchain pointer. */
312 unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
314 /* 'next_arg' points at the space for gpr3, and grows upwards as
315 we use GPR registers, then continues at rest. */
316 unsigned long *const gpr_base = stacktop - ASM_NEEDS_REGISTERS64
317 - NUM_GPR_ARG_REGISTERS64;
318 unsigned long *const gpr_end = gpr_base + NUM_GPR_ARG_REGISTERS64;
319 unsigned long *const rest = stack + 6 + NUM_GPR_ARG_REGISTERS64;
320 unsigned long *next_arg = gpr_base;
322 /* 'fpr_base' points at the space for fpr3, and grows upwards as
323 we use FPR registers. */
324 double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS64;
325 int fparg_count = 0;
327 int i, words;
328 ffi_type **ptr;
329 double double_tmp;
330 void **p_argv;
331 unsigned long gprvalue;
333 /* Check that everything starts aligned properly. */
334 FFI_ASSERT(((unsigned long)(char *)stack & 0xF) == 0);
335 FFI_ASSERT(((unsigned long)(char *)stacktop & 0xF) == 0);
336 FFI_ASSERT((bytes & 0xF) == 0);
338 /* Deal with return values that are actually pass-by-reference. */
339 if (flags & FLAG_RETVAL_REFERENCE)
340 *next_arg++ = (unsigned long)(char *)ecif->rvalue;
342 /* Now for the arguments. */
343 p_argv = ecif->avalue;
344 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
345 i > 0;
346 i--, ptr++, p_argv++)
348 switch ((*ptr)->type)
350 case FFI_TYPE_FLOAT:
351 double_tmp = *(float *)*p_argv;
352 *(float *)next_arg = (float)double_tmp;
353 if (++next_arg == gpr_end)
354 next_arg = rest;
355 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
356 *fpr_base++ = double_tmp;
357 fparg_count++;
358 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
359 break;
361 case FFI_TYPE_DOUBLE:
362 double_tmp = *(double *)*p_argv;
363 *(double *)next_arg = double_tmp;
364 if (++next_arg == gpr_end)
365 next_arg = rest;
366 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
367 *fpr_base++ = double_tmp;
368 fparg_count++;
369 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
370 break;
372 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
373 case FFI_TYPE_LONGDOUBLE:
374 double_tmp = ((double *) *p_argv)[0];
375 *(double *) next_arg = double_tmp;
376 if (++next_arg == gpr_end)
377 next_arg = rest;
378 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
379 *fpr_base++ = double_tmp;
380 fparg_count++;
381 double_tmp = ((double *) *p_argv)[1];
382 *(double *) next_arg = double_tmp;
383 if (++next_arg == gpr_end)
384 next_arg = rest;
385 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
386 *fpr_base++ = double_tmp;
387 fparg_count++;
388 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
389 break;
390 #endif
392 case FFI_TYPE_STRUCT:
393 words = ((*ptr)->size + 7) / 8;
394 if (next_arg >= gpr_base && next_arg + words > gpr_end)
396 size_t first = (char *) gpr_end - (char *) next_arg;
397 memcpy((char *) next_arg, (char *) *p_argv, first);
398 memcpy((char *) rest, (char *) *p_argv + first,
399 (*ptr)->size - first);
400 next_arg = (unsigned long *) ((char *) rest + words * 8 - first);
402 else
404 char *where = (char *) next_arg;
406 /* Structures with size less than eight bytes are passed
407 left-padded. */
408 if ((*ptr)->size < 8)
409 where += 8 - (*ptr)->size;
411 memcpy (where, (char *) *p_argv, (*ptr)->size);
412 next_arg += words;
413 if (next_arg == gpr_end)
414 next_arg = rest;
416 break;
418 case FFI_TYPE_UINT8:
419 gprvalue = *(unsigned char *)*p_argv;
420 goto putgpr;
421 case FFI_TYPE_SINT8:
422 gprvalue = *(signed char *)*p_argv;
423 goto putgpr;
424 case FFI_TYPE_UINT16:
425 gprvalue = *(unsigned short *)*p_argv;
426 goto putgpr;
427 case FFI_TYPE_SINT16:
428 gprvalue = *(signed short *)*p_argv;
429 goto putgpr;
430 case FFI_TYPE_UINT32:
431 gprvalue = *(unsigned int *)*p_argv;
432 goto putgpr;
433 case FFI_TYPE_INT:
434 case FFI_TYPE_SINT32:
435 gprvalue = *(signed int *)*p_argv;
436 goto putgpr;
438 case FFI_TYPE_UINT64:
439 case FFI_TYPE_SINT64:
440 case FFI_TYPE_POINTER:
441 gprvalue = *(unsigned long *)*p_argv;
442 putgpr:
443 *next_arg++ = gprvalue;
444 if (next_arg == gpr_end)
445 next_arg = rest;
446 break;
450 FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS
451 || (next_arg >= gpr_base && next_arg <= gpr_base + 4));
456 /* Perform machine dependent cif processing */
457 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
459 /* All this is for the SYSV and LINUX64 ABI. */
460 int i;
461 ffi_type **ptr;
462 unsigned bytes;
463 int fparg_count = 0, intarg_count = 0;
464 unsigned flags = 0;
465 unsigned struct_copy_size = 0;
466 unsigned type = cif->rtype->type;
468 if (cif->abi != FFI_LINUX64)
470 /* All the machine-independent calculation of cif->bytes will be wrong.
471 Redo the calculation for SYSV. */
473 /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
474 bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof(int);
476 /* Space for the GPR registers. */
477 bytes += NUM_GPR_ARG_REGISTERS * sizeof(int);
479 else
481 /* 64-bit ABI. */
483 /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
484 regs. */
485 bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof(long);
487 /* Space for the mandatory parm save area and general registers. */
488 bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof(long);
490 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
491 if (type == FFI_TYPE_LONGDOUBLE)
492 type = FFI_TYPE_DOUBLE;
493 #endif
496 /* Return value handling. The rules for SYSV are as follows:
497 - 32-bit (or less) integer values are returned in gpr3;
498 - Structures of size <= 4 bytes also returned in gpr3;
499 - 64-bit integer values and structures between 5 and 8 bytes are returned
500 in gpr3 and gpr4;
501 - Single/double FP values are returned in fpr1;
502 - Larger structures and long double (if not equivalent to double) values
503 are allocated space and a pointer is passed as the first argument.
504 For LINUX64:
505 - integer values in gpr3;
506 - Structures/Unions by reference;
507 - Single/double FP values in fpr1, long double in fpr1,fpr2. */
508 switch (type)
510 case FFI_TYPE_DOUBLE:
511 flags |= FLAG_RETURNS_64BITS;
512 /* Fall through. */
513 case FFI_TYPE_FLOAT:
514 flags |= FLAG_RETURNS_FP;
515 break;
517 case FFI_TYPE_UINT64:
518 case FFI_TYPE_SINT64:
519 flags |= FLAG_RETURNS_64BITS;
520 break;
522 case FFI_TYPE_STRUCT:
523 if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64)
524 if (cif->rtype->size <= 4)
525 break;
526 else if (cif->rtype->size <= 8)
528 flags |= FLAG_RETURNS_64BITS;
529 break;
531 /* else fall through. */
532 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
533 case FFI_TYPE_LONGDOUBLE:
534 #endif
535 intarg_count++;
536 flags |= FLAG_RETVAL_REFERENCE;
537 /* Fall through. */
538 case FFI_TYPE_VOID:
539 flags |= FLAG_RETURNS_NOTHING;
540 break;
542 default:
543 /* Returns 32-bit integer, or similar. Nothing to do here. */
544 break;
547 if (cif->abi != FFI_LINUX64)
548 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
549 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
550 goes on the stack. Structures and long doubles (if not equivalent
551 to double) are passed as a pointer to a copy of the structure.
552 Stuff on the stack needs to keep proper alignment. */
553 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
555 switch ((*ptr)->type)
557 case FFI_TYPE_FLOAT:
558 fparg_count++;
559 /* floating singles are not 8-aligned on stack */
560 break;
562 case FFI_TYPE_DOUBLE:
563 fparg_count++;
564 /* If this FP arg is going on the stack, it must be
565 8-byte-aligned. */
566 if (fparg_count > NUM_FPR_ARG_REGISTERS
567 && intarg_count%2 != 0)
568 intarg_count++;
569 break;
571 case FFI_TYPE_UINT64:
572 case FFI_TYPE_SINT64:
573 /* 'long long' arguments are passed as two words, but
574 either both words must fit in registers or both go
575 on the stack. If they go on the stack, they must
576 be 8-byte-aligned. */
577 if (intarg_count == NUM_GPR_ARG_REGISTERS-1
578 || (intarg_count >= NUM_GPR_ARG_REGISTERS
579 && intarg_count%2 != 0))
580 intarg_count++;
581 intarg_count += 2;
582 break;
584 case FFI_TYPE_STRUCT:
585 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
586 case FFI_TYPE_LONGDOUBLE:
587 #endif
588 /* We must allocate space for a copy of these to enforce
589 pass-by-value. Pad the space up to a multiple of 16
590 bytes (the maximum alignment required for anything under
591 the SYSV ABI). */
592 struct_copy_size += ((*ptr)->size + 15) & ~0xF;
593 /* Fall through (allocate space for the pointer). */
595 default:
596 /* Everything else is passed as a 4-byte word in a GPR, either
597 the object itself or a pointer to it. */
598 intarg_count++;
599 break;
602 else
603 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
605 switch ((*ptr)->type)
607 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
608 case FFI_TYPE_LONGDOUBLE:
609 fparg_count += 2;
610 intarg_count += 2;
611 break;
612 #endif
613 case FFI_TYPE_FLOAT:
614 case FFI_TYPE_DOUBLE:
615 fparg_count++;
616 intarg_count++;
617 break;
619 case FFI_TYPE_STRUCT:
620 intarg_count += ((*ptr)->size + 7) / 8;
621 break;
623 default:
624 /* Everything else is passed as a 8-byte word in a GPR, either
625 the object itself or a pointer to it. */
626 intarg_count++;
627 break;
631 if (fparg_count != 0)
632 flags |= FLAG_FP_ARGUMENTS;
633 if (intarg_count > 4)
634 flags |= FLAG_4_GPR_ARGUMENTS;
635 if (struct_copy_size != 0)
636 flags |= FLAG_ARG_NEEDS_COPY;
638 if (cif->abi != FFI_LINUX64)
640 /* Space for the FPR registers, if needed. */
641 if (fparg_count != 0)
642 bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
644 /* Stack space. */
645 if (intarg_count > NUM_GPR_ARG_REGISTERS)
646 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);
647 if (fparg_count > NUM_FPR_ARG_REGISTERS)
648 bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);
650 else
652 /* Space for the FPR registers, if needed. */
653 if (fparg_count != 0)
654 bytes += NUM_FPR_ARG_REGISTERS64 * sizeof(double);
656 /* Stack space. */
657 if (intarg_count > NUM_GPR_ARG_REGISTERS64)
658 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof(long);
661 /* The stack space allocated needs to be a multiple of 16 bytes. */
662 bytes = (bytes + 15) & ~0xF;
664 /* Add in the space for the copied structures. */
665 bytes += struct_copy_size;
667 cif->flags = flags;
668 cif->bytes = bytes;
670 return FFI_OK;
673 /*@-declundef@*/
674 /*@-exportheader@*/
675 extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
676 unsigned, unsigned,
677 /*@out@*/ unsigned *,
678 void (*fn)());
679 extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *,
680 unsigned long, unsigned long,
681 /*@out@*/ unsigned long *,
682 void (*fn)());
683 /*@=declundef@*/
684 /*@=exportheader@*/
686 void ffi_call(/*@dependent@*/ ffi_cif *cif,
687 void (*fn)(),
688 /*@out@*/ void *rvalue,
689 /*@dependent@*/ void **avalue)
691 extended_cif ecif;
693 ecif.cif = cif;
694 ecif.avalue = avalue;
696 /* If the return value is a struct and we don't have a return */
697 /* value address then we need to make one */
699 if ((rvalue == NULL) &&
700 (cif->rtype->type == FFI_TYPE_STRUCT))
702 /*@-sysunrecog@*/
703 ecif.rvalue = alloca(cif->rtype->size);
704 /*@=sysunrecog@*/
706 else
707 ecif.rvalue = rvalue;
710 switch (cif->abi)
712 #ifndef POWERPC64
713 case FFI_SYSV:
714 case FFI_GCC_SYSV:
715 /*@-usedef@*/
716 ffi_call_SYSV(&ecif, -cif->bytes,
717 cif->flags, ecif.rvalue, fn);
718 /*@=usedef@*/
719 break;
720 #else
721 case FFI_LINUX64:
722 /*@-usedef@*/
723 ffi_call_LINUX64(&ecif, -(long) cif->bytes,
724 cif->flags, ecif.rvalue, fn);
725 /*@=usedef@*/
726 break;
727 #endif
728 default:
729 FFI_ASSERT(0);
730 break;
735 #ifndef POWERPC64
736 static void flush_icache(char *, int);
738 #define MIN_CACHE_LINE_SIZE 8
740 static void flush_icache(char * addr1, int size)
742 int i;
743 char * addr;
744 for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) {
745 addr = addr1 + i;
746 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory");
748 addr = addr1 + size - 1;
749 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory");
751 #endif
753 ffi_status
754 ffi_prep_closure (ffi_closure* closure,
755 ffi_cif* cif,
756 void (*fun)(ffi_cif*, void*, void**, void*),
757 void *user_data)
759 #ifdef POWERPC64
760 void **tramp = (void **) &closure->tramp[0];
762 FFI_ASSERT (cif->abi == FFI_LINUX64);
763 /* Copy function address and TOC from ffi_closure_LINUX64. */
764 memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
765 tramp[2] = (void *) closure;
766 #else
767 unsigned int *tramp;
769 FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
771 tramp = (unsigned int *) &closure->tramp[0];
772 tramp[0] = 0x7c0802a6; /* mflr r0 */
773 tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
774 tramp[4] = 0x7d6802a6; /* mflr r11 */
775 tramp[5] = 0x7c0803a6; /* mtlr r0 */
776 tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
777 tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
778 tramp[8] = 0x7c0903a6; /* mtctr r0 */
779 tramp[9] = 0x4e800420; /* bctr */
780 *(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */
781 *(void **) &tramp[3] = (void *)closure; /* context */
783 /* Flush the icache. */
784 flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
785 #endif
787 closure->cif = cif;
788 closure->fun = fun;
789 closure->user_data = user_data;
791 return FFI_OK;
794 typedef union
796 float f;
797 double d;
798 } ffi_dblfl;
800 int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
801 ffi_dblfl*, unsigned long*);
803 /* Basically the trampoline invokes ffi_closure_SYSV, and on
804 * entry, r11 holds the address of the closure.
805 * After storing the registers that could possibly contain
806 * parameters to be passed into the stack frame and setting
807 * up space for a return value, ffi_closure_SYSV invokes the
808 * following helper function to do most of the work
812 ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
813 unsigned long * pgr, ffi_dblfl * pfr,
814 unsigned long * pst)
816 /* rvalue is the pointer to space for return value in closure assembly */
817 /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
818 /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
819 /* pst is the pointer to outgoing parameter stack in original caller */
821 void ** avalue;
822 ffi_type ** arg_types;
823 long i, avn;
824 long nf; /* number of floating registers already used */
825 long ng; /* number of general registers already used */
826 ffi_cif * cif;
827 double temp;
829 cif = closure->cif;
830 avalue = alloca(cif->nargs * sizeof(void *));
832 nf = 0;
833 ng = 0;
835 /* Copy the caller's structure return value address so that the closure
836 returns the data directly to the caller. */
837 if (cif->rtype->type == FFI_TYPE_STRUCT)
839 rvalue = (void *) *pgr;
840 ng++;
841 pgr++;
844 i = 0;
845 avn = cif->nargs;
846 arg_types = cif->arg_types;
848 /* Grab the addresses of the arguments from the stack frame. */
849 while (i < avn)
851 switch (arg_types[i]->type)
853 case FFI_TYPE_SINT8:
854 case FFI_TYPE_UINT8:
855 /* there are 8 gpr registers used to pass values */
856 if (ng < 8) {
857 avalue[i] = (((char *)pgr)+3);
858 ng++;
859 pgr++;
860 } else {
861 avalue[i] = (((char *)pst)+3);
862 pst++;
864 break;
866 case FFI_TYPE_SINT16:
867 case FFI_TYPE_UINT16:
868 /* there are 8 gpr registers used to pass values */
869 if (ng < 8) {
870 avalue[i] = (((char *)pgr)+2);
871 ng++;
872 pgr++;
873 } else {
874 avalue[i] = (((char *)pst)+2);
875 pst++;
877 break;
879 case FFI_TYPE_SINT32:
880 case FFI_TYPE_UINT32:
881 case FFI_TYPE_POINTER:
882 /* there are 8 gpr registers used to pass values */
883 if (ng < 8) {
884 avalue[i] = pgr;
885 ng++;
886 pgr++;
887 } else {
888 avalue[i] = pst;
889 pst++;
891 break;
893 case FFI_TYPE_STRUCT:
894 /* Structs are passed by reference. The address will appear in a
895 gpr if it is one of the first 8 arguments. */
896 if (ng < 8) {
897 avalue[i] = (void *) *pgr;
898 ng++;
899 pgr++;
900 } else {
901 avalue[i] = (void *) *pst;
902 pst++;
904 break;
906 case FFI_TYPE_SINT64:
907 case FFI_TYPE_UINT64:
908 /* passing long long ints are complex, they must
909 * be passed in suitable register pairs such as
910 * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
911 * and if the entire pair aren't available then the outgoing
912 * parameter stack is used for both but an alignment of 8
913 * must will be kept. So we must either look in pgr
914 * or pst to find the correct address for this type
915 * of parameter.
917 if (ng < 7) {
918 if (ng & 0x01) {
919 /* skip r4, r6, r8 as starting points */
920 ng++;
921 pgr++;
923 avalue[i] = pgr;
924 ng+=2;
925 pgr+=2;
926 } else {
927 if (((long)pst) & 4) pst++;
928 avalue[i] = pst;
929 pst+=2;
931 break;
933 case FFI_TYPE_FLOAT:
934 /* unfortunately float values are stored as doubles
935 * in the ffi_closure_SYSV code (since we don't check
936 * the type in that routine).
939 /* there are 8 64bit floating point registers */
941 if (nf < 8) {
942 temp = pfr->d;
943 pfr->f = (float)temp;
944 avalue[i] = pfr;
945 nf++;
946 pfr++;
947 } else {
948 /* FIXME? here we are really changing the values
949 * stored in the original calling routines outgoing
950 * parameter stack. This is probably a really
951 * naughty thing to do but...
953 avalue[i] = pst;
954 nf++;
955 pst+=1;
957 break;
959 case FFI_TYPE_DOUBLE:
960 /* On the outgoing stack all values are aligned to 8 */
961 /* there are 8 64bit floating point registers */
963 if (nf < 8) {
964 avalue[i] = pfr;
965 nf++;
966 pfr++;
967 } else {
968 if (((long)pst) & 4) pst++;
969 avalue[i] = pst;
970 nf++;
971 pst+=2;
973 break;
975 default:
976 FFI_ASSERT(0);
979 i++;
983 (closure->fun) (cif, rvalue, avalue, closure->user_data);
985 /* Tell ffi_closure_SYSV how to perform return type promotions. */
986 return cif->rtype->type;
990 int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
991 ffi_dblfl*);
993 int hidden
994 ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
995 unsigned long *pst, ffi_dblfl *pfr)
997 /* rvalue is the pointer to space for return value in closure assembly */
998 /* pst is the pointer to parameter save area
999 (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
1000 /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
1002 void **avalue;
1003 ffi_type **arg_types;
1004 long i, avn;
1005 ffi_cif *cif;
1006 ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
1008 cif = closure->cif;
1009 avalue = alloca (cif->nargs * sizeof (void *));
1011 /* Copy the caller's structure return value address so that the closure
1012 returns the data directly to the caller. */
1013 if (cif->rtype->type == FFI_TYPE_STRUCT)
1015 rvalue = (void *) *pst;
1016 pst++;
1019 i = 0;
1020 avn = cif->nargs;
1021 arg_types = cif->arg_types;
1023 /* Grab the addresses of the arguments from the stack frame. */
1024 while (i < avn)
1026 switch (arg_types[i]->type)
1028 case FFI_TYPE_SINT8:
1029 case FFI_TYPE_UINT8:
1030 avalue[i] = (char *) pst + 7;
1031 pst++;
1032 break;
1034 case FFI_TYPE_SINT16:
1035 case FFI_TYPE_UINT16:
1036 avalue[i] = (char *) pst + 6;
1037 pst++;
1038 break;
1040 case FFI_TYPE_SINT32:
1041 case FFI_TYPE_UINT32:
1042 avalue[i] = (char *) pst + 4;
1043 pst++;
1044 break;
1046 case FFI_TYPE_SINT64:
1047 case FFI_TYPE_UINT64:
1048 case FFI_TYPE_POINTER:
1049 avalue[i] = pst;
1050 pst++;
1051 break;
1053 case FFI_TYPE_STRUCT:
1054 /* Structures with size less than eight bytes are passed
1055 left-padded. */
1056 if (arg_types[i]->size < 8)
1057 avalue[i] = (char *) pst + 8 - arg_types[i]->size;
1058 else
1059 avalue[i] = pst;
1060 pst += (arg_types[i]->size + 7) / 8;
1061 break;
1063 case FFI_TYPE_FLOAT:
1064 /* unfortunately float values are stored as doubles
1065 * in the ffi_closure_LINUX64 code (since we don't check
1066 * the type in that routine).
1069 /* there are 13 64bit floating point registers */
1071 if (pfr < end_pfr)
1073 double temp = pfr->d;
1074 pfr->f = (float) temp;
1075 avalue[i] = pfr;
1076 pfr++;
1078 else
1079 avalue[i] = pst;
1080 pst++;
1081 break;
1083 case FFI_TYPE_DOUBLE:
1084 /* On the outgoing stack all values are aligned to 8 */
1085 /* there are 13 64bit floating point registers */
1087 if (pfr < end_pfr)
1089 avalue[i] = pfr;
1090 pfr++;
1092 else
1093 avalue[i] = pst;
1094 pst++;
1095 break;
1097 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1098 case FFI_TYPE_LONGDOUBLE:
1099 if (pfr + 1 < end_pfr)
1101 avalue[i] = pfr;
1102 pfr += 2;
1104 else
1106 if (pfr < end_pfr)
1108 /* Passed partly in f13 and partly on the stack.
1109 Move it all to the stack. */
1110 *pst = *(unsigned long *) pfr;
1111 pfr++;
1113 avalue[i] = pst;
1115 pst += 2;
1116 break;
1117 #endif
1119 default:
1120 FFI_ASSERT(0);
1123 i++;
1127 (closure->fun) (cif, rvalue, avalue, closure->user_data);
1129 /* Tell ffi_closure_LINUX64 how to perform return type promotions. */
1130 return cif->rtype->type;