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

📄 rs6000.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
     register enum machine_mode mode;{  return (gpc_reg_operand (op, mode)	  || memory_operand (op, mode)	  || volatile_mem_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;  /* Allow any integer constant.  */  if (GET_MODE_CLASS (mode) == MODE_INT      && (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE))    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;  /* A SYMBOL_REF referring to the TOC is valid.  */  if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op))    return 1;  /* Windows NT allows SYMBOL_REFs and LABEL_REFs against the TOC     directly in the instruction stream */  if (DEFAULT_ABI == ABI_NT      && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF))    return 1;  /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region     to be valid.  */  if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)      && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)      && small_data_operand (op, Pmode))    return 1;  return 0;}/* Return 1 for an operand in small memory on V.4/eabi */intsmall_data_operand (op, mode)     rtx op;     enum machine_mode mode;{#if TARGET_ELF  rtx sym_ref, const_part;  if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)    return 0;  if (DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)    return 0;  if (GET_CODE (op) == SYMBOL_REF)    sym_ref = op;  else if (GET_CODE (op) != CONST	   || GET_CODE (XEXP (op, 0)) != PLUS	   || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF	   || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT)    return 0;  else    sym_ref = XEXP (XEXP (op, 0), 0);  if (*XSTR (sym_ref, 0) != '@')    return 0;  return 1;#else  return 0;#endif}/* 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 a PARALLEL.  */voidinit_cumulative_args (cum, fntype, libname, incoming)     CUMULATIVE_ARGS *cum;     tree fntype;     rtx libname;     int incoming;{  static CUMULATIVE_ARGS zero_cumulative;  enum rs6000_abi abi = DEFAULT_ABI;  *cum = zero_cumulative;  cum->words = 0;  cum->fregno = FP_ARG_MIN_REG;  cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));  cum->call_cookie = CALL_NORMAL;  if (incoming)    {      cum->nargs_prototype = 1000;		/* don't return a PARALLEL */      if (abi == ABI_V4 || abi == ABI_SOLARIS)	cum->varargs_offset = RS6000_VARARGS_OFFSET;    }  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;  /* Check for DLL import functions */  if (abi == ABI_NT      && fntype      && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (fntype)))    cum->call_cookie = CALL_NT_DLLIMPORT;  /* Also check for longcall's */  else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))    cum->call_cookie = CALL_LONG;  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) ]);	}      if ((abi == ABI_V4 || abi == ABI_SOLARIS) && incoming)	fprintf (stderr, " varargs = %d, ", cum->varargs_offset);      if (cum->call_cookie & CALL_NT_DLLIMPORT)	fprintf (stderr, " dllimport,");      if (cum->call_cookie & CALL_LONG)	fprintf (stderr, " longcall,");      fprintf (stderr, " proto = %d, nargs = %d\n",	       cum->prototype, cum->nargs_prototype);    }}/* If defined, a C expression which determines whether, and in which   direction, to pad out an argument with extra space.  The value   should be of type `enum direction': either `upward' to pad above   the argument, `downward' to pad below, or `none' to inhibit   padding.   For the AIX ABI structs are always stored left shifted in their   argument slot.  */enum directionfunction_arg_padding (mode, type)     enum machine_mode mode;     tree type;{  if (type != 0 && AGGREGATE_TYPE_P (type))    return upward;  /* This is the default definition.  */  return (! BYTES_BIG_ENDIAN          ? upward          : ((mode == BLKmode              ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST                 && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))              : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)             ? downward : upward));}/* If defined, a C expression that gives the alignment boundary, in bits,   of an argument with the specified mode and type.  If it is not defined,    PARM_BOUNDARY is used for all arguments.      Windows NT wants anything >= 8 bytes to be double word aligned.   V.4 wants long longs to be double word aligned.  */intfunction_arg_boundary (mode, type)     enum machine_mode mode;     tree type;{  if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && mode == DImode)    return 64;  if (DEFAULT_ABI != ABI_NT || TARGET_64BIT)    return PARM_BOUNDARY;  if (mode != BLKmode)    return (GET_MODE_SIZE (mode)) >= 8 ? 64 : 32;  return (int_size_in_bytes (type) >= 8) ? 64 : 32;}/* 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;{  int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0;  cum->words += align;  cum->nargs_prototype--;  if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)    {      /* 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    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, align = %d\n",	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);}/* 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 PARALLEL anyway.  */struct rtx_def *function_arg (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;{  int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0;  int align_words = cum->words + align;  if (TARGET_DEBUG_ARG)    fprintf (stderr,	     "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n",	     cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align);  /* 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)    {      enum rs6000_abi abi = DEFAULT_ABI;      if ((abi == ABI_V4 || abi == ABI_SOLARIS)	  && TARGET_HARD_FLOAT	  && cum->nargs_prototype < 0	  && type && (cum->prototype || TARGET_NO_PROTOTYPE))	{	  return GEN_INT (cum->call_cookie			  | ((cum->fregno == FP_ARG_MIN_REG)			     ? CALL_V4_SET_FP_ARGS			     : CALL_V4_CLEAR_FP_ARGS));	}      return GEN_INT (cum->call_cookie);    }  if (!named)    {      if (DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)	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 (DEFAULT_ABI == ABI_V4 /* V.4 never passes FP values in GP registers */	  || DEFAULT_ABI == ABI_SOLARIS	  || ! type	  || ((cum->nargs_prototype > 0)	      /* IBM AIX extended its linkage convention definition always to		 require FP args after register save area hole on the stack.  */	      && (DEFAULT_ABI != ABI_AIX		  || ! TARGET_XL_CALL		  || (align_words < GP_ARG_NUM_REG))))	return gen_rtx (REG, mode, cum->fregno);      return gen_rtx (PARALLEL, mode,		      gen_rtvec		      (2,		       gen_rtx (EXPR_LIST, VOIDmode,				((align_words >= GP_ARG_NUM_REG)				 ? NULL_RTX				 : (align_words				    + RS6000_ARG_SIZE (mode, type, named)				    > GP_ARG_NUM_REG				    /* If this is partially on the stack, then				       we only include the portion actually				       in registers here.  */				    ? gen_rtx (REG, SImode,					       GP_ARG_MIN_REG + align_words)				    : gen_rtx (REG, mode,					       GP_ARG_MIN_REG + align_words))),				const0_rtx),		       gen_rtx (EXPR_LIST, VOIDmode,				gen_rtx (REG, mode, cum->fregno),				const0_rtx)));    }  /* Long longs won't be split between register and stack;     FP arguments get passed on the stack if they didn't get a register.  */  else if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) &&	   (align_words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG	    || (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)))    {      return NULL_RTX;    }  else if (align_words < GP_ARG_NUM_REG)    return gen_rtx (REG, mode, GP_ARG_MIN_REG + align_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;  if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)    return 0;  if (USE_FP_FOR_ARG_P (*cum, mode, type))    {      if (cum->nargs_prototype >= 0)	return 0;    }

⌨️ 快捷键说明

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