37 static int vfp_type_p (ffi_type *);
38 static void layout_vfp_args (ffi_cif *);
43 static char* ffi_align(ffi_type **p_arg,
char *argp)
46 register size_t alignment = (*p_arg)->alignment;
57 if ((alignment - 1) & (
unsigned) argp)
59 argp = (
char *)
ALIGN(argp, alignment);
62 if ((*p_arg)->type == FFI_TYPE_STRUCT)
64 argp = (
char *)
ALIGN(argp, 4);
69 static size_t ffi_put_arg(ffi_type **arg_type,
void **
arg,
char *stack)
71 register char* argp = stack;
72 register ffi_type **p_arg = arg_type;
73 register void **p_argv =
arg;
74 register size_t z = (*p_arg)->size;
78 switch ((*p_arg)->type)
81 *(
signed int *) argp = (
signed int)*(SINT8 *)(* p_argv);
85 *(
unsigned int *) argp = (
unsigned int)*(UINT8 *)(* p_argv);
89 *(
signed int *) argp = (
signed int)*(SINT16 *)(* p_argv);
93 *(
unsigned int *) argp = (
unsigned int)*(UINT16 *)(* p_argv);
97 memcpy(argp, *p_argv, (*p_arg)->size);
104 else if (z ==
sizeof(
int))
106 if ((*p_arg)->type == FFI_TYPE_FLOAT)
107 *(
float *) argp = *(
float *)(* p_argv);
109 *(
unsigned int *) argp = (
unsigned int)*(UINT32 *)(* p_argv);
111 else if (z ==
sizeof(
double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
113 *(
double *) argp = *(
double *)(* p_argv);
130 register unsigned int i;
131 register void **p_argv;
133 register ffi_type **p_arg;
137 if ( ecif->
cif->flags == FFI_TYPE_STRUCT ) {
138 *(
void **) argp = ecif->
rvalue;
144 for (
i = ecif->
cif->nargs, p_arg = ecif->
cif->arg_types;
146 i--, p_arg++, p_argv++)
148 argp = ffi_align(p_arg, argp);
149 argp += ffi_put_arg(p_arg, p_argv, argp);
157 register unsigned int i, vi = 0;
158 register void **p_argv;
159 register char *argp, *regp, *eo_regp;
160 register ffi_type **p_arg;
162 char done_with_regs = 0;
171 eo_regp = argp = regp + 16;
176 if ( ecif->
cif->flags == FFI_TYPE_STRUCT ) {
177 *(
void **) regp = ecif->
rvalue;
183 for (
i = ecif->
cif->nargs, p_arg = ecif->
cif->arg_types;
185 i--, p_arg++, p_argv++)
187 is_vfp_type = vfp_type_p (*p_arg);
190 if(vi < ecif->cif->vfp_nargs && is_vfp_type)
192 char *vfp_slot = (
char *)(vfp_space + ecif->
cif->vfp_args[vi++]);
193 ffi_put_arg(p_arg, p_argv, vfp_slot);
197 else if (!done_with_regs && !is_vfp_type)
199 char *tregp = ffi_align(p_arg, regp);
200 size_t size = (*p_arg)->size;
204 if(tregp +
size <= eo_regp)
206 regp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
207 done_with_regs = (regp == argp);
215 else if (!stack_used)
219 argp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
226 argp = ffi_align(p_arg, argp);
227 argp += ffi_put_arg(p_arg, p_argv, argp);
230 return ecif->
cif->vfp_used;
240 cif->bytes = (cif->bytes + 7) & ~7;
243 switch (cif->rtype->type)
247 case FFI_TYPE_DOUBLE:
248 cif->flags = (
unsigned) cif->rtype->type;
251 case FFI_TYPE_SINT64:
252 case FFI_TYPE_UINT64:
253 cif->flags = (
unsigned) FFI_TYPE_SINT64;
256 case FFI_TYPE_STRUCT:
258 && (type_code = vfp_type_p (cif->rtype)) != 0)
264 else if (cif->rtype->size <= 4)
266 cif->flags = (
unsigned)FFI_TYPE_INT;
271 cif->flags = (
unsigned)FFI_TYPE_STRUCT;
275 cif->flags = FFI_TYPE_INT;
283 layout_vfp_args (cif);
290 unsigned int nfixedargs,
291 unsigned int ntotalargs)
304 void ffi_call(ffi_cif *cif,
void (*fn)(
void),
void *rvalue,
void **avalue)
308 int small_struct = (cif->flags == FFI_TYPE_INT
309 && cif->rtype->type == FFI_TYPE_STRUCT);
321 if ((rvalue ==
NULL) &&
322 (cif->flags == FFI_TYPE_STRUCT))
326 else if (small_struct)
355 memcpy (rvalue, &temp, cif->rtype->size);
368 static void ffi_prep_incoming_args_SYSV (
char *stack,
void **ret,
369 void** args, ffi_cif* cif,
float *vfp_stack);
371 static void ffi_prep_incoming_args_VFP (
char *stack,
void **ret,
372 void** args, ffi_cif* cif,
float *vfp_stack);
382 void **respp,
void *args,
void *vfp_args)
389 arg_area = (
void**)
alloca (cif->nargs * sizeof (
void*));
397 ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args);
399 ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
401 (closure->fun) (cif, *respp, arg_area, closure->user_data);
408 ffi_prep_incoming_args_SYSV(
char *stack,
void **rvalue,
409 void **avalue, ffi_cif *cif,
414 register unsigned int i;
415 register void **p_argv;
417 register ffi_type **p_arg;
421 if ( cif->flags == FFI_TYPE_STRUCT ) {
422 *rvalue = *(
void **) argp;
428 for (
i = cif->nargs, p_arg = cif->arg_types; (
i != 0);
i--, p_arg++)
432 argp = ffi_align(p_arg, argp);
438 *p_argv = (
void*) argp;
449 ffi_prep_incoming_args_VFP(
char *stack,
void **rvalue,
450 void **avalue, ffi_cif *cif,
455 register unsigned int i, vi = 0;
456 register void **p_argv;
457 register char *argp, *regp, *eo_regp;
458 register ffi_type **p_arg;
459 char done_with_regs = 0;
465 eo_regp = argp = regp + 16;
467 if ( cif->flags == FFI_TYPE_STRUCT ) {
468 *rvalue = *(
void **) regp;
474 for (
i = cif->nargs, p_arg = cif->arg_types; (
i != 0);
i--, p_arg++)
477 is_vfp_type = vfp_type_p (*p_arg);
479 if(vi < cif->vfp_nargs && is_vfp_type)
481 *p_argv++ = (
void*)(vfp_stack + cif->vfp_args[vi++]);
484 else if (!done_with_regs && !is_vfp_type)
486 char* tregp = ffi_align(p_arg, regp);
493 if(tregp + z <= eo_regp || !stack_used)
496 *p_argv = (
void*) tregp;
521 argp = ffi_align(p_arg, argp);
527 *p_argv = (
void*) argp;
540 #if FFI_EXEC_TRAMPOLINE_TABLE
542 #include <mach/mach.h>
547 extern void *ffi_closure_trampoline_table_page;
549 typedef struct ffi_trampoline_table ffi_trampoline_table;
550 typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
552 struct ffi_trampoline_table {
554 vm_address_t config_page;
555 vm_address_t trampoline_page;
559 ffi_trampoline_table_entry *free_list;
560 ffi_trampoline_table_entry *free_list_pool;
562 ffi_trampoline_table *prev;
563 ffi_trampoline_table *next;
566 struct ffi_trampoline_table_entry {
567 void *(*trampoline)();
568 ffi_trampoline_table_entry *next;
573 #undef FFI_TRAMPOLINE_SIZE
574 #define FFI_TRAMPOLINE_SIZE 12
577 #define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
580 #define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
583 #define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
586 static ffi_trampoline_table *ffi_trampoline_tables =
NULL;
588 static ffi_trampoline_table *
589 ffi_trampoline_table_alloc ()
591 ffi_trampoline_table *table =
NULL;
594 while (table ==
NULL) {
595 vm_address_t config_page = 0x0;
599 kt = vm_allocate (mach_task_self (), &config_page,
PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
600 if (kt != KERN_SUCCESS) {
601 fprintf(
stderr,
"vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
606 vm_address_t trampoline_page = config_page+
PAGE_SIZE;
607 kt = vm_deallocate (mach_task_self (), trampoline_page,
PAGE_SIZE);
608 if (kt != KERN_SUCCESS) {
609 fprintf(
stderr,
"vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
617 kt = vm_remap (mach_task_self (), &trampoline_page,
PAGE_SIZE, 0x0,
FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page,
FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
620 if (kt != KERN_SUCCESS) {
622 if (kt != KERN_NO_SPACE) {
623 fprintf(
stderr,
"vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
626 vm_deallocate (mach_task_self (), config_page,
PAGE_SIZE);
631 table =
calloc (1,
sizeof(ffi_trampoline_table));
632 table->free_count = FFI_TRAMPOLINE_COUNT;
633 table->config_page = config_page;
634 table->trampoline_page = trampoline_page;
637 table->free_list_pool =
calloc(FFI_TRAMPOLINE_COUNT,
sizeof(ffi_trampoline_table_entry));
640 for (
i = 0;
i < table->free_count;
i++) {
641 ffi_trampoline_table_entry *entry = &table->free_list_pool[
i];
644 if (i < table->free_count - 1)
645 entry->next = &table->free_list_pool[
i+1];
648 table->free_list = table->free_list_pool;
655 ffi_closure_alloc (
size_t size,
void **code)
665 ffi_trampoline_table *table = ffi_trampoline_tables;
666 if (table ==
NULL || table->free_list ==
NULL) {
667 table = ffi_trampoline_table_alloc ();
674 table->next = ffi_trampoline_tables;
675 if (table->next !=
NULL)
676 table->next->prev = table;
678 ffi_trampoline_tables = table;
682 ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
683 ffi_trampoline_tables->free_list = entry->next;
684 ffi_trampoline_tables->free_count--;
690 *code = entry->trampoline;
691 closure->trampoline_table = table;
692 closure->trampoline_table_entry = entry;
698 ffi_closure_free (
void *
ptr)
700 ffi_closure *closure =
ptr;
705 ffi_trampoline_table *table = closure->trampoline_table;
706 ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
709 entry->next = table->free_list;
710 table->free_list = entry;
715 if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
717 if (table->prev !=
NULL)
718 table->prev->next = table->next;
720 if (table->next !=
NULL)
721 table->next->prev = table->prev;
725 kt = vm_deallocate (mach_task_self (), table->config_page,
PAGE_SIZE);
726 if (kt != KERN_SUCCESS)
727 fprintf(
stderr,
"vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
729 kt = vm_deallocate (mach_task_self (), table->trampoline_page,
PAGE_SIZE);
730 if (kt != KERN_SUCCESS)
731 fprintf(
stderr,
"vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
734 free (table->free_list_pool);
736 }
else if (ffi_trampoline_tables != table) {
739 table->next = ffi_trampoline_tables;
740 if (ffi_trampoline_tables !=
NULL)
741 ffi_trampoline_tables->prev = table;
743 ffi_trampoline_tables = table;
754 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
755 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
756 unsigned int __fun = (unsigned int)(FUN); \
757 unsigned int __ctx = (unsigned int)(CTX); \
758 unsigned char *insns = (unsigned char *)(CTX); \
759 memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline); \
760 *(unsigned int*) &__tramp[12] = __ctx; \
761 *(unsigned int*) &__tramp[16] = __fun; \
762 __clear_cache((&__tramp[0]), (&__tramp[19])); \
763 __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \
775 void (*fun)(ffi_cif*,
void*,
void**,
void*),
779 void (*closure_func)(ffi_closure*) =
NULL;
790 #if FFI_EXEC_TRAMPOLINE_TABLE
791 void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
793 config[1] = closure_func;
801 closure->user_data = user_data;
809 static int rec_vfp_type_p (ffi_type *t,
int *elt,
int *elnum)
814 case FFI_TYPE_DOUBLE:
815 *elt = (
int) t->type;
820 *elt = FFI_TYPE_FLOAT;
821 *elnum = t->size / sizeof (
float);
825 *elt = FFI_TYPE_DOUBLE;
826 *elnum = t->size /
sizeof (
double);
829 case FFI_TYPE_STRUCT:;
831 int base_elt = 0, total_elnum = 0;
832 ffi_type **el = t->elements;
835 int el_elt = 0, el_elnum = 0;
836 if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
837 || (base_elt && base_elt != el_elt)
838 || total_elnum + el_elnum > 4)
841 total_elnum += el_elnum;
844 *elnum = total_elnum;
853 static int vfp_type_p (ffi_type *t)
856 if (rec_vfp_type_p (t, &elt, &elnum))
858 if (t->type == FFI_TYPE_STRUCT)
863 t->type = (elt == FFI_TYPE_FLOAT
867 return (
int) t->type;
872 static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
874 short reg = cif->vfp_reg_free;
875 int nregs = t->size /
sizeof (float);
877 || t->type == FFI_TYPE_FLOAT) ? 1 : 2);
879 if ((reg & 1) && align == 2)
881 while (reg + nregs <= 16)
884 for (s = reg; s < reg + nregs; s++)
886 new_used |= (1 << s);
887 if (cif->vfp_used & (1 << s))
894 cif->vfp_used |= new_used;
895 cif->vfp_args[cif->vfp_nargs++] = reg;
898 if (cif->vfp_used & (1 << cif->vfp_reg_free))
901 while (cif->vfp_used & (1 << reg))
903 cif->vfp_reg_free = reg;
909 cif->vfp_reg_free = 16;
910 cif->vfp_used = 0xFFFF;
914 static void layout_vfp_args (ffi_cif *cif)
920 cif->vfp_reg_free = 0;
921 memset (cif->vfp_args, -1, 16);
923 for (
i = 0;
i < cif->nargs;
i++)
925 ffi_type *t = cif->arg_types[
i];
926 if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1)