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

📄 ffi.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	  break;	case FFI_TYPE_STRUCT:#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE	case FFI_TYPE_LONGDOUBLE:#endif	  /* We must allocate space for a copy of these to enforce	     pass-by-value.  Pad the space up to a multiple of 16	     bytes (the maximum alignment required for anything under	     the SYSV ABI).  */	  struct_copy_size += ((*ptr)->size + 15) & ~0xF;	  /* Fall through (allocate space for the pointer).  */	default:	  /* Everything else is passed as a 4-byte word in a GPR, either	     the object itself or a pointer to it.  */	  intarg_count++;	  break;	}    }  if (fparg_count != 0)    flags |= FLAG_FP_ARGUMENTS;  if (intarg_count > 4)    flags |= FLAG_4_GPR_ARGUMENTS;  if (struct_copy_size != 0)    flags |= FLAG_ARG_NEEDS_COPY;    /* Space for the FPR registers, if needed.  */  if (fparg_count != 0)    bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);  /* Stack space.  */  if (intarg_count > NUM_GPR_ARG_REGISTERS)    bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);  if (fparg_count > NUM_FPR_ARG_REGISTERS)    bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);  /* The stack space allocated needs to be a multiple of 16 bytes.  */  bytes = (bytes + 15) & ~0xF;  /* Add in the space for the copied structures.  */  bytes += struct_copy_size;  cif->flags = flags;  cif->bytes = bytes;  return FFI_OK;}/*@-declundef@*//*@-exportheader@*/extern void ffi_call_SYSV(/*@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_SYSV:    case FFI_GCC_SYSV:      /*@-usedef@*/      ffi_call_SYSV(&ecif, -cif->bytes, 		    cif->flags, ecif.rvalue, fn);      /*@=usedef@*/      break;    default:      FFI_ASSERT(0);      break;    }}static void flush_icache(char *, int);ffi_statusffi_prep_closure (ffi_closure* closure,		  ffi_cif* cif,		  void (*fun)(ffi_cif*, void*, void**, void*),		  void *user_data){  unsigned int *tramp;  FFI_ASSERT (cif->abi == FFI_GCC_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 */  closure->cif = cif;  closure->fun = fun;  closure->user_data = user_data;  /* Flush the icache.  */  flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);  return FFI_OK;}#define MIN_CACHE_LINE_SIZE 8static void flush_icache(char * addr1, int size){  int i;  char * addr;  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) {     addr = addr1 + i;     __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory");  }  addr = addr1 + size - 1;  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory");}int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*,                                      unsigned long*, 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, unsigned long * 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;   cif = closure->cif;  avalue = alloca(cif->nargs * sizeof(void *));  nf = 0;  ng = 0;  /* 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 = *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:	case FFI_TYPE_STRUCT:	/* 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_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).  This is also true             * of floats passed on the outgoing parameter stack.             * Also, on the outgoing stack all values are aligned             * to 8             *             * Don't you just love the simplicity of this ABI!             */          /* there are 8 64bit floating point registers */          if (nf < 8) {	     temp = *(double*)pfr;             *(float*)pfr = (float)temp;	     avalue[i] = pfr;             nf++;             pfr+=2;          } 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...             */	     if (((long)pst) & 4) pst++;	     temp = *(double*)pst;             *(float*)pst = (float)temp;	     avalue[i] = pst;             nf++;             pst+=2;          }	  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+=2;          } 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_osf how to perform return type promotions.  */  return cif->rtype->type;}

⌨️ 快捷键说明

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