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

📄 i386.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
     make the problem with not enough registers even worse.  */#ifdef INSN_SCHEDULING  if (level > 1)    flag_schedule_insns = 0;#endif}/* Sign-extend a 16-bit constant */struct rtx_def *i386_sext16_if_const (op)     struct rtx_def *op;{  if (GET_CODE (op) == CONST_INT)    {      HOST_WIDE_INT val = INTVAL (op);      HOST_WIDE_INT sext_val;      if (val & 0x8000)	sext_val = val | ~0xffff;      else	sext_val = val & 0xffff;      if (sext_val != val)	op = GEN_INT (sext_val);    }  return op;}/* Return nonzero if the rtx is aligned */static inti386_aligned_reg_p (regno)     int regno;{  return (regno == STACK_POINTER_REGNUM	  || (! flag_omit_frame_pointer && regno == FRAME_POINTER_REGNUM));}inti386_aligned_p (op)     rtx op;{  /* Registers and immediate operands are always "aligned". */  if (GET_CODE (op) != MEM)    return 1;  /* Don't even try to do any aligned optimizations with volatiles. */  if (MEM_VOLATILE_P (op))    return 0;  /* Get address of memory operand. */  op = XEXP (op, 0);  switch (GET_CODE (op))    {    case CONST_INT:      if (INTVAL (op) & 3)	break;      return 1;      /* Match "reg + offset" */    case PLUS:      if (GET_CODE (XEXP (op, 1)) != CONST_INT)	break;      if (INTVAL (XEXP (op, 1)) & 3)	break;      op = XEXP (op, 0);      if (GET_CODE (op) != REG)	break;      /* ... fall through ... */    case REG:      return i386_aligned_reg_p (REGNO (op));    default:      break;    }  return 0;}/* Return nonzero if INSN looks like it won't compute useful cc bits   as a side effect.  This information is only a hint. */inti386_cc_probably_useless_p (insn)     rtx insn;{  return ! next_cc0_user (insn);}/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific   attribute for DECL.  The attributes in ATTRIBUTES have previously been   assigned to DECL.  */inti386_valid_decl_attribute_p (decl, attributes, identifier, args)     tree decl ATTRIBUTE_UNUSED;     tree attributes ATTRIBUTE_UNUSED;     tree identifier ATTRIBUTE_UNUSED;     tree args ATTRIBUTE_UNUSED;{  return 0;}/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific   attribute for TYPE.  The attributes in ATTRIBUTES have previously been   assigned to TYPE.  */inti386_valid_type_attribute_p (type, attributes, identifier, args)     tree type;     tree attributes ATTRIBUTE_UNUSED;     tree identifier;     tree args;{  if (TREE_CODE (type) != FUNCTION_TYPE      && TREE_CODE (type) != METHOD_TYPE      && TREE_CODE (type) != FIELD_DECL      && TREE_CODE (type) != TYPE_DECL)    return 0;  /* Stdcall attribute says callee is responsible for popping arguments     if they are not variable.  */  if (is_attribute_p ("stdcall", identifier))    return (args == NULL_TREE);  /* Cdecl attribute says the callee is a normal C declaration. */  if (is_attribute_p ("cdecl", identifier))    return (args == NULL_TREE);  /* Regparm attribute specifies how many integer arguments are to be     passed in registers. */  if (is_attribute_p ("regparm", identifier))    {      tree cst;      if (! args || TREE_CODE (args) != TREE_LIST	  || TREE_CHAIN (args) != NULL_TREE	  || TREE_VALUE (args) == NULL_TREE)	return 0;      cst = TREE_VALUE (args);      if (TREE_CODE (cst) != INTEGER_CST)	return 0;      if (TREE_INT_CST_HIGH (cst) != 0	  || TREE_INT_CST_LOW (cst) < 0	  || TREE_INT_CST_LOW (cst) > REGPARM_MAX)	return 0;      return 1;    }  return 0;}/* Return 0 if the attributes for two types are incompatible, 1 if they   are compatible, and 2 if they are nearly compatible (which causes a   warning to be generated).  */inti386_comp_type_attributes (type1, type2)     tree type1;     tree type2;{  /* Check for mismatch of non-default calling convention. */  char *rtdstr = TARGET_RTD ? "cdecl" : "stdcall";  if (TREE_CODE (type1) != FUNCTION_TYPE)    return 1;  /* Check for mismatched return types (cdecl vs stdcall).  */  if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))      != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))    return 0;  return 1;}/* Value is the number of bytes of arguments automatically   popped when returning from a subroutine call.   FUNDECL is the declaration node of the function (as a tree),   FUNTYPE is the data type of the function (as a tree),   or for a library call it is an identifier node for the subroutine name.   SIZE is the number of bytes of arguments passed on the stack.   On the 80386, the RTD insn may be used to pop them if the number     of args is fixed, but if the number is variable then the caller     must pop them all.  RTD can't be used for library calls now     because the library is compiled with the Unix compiler.   Use of RTD is a selectable option, since it is incompatible with   standard Unix calling sequences.  If the option is not selected,   the caller must always pop the args.   The attribute stdcall is equivalent to RTD on a per module basis.  */inti386_return_pops_args (fundecl, funtype, size)     tree fundecl;     tree funtype;     int size;{  int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);    /* Cdecl functions override -mrtd, and never pop the stack. */  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {    /* Stdcall functions will pop the stack if not variable args. */    if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))      rtd = 1;    if (rtd        && (TYPE_ARG_TYPES (funtype) == NULL_TREE	    || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype)))		== void_type_node)))      return size;  }  /* Lose any fake structure return argument.  */  if (aggregate_value_p (TREE_TYPE (funtype)))    return GET_MODE_SIZE (Pmode);    return 0;}/* Argument support functions.  *//* Initialize a variable CUM of type CUMULATIVE_ARGS   for a call to a function whose data type is FNTYPE.   For a library call, FNTYPE is 0.  */voidinit_cumulative_args (cum, fntype, libname)     CUMULATIVE_ARGS *cum;	/* Argument info to initialize */     tree fntype;		/* tree ptr for function decl */     rtx libname;		/* SYMBOL_REF of library name or 0 */{  static CUMULATIVE_ARGS zero_cum;  tree param, next_param;  if (TARGET_DEBUG_ARG)    {      fprintf (stderr, "\ninit_cumulative_args (");      if (fntype)	fprintf (stderr, "fntype code = %s, ret code = %s",		 tree_code_name[(int) TREE_CODE (fntype)],		 tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]);      else	fprintf (stderr, "no fntype");      if (libname)	fprintf (stderr, ", libname = %s", XSTR (libname, 0));    }  *cum = zero_cum;  /* Set up the number of registers to use for passing arguments.  */  cum->nregs = i386_regparm;  if (fntype)    {      tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));      if (attr)	cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));    }  /* Determine if this function has variable arguments.  This is     indicated by the last argument being 'void_type_mode' if there     are no variable arguments.  If there are variable arguments, then     we won't pass anything in registers */  if (cum->nregs)    {      for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;	   param != 0; param = next_param)	{	  next_param = TREE_CHAIN (param);	  if (next_param == 0 && TREE_VALUE (param) != void_type_node)	    cum->nregs = 0;	}    }  if (TARGET_DEBUG_ARG)    fprintf (stderr, ", nregs=%d )\n", cum->nregs);  return;}/* Update the data in CUM to advance over an argument   of mode MODE and data type TYPE.   (TYPE is null for libcalls where that information may not be available.)  */voidfunction_arg_advance (cum, mode, type, named)     CUMULATIVE_ARGS *cum;	/* current arg information */     enum machine_mode mode;	/* current arg mode */     tree type;			/* type of the argument or 0 if lib support */     int named;			/* whether or not the argument was named */{  int bytes    = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  if (TARGET_DEBUG_ARG)    fprintf (stderr,	     "function_adv (sz=%d, wds=%2d, nregs=%d, mode=%s, named=%d)\n\n",	     words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);  cum->words += words;  cum->nregs -= words;  cum->regno += words;  if (cum->nregs <= 0)    {      cum->nregs = 0;      cum->regno = 0;    }  return;}/* Define where to put the arguments to a function.   Value is zero to push the argument on the stack,   or a hard register in which to store the argument.   MODE is the argument's machine mode.   TYPE is the data type of the argument (as a tree).    This is null for libcalls where that information may    not be available.   CUM is a variable of type CUMULATIVE_ARGS which gives info about    the preceding args and about the function being called.   NAMED is nonzero if this argument is a named parameter    (otherwise it is an extra parameter matching an ellipsis).  */struct rtx_def *function_arg (cum, mode, type, named)     CUMULATIVE_ARGS *cum;	/* current arg information */     enum machine_mode mode;	/* current arg mode */     tree type;			/* type of the argument or 0 if lib support */     int named;			/* != 0 for normal args, == 0 for ... args */{  rtx ret   = NULL_RTX;  int bytes    = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  switch (mode)    {      /* For now, pass fp/complex values on the stack. */    default:      break;    case BLKmode:    case DImode:    case SImode:    case HImode:    case QImode:      if (words <= cum->nregs)	ret = gen_rtx_REG (mode, cum->regno);      break;    }  if (TARGET_DEBUG_ARG)    {      fprintf (stderr,	       "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d",	       words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);      if (ret)	fprintf (stderr, ", reg=%%e%s", reg_names[ REGNO(ret) ]);      else	fprintf (stderr, ", stack");      fprintf (stderr, " )\n");    }  return ret;}/* For an arg passed partly in registers and partly in memory,   this is the number of registers used.   For args passed entirely in registers or entirely in memory, zero.  */intfunction_arg_partial_nregs (cum, mode, type, named)     CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;	/* current arg information */     enum machine_mode mode ATTRIBUTE_UNUSED;	/* current arg mode */     tree type ATTRIBUTE_UNUSED;		/* type of the argument or 0 if lib support */     int named ATTRIBUTE_UNUSED;		/* != 0 for normal args, == 0 for ... args */{  return 0;}char *singlemove_string (operands)     rtx *operands;{  rtx x;  if (GET_CODE (operands[0]) == MEM      && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC)    {      if (XEXP (x, 0) != stack_pointer_rtx)	abort ();      return "push%L1 %1";    }  else if (GET_CODE (operands[1]) == CONST_DOUBLE)    return output_move_const_single (operands);  else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)    return AS2 (mov%L0,%1,%0);  else if (CONSTANT_P (operands[1]))    return AS2 (mov%L0,%1,%0);  else    {      output_asm_insn ("push%L1 %1", operands);      return "pop%L0 %0";    }}/* Output an insn to add the constant N to the register X.  */static voidasm_add (n, x)     int n;     rtx x;{  rtx xops[2];  xops[0] = x;  if (n == -1)    output_asm_insn (AS1 (dec%L0,%0), xops);  else if (n == 1)    output_asm_insn (AS1 (inc%L0,%0), xops);  else if (n < 0 || n == 128)    {      xops[1] = GEN_INT (-n);      output_asm_insn (AS2 (sub%L0,%1,%0), xops);    }  else if (n > 0)    {      xops[1] = GEN_INT (n);      output_asm_insn (AS2 (add%L0,%1,%0), xops);    }}/* Output assembler code to perform a doubleword move insn   with operands OPERANDS.  */char *output_move_double (operands)     rtx *operands;{  enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;  rtx latehalf[2];  rtx middlehalf[2];  rtx xops[2];  int dest_overlapped_low = 0;  int size = GET_MODE_SIZE (GET_MODE (operands[0]));  middlehalf[0] = 0;  middlehalf[1] = 0;  /* First classify both operands.  */  if (REG_P (operands[0]))    optype0 = REGOP;  else if (offsettable_memref_p (operands[0]))    optype0 = OFFSOP;  else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)    optype0 = POPOP;  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)    optype0 = PUSHOP;  else if (GET_CODE (operands[0]) == MEM)    optype0 = MEMOP;  else

⌨️ 快捷键说明

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