📄 ffi.c
字号:
for (m = 0; m < n; m++) cif->flags += FFI_TYPE_INT << (2 * j++); break; } }#else for (i = j = 0; i < cif->nargs && j < 4; i++) { size = (cif->arg_types)[i]->size; n = (size + sizeof (int) - 1) / sizeof (int); if (greg >= NGREGARG) continue; else if (greg + n - 1 >= NGREGARG) n = NGREGARG - greg; greg += n; for (m = 0; m < n; m++) cif->flags += FFI_TYPE_INT << (2 * j++); }#endif /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_STRUCT: cif->flags += (unsigned) (return_type (cif->rtype)) << 24; break; case FFI_TYPE_VOID: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: cif->flags += (unsigned) cif->rtype->type << 24; break; default: cif->flags += FFI_TYPE_INT << 24; break; } return FFI_OK;}/*@-declundef@*//*@-exportheader@*/extern void ffi_call_SYSV(void (*)(char *, extended_cif *), /*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, void (*fn)());/*@=declundef@*//*@=exportheader@*/void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, /*@dependent@*/ void **avalue){ extended_cif ecif; UINT64 trvalue; ecif.cif = cif; ecif.avalue = avalue; /* If the return value is a struct and we don't have a return */ /* value address then we need to make one */ if (cif->rtype->type == FFI_TYPE_STRUCT && return_type (cif->rtype) != FFI_TYPE_STRUCT) ecif.rvalue = &trvalue; else if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-sysunrecog@*/ ecif.rvalue = alloca(cif->rtype->size); /*@=sysunrecog@*/ } else ecif.rvalue = rvalue; switch (cif->abi) { case FFI_SYSV: /*@-usedef@*/ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } if (rvalue && cif->rtype->type == FFI_TYPE_STRUCT && return_type (cif->rtype) != FFI_TYPE_STRUCT) memcpy (rvalue, &trvalue, cif->rtype->size);}extern void ffi_closure_SYSV (void);#if defined(__SH4__)extern void __ic_invalidate (void *line);#endifffi_statusffi_prep_closure (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data){ unsigned int *tramp; unsigned short insn; FFI_ASSERT (cif->abi == FFI_GCC_SYSV); tramp = (unsigned int *) &closure->tramp[0]; /* Set T bit if the function returns a struct pointed with R2. */ insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 0x0018 /* sett */ : 0x0008 /* clrt */);#ifdef __LITTLE_ENDIAN__ tramp[0] = 0xd301d102; tramp[1] = 0x0000412b | (insn << 16);#else tramp[0] = 0xd102d301; tramp[1] = 0x412b0000 | insn;#endif *(void **) &tramp[2] = (void *)closure; /* ctx */ *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ closure->cif = cif; closure->fun = fun; closure->user_data = user_data;#if defined(__SH4__) /* Flush the icache. */ __ic_invalidate(&closure->tramp[0]);#endif return FFI_OK;}/* Basically the trampoline invokes ffi_closure_SYSV, and on * entry, r3 holds the address of the closure. * After storing the registers that could possibly contain * parameters to be passed into the stack frame and setting * up space for a return value, ffi_closure_SYSV invokes the * following helper function to do most of the work. */#ifdef __LITTLE_ENDIAN__#define OFS_INT8 0#define OFS_INT16 0#else#define OFS_INT8 3#define OFS_INT16 2#endifintffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, unsigned long *pgr, unsigned long *pfr, unsigned long *pst){ void **avalue; ffi_type **p_arg; int i, avn; int ireg, greg = 0;#if defined(__SH4__) int freg = 0;#endif ffi_cif *cif; double temp; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); /* Copy the caller's structure return value address so that the closure returns the data directly to the caller. */ if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG) { rvalue = *pgr++; ireg = 1; } else ireg = 0; cif = closure->cif; greg = ireg; avn = cif->nargs; /* Grab the addresses of the arguments from the stack frame. */ for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { size_t z; z = (*p_arg)->size; if (z < sizeof(int)) { if (greg++ >= NGREGARG) continue; z = sizeof(int); switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: avalue[i] = (((char *)pgr) + OFS_INT8); break; case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: avalue[i] = (((char *)pgr) + OFS_INT16); break; case FFI_TYPE_STRUCT: avalue[i] = pgr; break; default: FFI_ASSERT(0); } pgr++; } else if (z == sizeof(int)) {#if defined(__SH4__) if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg++ >= NFREGARG) continue; avalue[i] = pfr; pfr++; } else#endif { if (greg++ >= NGREGARG) continue; avalue[i] = pgr; pgr++; } }#if defined(__SH4__) else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 >= NFREGARG) continue; freg = (freg + 1) & ~1; freg += 2; avalue[i] = pfr; pfr += 2; }#endif else { int n = (z + sizeof (int) - 1) / sizeof (int);#if defined(__SH4__) if (greg + n - 1 >= NGREGARG) continue;#else if (greg >= NGREGARG) continue;#endif greg += n; avalue[i] = pgr; pgr += n; } } greg = ireg;#if defined(__SH4__) freg = 0;#endif for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { size_t z; z = (*p_arg)->size; if (z < sizeof(int)) { if (greg++ < NGREGARG) continue; z = sizeof(int); switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: avalue[i] = (((char *)pst) + OFS_INT8); break; case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: avalue[i] = (((char *)pst) + OFS_INT16); break; case FFI_TYPE_STRUCT: avalue[i] = pst; break; default: FFI_ASSERT(0); } pst++; } else if (z == sizeof(int)) {#if defined(__SH4__) if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg++ < NFREGARG) continue; } else#endif { if (greg++ < NGREGARG) continue; } avalue[i] = pst; pst++; }#if defined(__SH4__) else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 < NFREGARG) { freg = (freg + 1) & ~1; freg += 2; continue; } avalue[i] = pst; pst += 2; }#endif else { int n = (z + sizeof (int) - 1) / sizeof (int); if (greg + n - 1 < NGREGARG) { greg += n; continue; }#if (! defined(__SH4__)) else if (greg < NGREGARG) { greg += n; pst += greg - NGREGARG; continue; }#endif avalue[i] = pst; pst += n; } } (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_SYSV how to perform return type promotions. */ return return_type (cif->rtype);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -