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 ----------------------------------------------------------------------- */
29 #include <ffi_common.h>
34 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 1)
35 # define hidden __attribute__ ((visibility ("hidden")))
41 extern void ffi_closure_SYSV(void);
42 extern void hidden ffi_closure_LINUX64(void);
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. */
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
90 void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack)
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 + (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;
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)
115 /* 'next_arg' grows up as we put parameters in it. */
116 unsigned *next_arg = stack + 2;
122 size_t struct_copy_size;
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;
139 /* Now for the arguments. */
140 p_argv = ecif->avalue;
141 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
143 i--, ptr++, p_argv++)
145 switch ((*ptr)->type)
148 double_tmp = *(float *)*p_argv;
149 if (fparg_count >= NUM_FPR_ARG_REGISTERS)
151 *(float *)next_arg = (float)double_tmp;
155 *fpr_base++ = double_tmp;
157 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
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)
170 *(double *)next_arg = double_tmp;
174 *fpr_base++ = double_tmp;
176 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
179 case FFI_TYPE_UINT64:
180 case FFI_TYPE_SINT64:
181 if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
183 if (intarg_count >= NUM_GPR_ARG_REGISTERS)
185 if (intarg_count%2 != 0)
190 *(long long *)next_arg = *(long long *)*p_argv;
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)
207 *(long long *)gpr_base = *(long long *)*p_argv;
213 case FFI_TYPE_STRUCT:
214 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
215 case FFI_TYPE_LONGDOUBLE:
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);
228 gprvalue = *(unsigned char *)*p_argv;
231 gprvalue = *(signed char *)*p_argv;
233 case FFI_TYPE_UINT16:
234 gprvalue = *(unsigned short *)*p_argv;
236 case FFI_TYPE_SINT16:
237 gprvalue = *(signed short *)*p_argv;
241 case FFI_TYPE_UINT32:
242 case FFI_TYPE_SINT32:
243 case FFI_TYPE_POINTER:
244 gprvalue = *(unsigned *)*p_argv;
246 if (intarg_count >= NUM_GPR_ARG_REGISTERS)
247 *next_arg++ = gprvalue;
249 *gpr_base++ = gprvalue;
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. */
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 |--------------------------------------------| |
298 |--------------------------------------------| | stack pointer here
299 | Current backchain pointer 8 |-/ during
300 |--------------------------------------------| <<< ffi_call_LINUX64
305 void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack)
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;
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;
346 i--, ptr++, p_argv++)
348 switch ((*ptr)->type)
351 double_tmp = *(float *)*p_argv;
352 *(float *)next_arg = (float)double_tmp;
353 if (++next_arg == gpr_end)
355 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
356 *fpr_base++ = double_tmp;
358 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
361 case FFI_TYPE_DOUBLE:
362 double_tmp = *(double *)*p_argv;
363 *(double *)next_arg = double_tmp;
364 if (++next_arg == gpr_end)
366 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
367 *fpr_base++ = double_tmp;
369 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
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)
378 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
379 *fpr_base++ = double_tmp;
381 double_tmp = ((double *) *p_argv)[1];
382 *(double *) next_arg = double_tmp;
383 if (++next_arg == gpr_end)
385 if (fparg_count < NUM_FPR_ARG_REGISTERS64)
386 *fpr_base++ = double_tmp;
388 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
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);
404 char *where = (char *) next_arg;
406 /* Structures with size less than eight bytes are passed
408 if ((*ptr)->size < 8)
409 where += 8 - (*ptr)->size;
411 memcpy (where, (char *) *p_argv, (*ptr)->size);
413 if (next_arg == gpr_end)
419 gprvalue = *(unsigned char *)*p_argv;
422 gprvalue = *(signed char *)*p_argv;
424 case FFI_TYPE_UINT16:
425 gprvalue = *(unsigned short *)*p_argv;
427 case FFI_TYPE_SINT16:
428 gprvalue = *(signed short *)*p_argv;
430 case FFI_TYPE_UINT32:
431 gprvalue = *(unsigned int *)*p_argv;
434 case FFI_TYPE_SINT32:
435 gprvalue = *(signed int *)*p_argv;
438 case FFI_TYPE_UINT64:
439 case FFI_TYPE_SINT64:
440 case FFI_TYPE_POINTER:
441 gprvalue = *(unsigned long *)*p_argv;
443 *next_arg++ = gprvalue;
444 if (next_arg == gpr_end)
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. */
463 int fparg_count = 0, intarg_count = 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);
483 /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
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;
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
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.
505 - integer values in gpr3;
506 - Structures/Unions by reference;
507 - Single/double FP values in fpr1, long double in fpr1,fpr2. */
510 case FFI_TYPE_DOUBLE:
511 flags |= FLAG_RETURNS_64BITS;
514 flags |= FLAG_RETURNS_FP;
517 case FFI_TYPE_UINT64:
518 case FFI_TYPE_SINT64:
519 flags |= FLAG_RETURNS_64BITS;
522 case FFI_TYPE_STRUCT:
523 if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64)
525 if (cif->rtype->size <= 4)
527 else if (cif->rtype->size <= 8)
529 flags |= FLAG_RETURNS_64BITS;
533 /* else fall through. */
534 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
535 case FFI_TYPE_LONGDOUBLE:
538 flags |= FLAG_RETVAL_REFERENCE;
541 flags |= FLAG_RETURNS_NOTHING;
545 /* Returns 32-bit integer, or similar. Nothing to do here. */
549 if (cif->abi != FFI_LINUX64)
550 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
551 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
552 goes on the stack. Structures and long doubles (if not equivalent
553 to double) are passed as a pointer to a copy of the structure.
554 Stuff on the stack needs to keep proper alignment. */
555 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
557 switch ((*ptr)->type)
561 /* floating singles are not 8-aligned on stack */
564 case FFI_TYPE_DOUBLE:
566 /* If this FP arg is going on the stack, it must be
568 if (fparg_count > NUM_FPR_ARG_REGISTERS
569 && intarg_count%2 != 0)
573 case FFI_TYPE_UINT64:
574 case FFI_TYPE_SINT64:
575 /* 'long long' arguments are passed as two words, but
576 either both words must fit in registers or both go
577 on the stack. If they go on the stack, they must
578 be 8-byte-aligned. */
579 if (intarg_count == NUM_GPR_ARG_REGISTERS-1
580 || (intarg_count >= NUM_GPR_ARG_REGISTERS
581 && intarg_count%2 != 0))
586 case FFI_TYPE_STRUCT:
587 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
588 case FFI_TYPE_LONGDOUBLE:
590 /* We must allocate space for a copy of these to enforce
591 pass-by-value. Pad the space up to a multiple of 16
592 bytes (the maximum alignment required for anything under
594 struct_copy_size += ((*ptr)->size + 15) & ~0xF;
595 /* Fall through (allocate space for the pointer). */
598 /* Everything else is passed as a 4-byte word in a GPR, either
599 the object itself or a pointer to it. */
605 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
607 switch ((*ptr)->type)
609 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
610 case FFI_TYPE_LONGDOUBLE:
616 case FFI_TYPE_DOUBLE:
621 case FFI_TYPE_STRUCT:
622 intarg_count += ((*ptr)->size + 7) / 8;
626 /* Everything else is passed as a 8-byte word in a GPR, either
627 the object itself or a pointer to it. */
633 if (fparg_count != 0)
634 flags |= FLAG_FP_ARGUMENTS;
635 if (intarg_count > 4)
636 flags |= FLAG_4_GPR_ARGUMENTS;
637 if (struct_copy_size != 0)
638 flags |= FLAG_ARG_NEEDS_COPY;
640 if (cif->abi != FFI_LINUX64)
642 /* Space for the FPR registers, if needed. */
643 if (fparg_count != 0)
644 bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
647 if (intarg_count > NUM_GPR_ARG_REGISTERS)
648 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);
649 if (fparg_count > NUM_FPR_ARG_REGISTERS)
650 bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);
654 /* Space for the FPR registers, if needed. */
655 if (fparg_count != 0)
656 bytes += NUM_FPR_ARG_REGISTERS64 * sizeof(double);
659 if (intarg_count > NUM_GPR_ARG_REGISTERS64)
660 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof(long);
663 /* The stack space allocated needs to be a multiple of 16 bytes. */
664 bytes = (bytes + 15) & ~0xF;
666 /* Add in the space for the copied structures. */
667 bytes += struct_copy_size;
677 extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
679 /*@out@*/ unsigned *,
681 extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *,
682 unsigned long, unsigned long,
683 /*@out@*/ unsigned long *,
688 void ffi_call(/*@dependent@*/ ffi_cif *cif,
690 /*@out@*/ void *rvalue,
691 /*@dependent@*/ void **avalue)
696 ecif.avalue = avalue;
698 /* If the return value is a struct and we don't have a return */
699 /* value address then we need to make one */
701 if ((rvalue == NULL) &&
702 (cif->rtype->type == FFI_TYPE_STRUCT))
705 ecif.rvalue = alloca(cif->rtype->size);
709 ecif.rvalue = rvalue;
718 ffi_call_SYSV(&ecif, -cif->bytes,
719 cif->flags, ecif.rvalue, fn);
725 ffi_call_LINUX64(&ecif, -(long) cif->bytes,
726 cif->flags, ecif.rvalue, fn);
738 static void flush_icache(char *, int);
740 #define MIN_CACHE_LINE_SIZE 8
742 static void flush_icache(char * addr1, int size)
746 for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) {
748 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory");
750 addr = addr1 + size - 1;
751 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory");
756 ffi_prep_closure (ffi_closure* closure,
758 void (*fun)(ffi_cif*, void*, void**, void*),
762 void **tramp = (void **) &closure->tramp[0];
764 FFI_ASSERT (cif->abi == FFI_LINUX64);
765 /* Copy function address and TOC from ffi_closure_LINUX64. */
766 memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
767 tramp[2] = (void *) closure;
771 FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
773 tramp = (unsigned int *) &closure->tramp[0];
774 tramp[0] = 0x7c0802a6; /* mflr r0 */
775 tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
776 tramp[4] = 0x7d6802a6; /* mflr r11 */
777 tramp[5] = 0x7c0803a6; /* mtlr r0 */
778 tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
779 tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
780 tramp[8] = 0x7c0903a6; /* mtctr r0 */
781 tramp[9] = 0x4e800420; /* bctr */
782 *(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */
783 *(void **) &tramp[3] = (void *)closure; /* context */
785 /* Flush the icache. */
786 flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
791 closure->user_data = user_data;
802 int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,
803 ffi_dblfl*, unsigned long*);
805 /* Basically the trampoline invokes ffi_closure_SYSV, and on
806 * entry, r11 holds the address of the closure.
807 * After storing the registers that could possibly contain
808 * parameters to be passed into the stack frame and setting
809 * up space for a return value, ffi_closure_SYSV invokes the
810 * following helper function to do most of the work
814 ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,
815 unsigned long * pgr, ffi_dblfl * pfr,
818 /* rvalue is the pointer to space for return value in closure assembly */
819 /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
820 /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
821 /* pst is the pointer to outgoing parameter stack in original caller */
824 ffi_type ** arg_types;
826 long nf; /* number of floating registers already used */
827 long ng; /* number of general registers already used */
832 avalue = alloca(cif->nargs * sizeof(void *));
837 /* Copy the caller's structure return value address so that the closure
838 returns the data directly to the caller. */
839 if (cif->rtype->type == FFI_TYPE_STRUCT)
841 rvalue = (void *) *pgr;
848 arg_types = cif->arg_types;
850 /* Grab the addresses of the arguments from the stack frame. */
853 switch (arg_types[i]->type)
857 /* there are 8 gpr registers used to pass values */
859 avalue[i] = (((char *)pgr)+3);
863 avalue[i] = (((char *)pst)+3);
868 case FFI_TYPE_SINT16:
869 case FFI_TYPE_UINT16:
870 /* there are 8 gpr registers used to pass values */
872 avalue[i] = (((char *)pgr)+2);
876 avalue[i] = (((char *)pst)+2);
881 case FFI_TYPE_SINT32:
882 case FFI_TYPE_UINT32:
883 case FFI_TYPE_POINTER:
884 /* there are 8 gpr registers used to pass values */
895 case FFI_TYPE_STRUCT:
896 /* Structs are passed by reference. The address will appear in a
897 gpr if it is one of the first 8 arguments. */
899 avalue[i] = (void *) *pgr;
903 avalue[i] = (void *) *pst;
908 case FFI_TYPE_SINT64:
909 case FFI_TYPE_UINT64:
910 /* passing long long ints are complex, they must
911 * be passed in suitable register pairs such as
912 * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
913 * and if the entire pair aren't available then the outgoing
914 * parameter stack is used for both but an alignment of 8
915 * must will be kept. So we must either look in pgr
916 * or pst to find the correct address for this type
921 /* skip r4, r6, r8 as starting points */
929 if (((long)pst) & 4) pst++;
936 /* unfortunately float values are stored as doubles
937 * in the ffi_closure_SYSV code (since we don't check
938 * the type in that routine).
941 /* there are 8 64bit floating point registers */
945 pfr->f = (float)temp;
950 /* FIXME? here we are really changing the values
951 * stored in the original calling routines outgoing
952 * parameter stack. This is probably a really
953 * naughty thing to do but...
961 case FFI_TYPE_DOUBLE:
962 /* On the outgoing stack all values are aligned to 8 */
963 /* there are 8 64bit floating point registers */
970 if (((long)pst) & 4) pst++;
985 (closure->fun) (cif, rvalue, avalue, closure->user_data);
987 /* Tell ffi_closure_SYSV how to perform return type promotions. */
988 return cif->rtype->type;
992 int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
996 ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
997 unsigned long *pst, ffi_dblfl *pfr)
999 /* rvalue is the pointer to space for return value in closure assembly */
1000 /* pst is the pointer to parameter save area
1001 (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
1002 /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
1005 ffi_type **arg_types;
1008 ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
1011 avalue = alloca (cif->nargs * sizeof (void *));
1013 /* Copy the caller's structure return value address so that the closure
1014 returns the data directly to the caller. */
1015 if (cif->rtype->type == FFI_TYPE_STRUCT)
1017 rvalue = (void *) *pst;
1023 arg_types = cif->arg_types;
1025 /* Grab the addresses of the arguments from the stack frame. */
1028 switch (arg_types[i]->type)
1030 case FFI_TYPE_SINT8:
1031 case FFI_TYPE_UINT8:
1032 avalue[i] = (char *) pst + 7;
1036 case FFI_TYPE_SINT16:
1037 case FFI_TYPE_UINT16:
1038 avalue[i] = (char *) pst + 6;
1042 case FFI_TYPE_SINT32:
1043 case FFI_TYPE_UINT32:
1044 avalue[i] = (char *) pst + 4;
1048 case FFI_TYPE_SINT64:
1049 case FFI_TYPE_UINT64:
1050 case FFI_TYPE_POINTER:
1055 case FFI_TYPE_STRUCT:
1056 /* Structures with size less than eight bytes are passed
1058 if (arg_types[i]->size < 8)
1059 avalue[i] = (char *) pst + 8 - arg_types[i]->size;
1062 pst += (arg_types[i]->size + 7) / 8;
1065 case FFI_TYPE_FLOAT:
1066 /* unfortunately float values are stored as doubles
1067 * in the ffi_closure_LINUX64 code (since we don't check
1068 * the type in that routine).
1071 /* there are 13 64bit floating point registers */
1075 double temp = pfr->d;
1076 pfr->f = (float) temp;
1085 case FFI_TYPE_DOUBLE:
1086 /* On the outgoing stack all values are aligned to 8 */
1087 /* there are 13 64bit floating point registers */
1099 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1100 case FFI_TYPE_LONGDOUBLE:
1101 if (pfr + 1 < end_pfr)
1110 /* Passed partly in f13 and partly on the stack.
1111 Move it all to the stack. */
1112 *pst = *(unsigned long *) pfr;
1129 (closure->fun) (cif, rvalue, avalue, closure->user_data);
1131 /* Tell ffi_closure_LINUX64 how to perform return type promotions. */
1132 return cif->rtype->type;