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

📄 ffi64.c

📁 gcc的组建
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (n == 0)	{	  /* The return value is passed in memory.  A pointer to that	     memory is the first argument.  Allocate a register for it.  */	  gprcount++;	  /* We don't have to do anything in asm for the return.  */	  flags = FFI_TYPE_VOID;	}      else if (flags == FFI_TYPE_STRUCT)	{	  /* Mark which registers the result appears in.  */	  _Bool sse0 = SSE_CLASS_P (classes[0]);	  _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);	  if (sse0 && !sse1)	    flags |= 1 << 8;	  else if (!sse0 && sse1)	    flags |= 1 << 9;	  else if (sse0 && sse1)	    flags |= 1 << 10;	  /* Mark the true size of the structure.  */	  flags |= cif->rtype->size << 12;	}    }  /* Go over all arguments and determine the way they should be passed.     If it's in a register and there is space for it, let that be so. If     not, add it's size to the stack byte count.  */  for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)    {      if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0	  || gprcount + ngpr > MAX_GPR_REGS	  || ssecount + nsse > MAX_SSE_REGS)	{	  long align = cif->arg_types[i]->alignment;	  if (align < 8)	    align = 8;	  bytes = ALIGN(bytes, align);	  bytes += cif->arg_types[i]->size;	}      else	{	  gprcount += ngpr;	  ssecount += nsse;	}    }  if (ssecount)    flags |= 1 << 11;  cif->flags = flags;  cif->bytes = bytes;  return FFI_OK;}voidffi_call (ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue){  enum x86_64_reg_class classes[MAX_CLASSES];  char *stack, *argp;  ffi_type **arg_types;  int gprcount, ssecount, ngpr, nsse, i, avn;  _Bool ret_in_memory;  struct register_args *reg_args;  /* Can't call 32-bit mode from 64-bit mode.  */  FFI_ASSERT (cif->abi == FFI_UNIX64);  /* If the return value is a struct and we don't have a return value     address then we need to make one.  Note the setting of flags to     VOID above in ffi_prep_cif_machdep.  */  ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT		   && (cif->flags & 0xff) == FFI_TYPE_VOID);  if (rvalue == NULL && ret_in_memory)    rvalue = alloca (cif->rtype->size);  /* Allocate the space for the arguments, plus 4 words of temp space.  */  stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);  reg_args = (struct register_args *) stack;  argp = stack + sizeof (struct register_args);  gprcount = ssecount = 0;  /* If the return value is passed in memory, add the pointer as the     first integer argument.  */  if (ret_in_memory)    reg_args->gpr[gprcount++] = (long) rvalue;  avn = cif->nargs;  arg_types = cif->arg_types;  for (i = 0; i < avn; ++i)    {      size_t size = arg_types[i]->size;      int n;      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);      if (n == 0	  || gprcount + ngpr > MAX_GPR_REGS	  || ssecount + nsse > MAX_SSE_REGS)	{	  long align = arg_types[i]->alignment;	  /* Stack arguments are *always* at least 8 byte aligned.  */	  if (align < 8)	    align = 8;	  /* Pass this argument in memory.  */	  argp = (void *) ALIGN (argp, align);	  memcpy (argp, avalue[i], size);	  argp += size;	}      else	{	  /* The argument is passed entirely in registers.  */	  char *a = (char *) avalue[i];	  int j;	  for (j = 0; j < n; j++, a += 8, size -= 8)	    {	      switch (classes[j])		{		case X86_64_INTEGER_CLASS:		case X86_64_INTEGERSI_CLASS:		  reg_args->gpr[gprcount] = 0;		  memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);		  gprcount++;		  break;		case X86_64_SSE_CLASS:		case X86_64_SSEDF_CLASS:		  reg_args->sse[ssecount++] = *(UINT64 *) a;		  break;		case X86_64_SSESF_CLASS:		  reg_args->sse[ssecount++] = *(UINT32 *) a;		  break;		default:		  abort();		}	    }	}    }  ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),		   cif->flags, rvalue, fn, ssecount);}extern void ffi_closure_unix64(void);ffi_statusffi_prep_closure (ffi_closure* closure,		  ffi_cif* cif,		  void (*fun)(ffi_cif*, void*, void**, void*),		  void *user_data){  volatile unsigned short *tramp;  tramp = (volatile unsigned short *) &closure->tramp[0];  tramp[0] = 0xbb49;		/* mov <code>, %r11	*/  *(void * volatile *) &tramp[1] = ffi_closure_unix64;  tramp[5] = 0xba49;		/* mov <data>, %r10	*/  *(void * volatile *) &tramp[6] = closure;  /* Set the carry bit iff the function uses any sse registers.     This is clc or stc, together with the first byte of the jmp.  */  tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;  tramp[11] = 0xe3ff;			/* jmp *%r11    */  closure->cif = cif;  closure->fun = fun;  closure->user_data = user_data;  return FFI_OK;}intffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,			 struct register_args *reg_args, char *argp){  ffi_cif *cif;  void **avalue;  ffi_type **arg_types;  long i, avn;  int gprcount, ssecount, ngpr, nsse;  int ret;  cif = closure->cif;  avalue = alloca(cif->nargs * sizeof(void *));  gprcount = ssecount = 0;  ret = cif->rtype->type;  if (ret != FFI_TYPE_VOID)    {      enum x86_64_reg_class classes[MAX_CLASSES];      int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);      if (n == 0)	{	  /* The return value goes in memory.  Arrange for the closure	     return value to go directly back to the original caller.  */	  rvalue = (void *) reg_args->gpr[gprcount++];	  /* We don't have to do anything in asm for the return.  */	  ret = FFI_TYPE_VOID;	}      else if (ret == FFI_TYPE_STRUCT && n == 2)	{	  /* Mark which register the second word of the structure goes in.  */	  _Bool sse0 = SSE_CLASS_P (classes[0]);	  _Bool sse1 = SSE_CLASS_P (classes[1]);	  if (!sse0 && sse1)	    ret |= 1 << 8;	  else if (sse0 && !sse1)	    ret |= 1 << 9;	}    }  avn = cif->nargs;  arg_types = cif->arg_types;    for (i = 0; i < avn; ++i)    {      enum x86_64_reg_class classes[MAX_CLASSES];      int n;      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);      if (n == 0	  || gprcount + ngpr > MAX_GPR_REGS	  || ssecount + nsse > MAX_SSE_REGS)	{	  long align = arg_types[i]->alignment;	  /* Stack arguments are *always* at least 8 byte aligned.  */	  if (align < 8)	    align = 8;	  /* Pass this argument in memory.  */	  argp = (void *) ALIGN (argp, align);	  avalue[i] = argp;	  argp += arg_types[i]->size;	}      /* If the argument is in a single register, or two consecutive	 registers, then we can use that address directly.  */      else if (n == 1	       || (n == 2		   && SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))	{	  /* The argument is in a single register.  */	  if (SSE_CLASS_P (classes[0]))	    {	      avalue[i] = &reg_args->sse[ssecount];	      ssecount += n;	    }	  else	    {	      avalue[i] = &reg_args->gpr[gprcount];	      gprcount += n;	    }	}      /* Otherwise, allocate space to make them consecutive.  */      else	{	  char *a = alloca (16);	  int j;	  avalue[i] = a;	  for (j = 0; j < n; j++, a += 8)	    {	      if (SSE_CLASS_P (classes[j]))		memcpy (a, &reg_args->sse[ssecount++], 8);	      else		memcpy (a, &reg_args->gpr[gprcount++], 8);	    }	}    }  /* Invoke the closure.  */  closure->fun (cif, rvalue, avalue, closure->user_data);  /* Tell assembly how to perform return type promotions.  */  return ret;}#endif /* __x86_64__ */

⌨️ 快捷键说明

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