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

📄 rs6000.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  low = operand_subword (op, 1, 0, mode);  if (high == 0 || ! input_operand (high, word_mode))    return 0;  return (mode == SFmode	  || (low != 0 && input_operand (low, word_mode)));}/* Return 1 if the operand is an offsettable memory address.  */intoffsettable_addr_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return offsettable_address_p (reload_completed | reload_in_progress,				mode, op);}/* Return 1 if the operand is either a floating-point register, a pseudo   register, or memory.  */intfp_reg_or_mem_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (memory_operand (op, mode)	  || (register_operand (op, mode)	      && (GET_CODE (op) != REG		  || REGNO (op) >= FIRST_PSEUDO_REGISTER		  || FP_REGNO_P (REGNO (op)))));}/* Return 1 if the operand is either an easy FP constant (see above) or   memory.  */intmem_or_easy_const_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return memory_operand (op, mode) || easy_fp_constant (op, mode);}/* Return 1 if the operand is either a non-special register or an item   that can be used as the operand of an SI add insn.  */intadd_operand (op, mode)    register rtx op;    enum machine_mode mode;{  return (reg_or_short_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0));}/* Return 1 if OP is a constant but not a valid add_operand.  */intnon_add_cint_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT	  && (unsigned) (INTVAL (op) + 0x8000) >= 0x10000	  && (INTVAL (op) & 0xffff) != 0);}/* Return 1 if the operand is a non-special register or a constant that   can be used as the operand of an OR or XOR insn on the RS/6000.  */intlogical_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (gpc_reg_operand (op, mode)	  || (GET_CODE (op) == CONST_INT	      && ((INTVAL (op) & 0xffff0000) == 0		  || (INTVAL (op) & 0xffff) == 0)));}/* Return 1 if C is a constant that is not a logical operand (as   above).  */intnon_logical_cint_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT	  && (INTVAL (op) & 0xffff0000) != 0	  && (INTVAL (op) & 0xffff) != 0);}/* Return 1 if C is a constant that can be encoded in a mask on the   RS/6000.  It is if there are no more than two 1->0 or 0->1 transitions.   Reject all ones and all zeros, since these should have been optimized   away and confuse the making of MB and ME.  */intmask_constant (c)     register int c;{  int i;  int last_bit_value;  int transitions = 0;  if (c == 0 || c == ~0)    return 0;  last_bit_value = c & 1;  for (i = 1; i < 32; i++)    if (((c >>= 1) & 1) != last_bit_value)      last_bit_value ^= 1, transitions++;  return transitions <= 2;}/* Return 1 if the operand is a constant that is a mask on the RS/6000. */intmask_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return GET_CODE (op) == CONST_INT && mask_constant (INTVAL (op));}/* Return 1 if the operand is either a non-special register or a   constant that can be used as the operand of an RS/6000 logical AND insn.  */intand_operand (op, mode)    register rtx op;    enum machine_mode mode;{  return (reg_or_short_operand (op, mode)	  || logical_operand (op, mode)	  || mask_operand (op, mode));}/* Return 1 if the operand is a constant but not a valid operand for an AND   insn.  */intnon_and_cint_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return GET_CODE (op) == CONST_INT && ! and_operand (op, mode);}/* Return 1 if the operand is a general register or memory operand.  */intreg_or_mem_operand (op, mode)     register rtx op;     register enum machine_mode mode;{  return gpc_reg_operand (op, mode) || memory_operand (op, mode);}/* Return 1 if the operand is a general register or memory operand without   pre-inc or pre_dec which produces invalid form of PowerPC lwa   instruction.  */intlwa_operand (op, mode)     register rtx op;     register enum machine_mode mode;{  rtx inner = op;  if (reload_completed && GET_CODE (inner) == SUBREG)    inner = SUBREG_REG (inner);      return gpc_reg_operand (inner, mode)    || (memory_operand (inner, mode)	&& GET_CODE (XEXP (inner, 0)) != PRE_INC	&& GET_CODE (XEXP (inner, 0)) != PRE_DEC);}/* Return 1 if the operand, used inside a MEM, is a valid first argument   to CALL.  This is a SYMBOL_REF or a pseudo-register, which will be   forced to lr.  */intcall_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (mode != VOIDmode && GET_MODE (op) != mode)    return 0;  return (GET_CODE (op) == SYMBOL_REF	  || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER));}/* Return 1 if the operand is a SYMBOL_REF for a function known to be in   this file.  */intcurrent_file_function_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == SYMBOL_REF	  && (SYMBOL_REF_FLAG (op)	      || op == XEXP (DECL_RTL (current_function_decl), 0)));}/* Return 1 if this operand is a valid input for a move insn.  */intinput_operand (op, mode)     register rtx op;     enum machine_mode mode;{  /* Memory is always valid.  */  if (memory_operand (op, mode))    return 1;  /* For floating-point, easy constants are valid.  */  if (GET_MODE_CLASS (mode) == MODE_FLOAT      && CONSTANT_P (op)      && easy_fp_constant (op, mode))    return 1;  /* For floating-point or multi-word mode, the only remaining valid type     is a register.  */  if (GET_MODE_CLASS (mode) == MODE_FLOAT      || GET_MODE_SIZE (mode) > UNITS_PER_WORD)    return register_operand (op, mode);  /* The only cases left are integral modes one word or smaller (we     do not get called for MODE_CC values).  These can be in any     register.  */  if (register_operand (op, mode))    return 1;  /* For HImode and QImode, any constant is valid. */  if ((mode == HImode || mode == QImode)      && GET_CODE (op) == CONST_INT)    return 1;  /* A SYMBOL_REF referring to the TOC is valid.  */  if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op))    return 1;  /* Otherwise, we will be doing this SET with an add, so anything valid     for an add will be valid.  */  return add_operand (op, mode);}/* 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.   For incoming args we set the number of arguments in the prototype large   so we never return an EXPR_LIST.  */voidinit_cumulative_args (cum, fntype, libname, incoming)     CUMULATIVE_ARGS *cum;     tree fntype;     rtx libname;     int incoming;{  static CUMULATIVE_ARGS zero_cumulative;  *cum = zero_cumulative;  cum->words = 0;  cum->fregno = FP_ARG_MIN_REG;  cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));  if (incoming)    {      cum->nargs_prototype = 1000;		/* don't return an EXPR_LIST */#ifdef TARGET_V4_CALLS      if (TARGET_V4_CALLS)	cum->varargs_offset = RS6000_VARARGS_OFFSET;#endif    }  else if (cum->prototype)    cum->nargs_prototype = (list_length (TYPE_ARG_TYPES (fntype)) - 1			    + (TYPE_MODE (TREE_TYPE (fntype)) == BLKmode			       || RETURN_IN_MEMORY (TREE_TYPE (fntype))));  else    cum->nargs_prototype = 0;  cum->orig_nargs = cum->nargs_prototype;  if (TARGET_DEBUG_ARG)    {      fprintf (stderr, "\ninit_cumulative_args:");      if (fntype)	{	  tree ret_type = TREE_TYPE (fntype);	  fprintf (stderr, " ret code = %s,",		   tree_code_name[ (int)TREE_CODE (ret_type) ]);	}#ifdef TARGET_V4_CALLS      if (TARGET_V4_CALLS && incoming)	fprintf (stderr, " varargs = %d, ", cum->varargs_offset);#endif      fprintf (stderr, " proto = %d, nargs = %d\n",	       cum->prototype, cum->nargs_prototype);    }}/* 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;     enum machine_mode mode;     tree type;     int named;{  cum->nargs_prototype--;#ifdef TARGET_V4_CALLS  if (TARGET_V4_CALLS)    {      /* Long longs must not be split between registers and stack */      if ((GET_MODE_CLASS (mode) != MODE_FLOAT || TARGET_SOFT_FLOAT)	  && type && !AGGREGATE_TYPE_P (type)	  && cum->words < GP_ARG_NUM_REG	  && cum->words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)	{	  cum->words = GP_ARG_NUM_REG;	}      /* Aggregates get passed as pointers */      if (type && AGGREGATE_TYPE_P (type))	cum->words++;      /* Floats go in registers, & don't occupy space in the GP registers	 like they do for AIX unless software floating point.  */      else if (GET_MODE_CLASS (mode) == MODE_FLOAT	       && TARGET_HARD_FLOAT	       && cum->fregno <= FP_ARG_V4_MAX_REG)	cum->fregno++;      else	cum->words += RS6000_ARG_SIZE (mode, type, 1);    }  else#endif    if (named)      {	cum->words += RS6000_ARG_SIZE (mode, type, named);	if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)	  cum->fregno++;      }  if (TARGET_DEBUG_ARG)    fprintf (stderr,	     "function_adv: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d\n",	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named);}/* Determine where to put an argument 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).   On RS/6000 the first eight words of non-FP are normally in registers   and the rest are pushed.  Under AIX, the first 13 FP args are in registers.   Under V.4, the first 8 FP args are in registers.   If this is floating-point and no prototype is specified, we use   both an FP and integer register (or possibly FP reg and stack).  Library   functions (when TYPE is zero) always have the proper types for args,   so we can pass the FP value just in one register.  emit_library_function   doesn't support EXPR_LIST anyway.  */struct rtx_def *function_arg (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;{  if (TARGET_DEBUG_ARG)    fprintf (stderr,	     "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d\n",	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named);  /* Return a marker to indicate whether CR1 needs to set or clear the bit that V.4     uses to say fp args were passed in registers.  Assume that we don't need the     marker for software floating point, or compiler generated library calls.  */  if (mode == VOIDmode)    {#ifdef TARGET_V4_CALLS      if (TARGET_V4_CALLS && TARGET_HARD_FLOAT && cum->nargs_prototype < 0	  && type && (cum->prototype || TARGET_NO_PROTOTYPE))	return GEN_INT ((cum->fregno == FP_ARG_MIN_REG) ? -1 : 1);#endif      return GEN_INT (0);    }  if (!named)    {#ifdef TARGET_V4_CALLS      if (!TARGET_V4_CALLS)#endif	return NULL_RTX;    }  if (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)    return NULL_RTX;  if (USE_FP_FOR_ARG_P (*cum, mode, type))    {      if ((cum->nargs_prototype > 0)#ifdef TARGET_V4_CALLS	  || TARGET_V4_CALLS	/* V.4 never passes FP values in GP registers */#endif	  || !type)	return gen_rtx (REG, mode, cum->fregno);      return gen_rtx (EXPR_LIST, VOIDmode,		      ((cum->words < GP_ARG_NUM_REG)		       ? gen_rtx (REG, mode, GP_ARG_MIN_REG + cum->words)		       : NULL_RTX),		      gen_rtx (REG, mode, cum->fregno));    }#ifdef TARGET_V4_CALLS  /* Long longs won't be split between register and stack */  else if (TARGET_V4_CALLS &&	   cum->words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG)    {      return NULL_RTX;    }#endif  else if (cum->words < GP_ARG_NUM_REG)    return gen_rtx (REG, mode, GP_ARG_MIN_REG + cum->words);  return NULL_RTX;}/* 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;     enum machine_mode mode;     tree type;     int named;{  if (! named)    return 0;#ifdef TARGET_V4_CALLS

⌨️ 快捷键说明

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