⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffi.c

📁 gcc的组建
💻 C
📖 第 1 页 / 共 2 页
字号:
      break;    case FFI_TYPE_UINT64:    case FFI_TYPE_SINT64:      cif->flags = FFI_TYPE_UINT64;      break;    default:      cif->flags = FFI_TYPE_INT;      break;    }  /* Lucky us, because of the unique PA ABI we get to do our     own stack sizing.  */  switch (cif->abi)    {    case FFI_LINUX:      ffi_size_stack_LINUX(cif);      break;    default:      FFI_ASSERT(0);      break;    }  return FFI_OK;}/*@-declundef@*//*@-exportheader@*/extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),			   /*@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;  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 ((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_LINUX:      /*@-usedef@*/      debug(2, "Calling ffi_call_LINUX: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);      ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,		     cif->flags, ecif.rvalue, fn);      /*@=usedef@*/      break;    default:      FFI_ASSERT(0);      break;    }}#if FFI_CLOSURES/* This is more-or-less an inverse of ffi_call -- we have arguments on   the stack, and we need to fill them into a cif structure and invoke   the user function. This really ought to be in asm to make sure   the compiler doesn't do things we don't expect.  */UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack){  ffi_cif *cif;  void **avalue;  void *rvalue;  UINT32 ret[2]; /* function can return up to 64-bits in registers */  ffi_type **p_arg;  char *tmp;  int i, avn, slot = FIRST_ARG_SLOT - 1;  register UINT32 r28 asm("r28");  cif = closure->cif;  /* If returning via structure, callee will write to our pointer.  */  if (cif->flags == FFI_TYPE_STRUCT)    rvalue = (void *)r28;  else    rvalue = &ret[0];  avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);  avn = cif->nargs;  p_arg = cif->arg_types;  for (i = 0; i < avn; i++)    {      int type = (*p_arg)->type;      switch (type)	{	case FFI_TYPE_SINT8:	case FFI_TYPE_UINT8:	case FFI_TYPE_SINT16:	case FFI_TYPE_UINT16:	case FFI_TYPE_SINT32:	case FFI_TYPE_UINT32:	case FFI_TYPE_POINTER:	  slot++;	  avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;	  break;	case FFI_TYPE_SINT64:	case FFI_TYPE_UINT64:	  slot += 2;	  if (slot & 1)	    slot++;	  avalue[i] = (void *)(stack - slot);	  break;	case FFI_TYPE_FLOAT:	  slot++;	  switch (slot - FIRST_ARG_SLOT)	    {	    case 0: fstw(fr4, (void *)(stack - slot)); break;	    case 1: fstw(fr5, (void *)(stack - slot)); break;	    case 2: fstw(fr6, (void *)(stack - slot)); break;	    case 3: fstw(fr7, (void *)(stack - slot)); break;	    }	  avalue[i] = (void *)(stack - slot);	  break;	case FFI_TYPE_DOUBLE:	  slot += 2;	  if (slot & 1)	    slot++;	  switch (slot - FIRST_ARG_SLOT + 1)	    {	    case 2: fstd(fr5, (void *)(stack - slot)); break;	    case 4: fstd(fr7, (void *)(stack - slot)); break;	    }	  avalue[i] = (void *)(stack - slot);	  break;	case FFI_TYPE_STRUCT:	  /* Structs smaller or equal than 4 bytes are passed in one	     register. Structs smaller or equal 8 bytes are passed in two	     registers. Larger structures are passed by pointer.  */	  if((*p_arg)->size <= 4) {	    slot++;	    avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -	      (*p_arg)->size;	  } else if ((*p_arg)->size <= 8) {	    slot += 2;	    if (slot & 1)	      slot++;	    avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -	      (*p_arg)->size;	  } else {	    slot++;	    avalue[i] = (void *) *(stack - slot);	  }	  break;	default:	  FFI_ASSERT(0);	}      p_arg++;    }  /* Invoke the closure.  */  (closure->fun) (cif, rvalue, avalue, closure->user_data);  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], ret[1]);  /* Store the result */  switch (cif->flags)    {    case FFI_TYPE_UINT8:      *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);      break;    case FFI_TYPE_SINT8:      *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);      break;    case FFI_TYPE_UINT16:      *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);      break;    case FFI_TYPE_SINT16:      *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);      break;    case FFI_TYPE_INT:    case FFI_TYPE_SINT32:    case FFI_TYPE_UINT32:      *(stack - FIRST_ARG_SLOT) = ret[0];      break;    case FFI_TYPE_SINT64:    case FFI_TYPE_UINT64:      *(stack - FIRST_ARG_SLOT) = ret[0];      *(stack - FIRST_ARG_SLOT - 1) = ret[1];      break;    case FFI_TYPE_DOUBLE:      fldd(rvalue, fr4);      break;    case FFI_TYPE_FLOAT:      fldw(rvalue, fr4);      break;    case FFI_TYPE_STRUCT:      /* Don't need a return value, done by caller.  */      break;    case FFI_TYPE_SMALL_STRUCT3:      tmp = (void*)(stack -  FIRST_ARG_SLOT);      tmp += 4 - cif->rtype->size;      memcpy((void*)tmp, &ret[0], cif->rtype->size);      break;    case FFI_TYPE_SMALL_STRUCT5:    case FFI_TYPE_SMALL_STRUCT6:    case FFI_TYPE_SMALL_STRUCT7:      {	unsigned int ret2[2];	int off;	/* Right justify ret[0] and ret[1] */	switch (cif->flags)	  {	    case FFI_TYPE_SMALL_STRUCT5: off = 3; break;	    case FFI_TYPE_SMALL_STRUCT6: off = 2; break;	    case FFI_TYPE_SMALL_STRUCT7: off = 1; break;	    default: off = 0; break;	  }	memset (ret2, 0, sizeof (ret2));	memcpy ((char *)ret2 + off, ret, 8 - off);	*(stack - FIRST_ARG_SLOT) = ret2[0];	*(stack - FIRST_ARG_SLOT - 1) = ret2[1];      }      break;    case FFI_TYPE_POINTER:    case FFI_TYPE_VOID:      break;    default:      debug(0, "assert with cif->flags: %d\n",cif->flags);      FFI_ASSERT(0);      break;    }  return FFI_OK;}/* Fill in a closure to refer to the specified fun and user_data.   cif specifies the argument and result types for fun.   The cif must already be prep'ed.  */void ffi_closure_LINUX(void);ffi_statusffi_prep_closure (ffi_closure* closure,		  ffi_cif* cif,		  void (*fun)(ffi_cif*,void*,void**,void*),		  void *user_data){  UINT32 *tramp = (UINT32 *)(closure->tramp);  FFI_ASSERT (cif->abi == FFI_LINUX);  /* Make a small trampoline that will branch to our     handler function. Use PC-relative addressing.  */  tramp[0] = 0xeaa00000; /* b,l  .+8, %r21      ; %r21 <- pc+8 */  tramp[1] = 0xd6a01c1e; /* depi 0,31,2, %r21   ; mask priv bits */  tramp[2] = 0x4aa10028; /* ldw  20(%r21), %r1  ; load plabel */  tramp[3] = 0x36b53ff1; /* ldo  -8(%r21), %r21 ; get closure addr */  tramp[4] = 0x0c201096; /* ldw  0(%r1), %r22   ; address of handler */  tramp[5] = 0xeac0c000; /* bv	 %r0(%r22)      ; branch to handler */  tramp[6] = 0x0c281093; /* ldw  4(%r1), %r19   ; GP of handler */  tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);  /* Flush d/icache -- have to flush up 2 two lines because of     alignment.  */  asm volatile (		"fdc 0(%0)\n"		"fdc %1(%0)\n"		"fic 0(%%sr4, %0)\n"		"fic %1(%%sr4, %0)\n"		"sync\n"		: : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));  closure->cif  = cif;  closure->user_data = user_data;  closure->fun  = fun;  return FFI_OK;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -