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

📄 ffi.c

📁 gcc的组建
💻 C
📖 第 1 页 / 共 3 页
字号:
		  void *user_data){#ifdef POWERPC64  void **tramp = (void **) &closure->tramp[0];  FFI_ASSERT (cif->abi == FFI_LINUX64);  /* Copy function address and TOC from ffi_closure_LINUX64.  */  memcpy (tramp, (char *) ffi_closure_LINUX64, 16);  tramp[2] = (void *) closure;#else  unsigned int *tramp;  FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);  tramp = (unsigned int *) &closure->tramp[0];  tramp[0] = 0x7c0802a6;  /*   mflr    r0 */  tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */  tramp[4] = 0x7d6802a6;  /*   mflr    r11 */  tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */  tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */  tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */  tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */  tramp[9] = 0x4e800420;  /*   bctr */  *(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */  *(void **) &tramp[3] = (void *)closure;          /* context */  /* Flush the icache.  */  flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);#endif  closure->cif = cif;  closure->fun = fun;  closure->user_data = user_data;  return FFI_OK;}typedef union{  float f;  double d;} ffi_dblfl;int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,			     ffi_dblfl*, unsigned long*);/* Basically the trampoline invokes ffi_closure_SYSV, and on * entry, r11 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 */intffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue,			 unsigned long * pgr, ffi_dblfl * pfr,			 unsigned long * pst){  /* rvalue is the pointer to space for return value in closure assembly */  /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */  /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */  /* pst is the pointer to outgoing parameter stack in original caller */  void **          avalue;  ffi_type **      arg_types;  long             i, avn;  long             nf;   /* number of floating registers already used */  long             ng;   /* number of general registers already used */  ffi_cif *        cif;  double           temp;  unsigned         size;  cif = closure->cif;  avalue = alloca(cif->nargs * sizeof(void *));  size = cif->rtype->size;  nf = 0;  ng = 0;  /* Copy the caller's structure return value address so that the closure     returns the data directly to the caller.     For FFI_SYSV the result is passed in r3/r4 if the struct size is less     or equal 8 bytes.  */  if (cif->rtype->type == FFI_TYPE_STRUCT)    {      if (!((cif->abi == FFI_SYSV) && (size <= 8))) {	rvalue = (void *) *pgr;	ng++;	pgr++;      }    }  i = 0;  avn = cif->nargs;  arg_types = cif->arg_types;  /* Grab the addresses of the arguments from the stack frame.  */  while (i < avn)    {      switch (arg_types[i]->type)	{	case FFI_TYPE_SINT8:	case FFI_TYPE_UINT8:	  /* there are 8 gpr registers used to pass values */	  if (ng < 8) {	    avalue[i] = (((char *)pgr)+3);	    ng++;	    pgr++;	  } else {	    avalue[i] = (((char *)pst)+3);	    pst++;	  }	  break;	case FFI_TYPE_SINT16:	case FFI_TYPE_UINT16:	  /* there are 8 gpr registers used to pass values */	  if (ng < 8) {	    avalue[i] = (((char *)pgr)+2);	    ng++;	    pgr++;	  } else {	    avalue[i] = (((char *)pst)+2);	    pst++;	  }	  break;	case FFI_TYPE_SINT32:	case FFI_TYPE_UINT32:	case FFI_TYPE_POINTER:	  /* there are 8 gpr registers used to pass values */	  if (ng < 8) {	    avalue[i] = pgr;	    ng++;	    pgr++;	  } else {	    avalue[i] = pst;	    pst++;	  }	  break;	case FFI_TYPE_STRUCT:	  /* Structs are passed by reference. The address will appear in a	     gpr if it is one of the first 8 arguments.  */	  if (ng < 8) {	    avalue[i] = (void *) *pgr;	    ng++;	    pgr++;	  } else {	    avalue[i] = (void *) *pst;	    pst++;	  }	  break;	case FFI_TYPE_SINT64:	case FFI_TYPE_UINT64:	  /* passing long long ints are complex, they must	   * be passed in suitable register pairs such as	   * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)	   * and if the entire pair aren't available then the outgoing	   * parameter stack is used for both but an alignment of 8	   * must will be kept.  So we must either look in pgr	   * or pst to find the correct address for this type	   * of parameter.	   */	  if (ng < 7) {	    if (ng & 0x01) {	      /* skip r4, r6, r8 as starting points */	      ng++;	      pgr++;	    }	    avalue[i] = pgr;	    ng+=2;	    pgr+=2;	  } else {	    if (((long)pst) & 4) pst++;	    avalue[i] = pst;	    pst+=2;	  }	  break;	case FFI_TYPE_FLOAT:	  /* unfortunately float values are stored as doubles	   * in the ffi_closure_SYSV code (since we don't check	   * the type in that routine).	   */	  /* there are 8 64bit floating point registers */	  if (nf < 8) {	    temp = pfr->d;	    pfr->f = (float)temp;	    avalue[i] = pfr;	    nf++;	    pfr++;	  } else {	    /* FIXME? here we are really changing the values	     * stored in the original calling routines outgoing	     * parameter stack.  This is probably a really	     * naughty thing to do but...	     */	    avalue[i] = pst;	    nf++;	    pst+=1;	  }	  break;	case FFI_TYPE_DOUBLE:	  /* On the outgoing stack all values are aligned to 8 */	  /* there are 8 64bit floating point registers */	  if (nf < 8) {	    avalue[i] = pfr;	    nf++;	    pfr++;	  } else {	    if (((long)pst) & 4) pst++;	    avalue[i] = pst;	    nf++;	    pst+=2;	  }	  break;	default:	  FFI_ASSERT(0);	}      i++;    }  (closure->fun) (cif, rvalue, avalue, closure->user_data);  /* Tell ffi_closure_SYSV how to perform return type promotions.     Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4     we have to tell ffi_closure_SYSV how to treat them.  */  if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT      && size <= 8)    return FFI_SYSV_TYPE_SMALL_STRUCT + size;  return cif->rtype->type;}int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,					   ffi_dblfl*);int FFI_HIDDENffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,			    unsigned long *pst, ffi_dblfl *pfr){  /* rvalue is the pointer to space for return value in closure assembly */  /* pst is the pointer to parameter save area     (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */  /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */  void **avalue;  ffi_type **arg_types;  long i, avn;  ffi_cif *cif;  ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;  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)    {      rvalue = (void *) *pst;      pst++;    }  i = 0;  avn = cif->nargs;  arg_types = cif->arg_types;  /* Grab the addresses of the arguments from the stack frame.  */  while (i < avn)    {      switch (arg_types[i]->type)	{	case FFI_TYPE_SINT8:	case FFI_TYPE_UINT8:	  avalue[i] = (char *) pst + 7;	  pst++;	  break;	case FFI_TYPE_SINT16:	case FFI_TYPE_UINT16:	  avalue[i] = (char *) pst + 6;	  pst++;	  break;	case FFI_TYPE_SINT32:	case FFI_TYPE_UINT32:	  avalue[i] = (char *) pst + 4;	  pst++;	  break;	case FFI_TYPE_SINT64:	case FFI_TYPE_UINT64:	case FFI_TYPE_POINTER:	  avalue[i] = pst;	  pst++;	  break;	case FFI_TYPE_STRUCT:	  /* Structures with size less than eight bytes are passed	     left-padded.  */	  if (arg_types[i]->size < 8)	    avalue[i] = (char *) pst + 8 - arg_types[i]->size;	  else	    avalue[i] = pst;	  pst += (arg_types[i]->size + 7) / 8;	  break;	case FFI_TYPE_FLOAT:	  /* unfortunately float values are stored as doubles	   * in the ffi_closure_LINUX64 code (since we don't check	   * the type in that routine).	   */	  /* there are 13 64bit floating point registers */	  if (pfr < end_pfr)	    {	      double temp = pfr->d;	      pfr->f = (float) temp;	      avalue[i] = pfr;	      pfr++;	    }	  else	    avalue[i] = pst;	  pst++;	  break;	case FFI_TYPE_DOUBLE:	  /* On the outgoing stack all values are aligned to 8 */	  /* there are 13 64bit floating point registers */	  if (pfr < end_pfr)	    {	      avalue[i] = pfr;	      pfr++;	    }	  else	    avalue[i] = pst;	  pst++;	  break;#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE	case FFI_TYPE_LONGDOUBLE:	  if (pfr + 1 < end_pfr)	    {	      avalue[i] = pfr;	      pfr += 2;	    }	  else	    {	      if (pfr < end_pfr)		{		  /* Passed partly in f13 and partly on the stack.		     Move it all to the stack.  */		  *pst = *(unsigned long *) pfr;		  pfr++;		}	      avalue[i] = pst;	    }	  pst += 2;	  break;#endif	default:	  FFI_ASSERT(0);	}      i++;    }  (closure->fun) (cif, rvalue, avalue, closure->user_data);  /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */  return cif->rtype->type;}

⌨️ 快捷键说明

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