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

📄 d30v.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
      break;    }  x0 = XEXP (op, 0);  if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG)    return FALSE;  if (GET_MODE (x0) != SImode)    return FALSE;  x1 = XEXP (op, 1);  switch (GET_CODE (x1))    {    default:      return FALSE;    case REG:    case SUBREG:    case CONST_INT:    case LABEL_REF:    case SYMBOL_REF:    case CONST:      break;    }  return TRUE;}/* Return true if operand is a SI mode unsigned relational test.  */inturelational_si_operator (op, mode)     register rtx op;     enum machine_mode mode;{  rtx x0, x1;  if (GET_MODE (op) != mode && mode != VOIDmode)    return FALSE;  switch (GET_CODE (op))    {    default:      return FALSE;    case LTU:    case LEU:    case GTU:    case GEU:      break;    }  x0 = XEXP (op, 0);  if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG)    return FALSE;  if (GET_MODE (x0) != SImode)    return FALSE;  x1 = XEXP (op, 1);  switch (GET_CODE (x1))    {    default:      return FALSE;    case REG:    case SUBREG:    case CONST_INT:    case LABEL_REF:    case SYMBOL_REF:    case CONST:      break;    }  return TRUE;}/* Return true if operand is a DI mode relational test.  */intrelational_di_operator (op, mode)     register rtx op;     enum machine_mode mode;{  rtx x0, x1;  if (GET_MODE (op) != mode && mode != VOIDmode)    return FALSE;  if (GET_RTX_CLASS (GET_CODE (op)) != '<')    return FALSE;  x0 = XEXP (op, 0);  if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG)    return FALSE;  if (GET_MODE (x0) != DImode)    return FALSE;  x1 = XEXP (op, 1);  if (GET_CODE (x1) != REG && GET_CODE (x1) != SUBREG      && GET_CODE (x1) != CONST_INT && GET_CODE (x1) != CONST_DOUBLE)    return FALSE;  return TRUE;}/* Calculate the stack information for the current function.   D30V stack frames look like:	high		|  ....				|			+-------------------------------+			| Argument word #19		|			+-------------------------------+			| Argument word #18		|			+-------------------------------+			| Argument word #17		|			+-------------------------------+			| Argument word #16		|		Prev sp	+-------------------------------+			|				|			| Save for arguments 1..16 if	|			| the func. uses stdarg/varargs	|			|				|			+-------------------------------+			|				|			| Save area for GPR registers	|			|				|			+-------------------------------+			|				|			| Save area for accumulators	|			|				|			+-------------------------------+			|				|			| Local variables		|			|				|			+-------------------------------+			|				|			| alloca space if used		|			|				|			+-------------------------------+			|				|			| Space for outgoing arguments	|			|				|	low	SP---->	+-------------------------------+*/d30v_stack_t *d30v_stack_info (){  static d30v_stack_t info, zero_info;  d30v_stack_t *info_ptr = &info;  tree fndecl		 = current_function_decl;  tree fntype		 = TREE_TYPE (fndecl);  int varargs_p		 = 0;  tree cur_arg;  tree next_arg;  int saved_gprs;  int saved_accs;  int memrefs_2words;  int memrefs_1word;  unsigned char save_gpr_p[GPR_LAST];  int i;  /* If we've already calculated the values and reload is complete, just return now */  if (d30v_stack_cache)    return d30v_stack_cache;  /* Zero all fields */  info = zero_info;  if (current_function_profile)    regs_ever_live[GPR_LINK] = 1;  /* Determine if this is a stdarg function */  if (TYPE_ARG_TYPES (fntype) != 0      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))    varargs_p = 1;  else    {      /* Find the last argument, and see if it is __builtin_va_alist.  */      for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg)	{	  next_arg = TREE_CHAIN (cur_arg);	  if (next_arg == (tree)0)	    {	      if (DECL_NAME (cur_arg)		  && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist"))		varargs_p = 1;	      break;	    }	}    }  /* Calculate which registers need to be saved & save area size */  saved_accs = 0;  memrefs_2words = 0;  memrefs_1word = 0;  for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++)    {      if (regs_ever_live[i] && !call_used_regs[i])	{	  info_ptr->save_p[i] = 2;	  saved_accs++;	  memrefs_2words++;	}    }  saved_gprs = 0;  for (i = GPR_FIRST; i <= GPR_LAST; i++)    {      if (regs_ever_live[i] && (!call_used_regs[i] || i == GPR_LINK))	{	  save_gpr_p[i] = 1;	  saved_gprs++;	}      else	save_gpr_p[i] = 0;    }  /* Determine which register pairs can be saved together with ld2w/st2w  */  for (i = GPR_FIRST; i <= GPR_LAST; i++)    {      if (((i - GPR_FIRST) & 1) == 0 && save_gpr_p[i] && save_gpr_p[i+1])	{	  memrefs_2words++;	  info_ptr->save_p[i++] = 2;	}      else if (save_gpr_p[i])	{	  memrefs_1word++;	  info_ptr->save_p[i] = 1;	}    }  /* Determine various sizes */  info_ptr->varargs_p	 = varargs_p;  info_ptr->varargs_size = ((varargs_p)			    ? (GPR_ARG_LAST + 1 - GPR_ARG_FIRST) * UNITS_PER_WORD			    : 0);  info_ptr->accum_size	 = 2 * UNITS_PER_WORD * saved_accs;  info_ptr->gpr_size	 = D30V_ALIGN (UNITS_PER_WORD * saved_gprs,				       2 * UNITS_PER_WORD);  info_ptr->vars_size    = D30V_ALIGN (get_frame_size (), 2 * UNITS_PER_WORD);  info_ptr->parm_size    = D30V_ALIGN (current_function_outgoing_args_size,				       2 * UNITS_PER_WORD);  info_ptr->total_size	 = D30V_ALIGN ((info_ptr->gpr_size					+ info_ptr->accum_size					+ info_ptr->vars_size					+ info_ptr->parm_size					+ info_ptr->varargs_size					+ current_function_pretend_args_size),				       (STACK_BOUNDARY / BITS_PER_UNIT));  info_ptr->save_offset  = (info_ptr->total_size			    - (current_function_pretend_args_size			       + info_ptr->varargs_size			       + info_ptr->gpr_size			       + info_ptr->accum_size));  /* The link register is the last GPR saved, but there might be some padding     bytes after it, so account for that.  */  info_ptr->link_offset  = (info_ptr->total_size			    - (current_function_pretend_args_size			       + info_ptr->varargs_size			       + (info_ptr->gpr_size				  - UNITS_PER_WORD * saved_gprs)			       + UNITS_PER_WORD));  info_ptr->memrefs_varargs = info_ptr->varargs_size / (2 * UNITS_PER_WORD);  info_ptr->memrefs_2words  = memrefs_2words;  info_ptr->memrefs_1word   = memrefs_1word;  if (reload_completed)    d30v_stack_cache = info_ptr;  return info_ptr;}/* Internal function to print all of the information about the stack */voiddebug_stack_info (info)     d30v_stack_t *info;{  int i;  if (!info)    info = d30v_stack_info ();  fprintf (stderr, "\nStack information for function %s:\n",	   ((current_function_decl && DECL_NAME (current_function_decl))	    ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))	    : "<unknown>"));  fprintf (stderr, "\tsave_offset     = %d\n", info->save_offset);  fprintf (stderr, "\tmemrefs_varargs = %d\n", info->memrefs_varargs);  fprintf (stderr, "\tmemrefs_2words  = %d\n", info->memrefs_2words);  fprintf (stderr, "\tmemrefs_1word   = %d\n", info->memrefs_1word);  fprintf (stderr, "\tvarargs_p       = %d\n", info->varargs_p);  fprintf (stderr, "\tvarargs_size    = %d\n", info->varargs_size);  fprintf (stderr, "\tvars_size       = %d\n", info->vars_size);  fprintf (stderr, "\tparm_size       = %d\n", info->parm_size);  fprintf (stderr, "\tgpr_size        = %d\n", info->gpr_size);  fprintf (stderr, "\taccum_size      = %d\n", info->accum_size);  fprintf (stderr, "\ttotal_size      = %d\n", info->total_size);  fprintf (stderr, "\tsaved registers =");  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      if (info->save_p[i] == 2)	{	  fprintf (stderr, " %s-%s", reg_names[i], reg_names[i+1]);	  i++;	}      else if (info->save_p[i])	fprintf (stderr, " %s", reg_names[i]);    }  putc ('\n', stderr);  fflush (stderr);}/* Return nonzero if this function is known to have a null or 1 instruction epilogue.  */intdirect_return (){  if (reload_completed)    {      d30v_stack_t *info = d30v_stack_info ();      /* If no epilogue code is needed, can use just a simple jump */      if (info->total_size == 0)	return 1;#if 0      /* If just a small amount of local stack was allocated and no registers         saved, skip forward branch */      if (info->total_size == info->vars_size	  && IN_RANGE_P (info->total_size, 1, 31))	return 1;#endif    }  return 0;}/* A C statement (sans semicolon) for initializing the variable CUM for the   state at the beginning of the argument list.  The variable has type   `CUMULATIVE_ARGS'.  The value of FNTYPE is the tree node for the data type   of the function which will receive the args, or 0 if the args are to a   compiler support library function.  The value of INDIRECT is nonzero when   processing an indirect call, for example a call through a function pointer.   The value of INDIRECT is zero for a call to an explicitly named function, a   library function call, or when `INIT_CUMULATIVE_ARGS' is used to find   arguments for the function being compiled.   When processing a call to a compiler support library function, LIBNAME   identifies which one.  It is a `symbol_ref' rtx which contains the name of   the function, as a string.  LIBNAME is 0 when an ordinary C function call is   being processed.  Thus, each time this macro is called, either LIBNAME or   FNTYPE is nonzero, but never both of them at once.  */voidd30v_init_cumulative_args (cum, fntype, libname, indirect, incoming)     CUMULATIVE_ARGS *cum;     tree fntype;     rtx libname;     int indirect;     int incoming;{  *cum = GPR_ARG_FIRST;  if (TARGET_DEBUG_ARG)    {      fprintf (stderr, "\ninit_cumulative_args:");      if (indirect)	fputs (" indirect", stderr);      if (incoming)	fputs (" incoming", stderr);      if (fntype)	{	  tree ret_type = TREE_TYPE (fntype);	  fprintf (stderr, " return=%s,",		   tree_code_name[ (int)TREE_CODE (ret_type) ]);	}      if (libname && GET_CODE (libname) == SYMBOL_REF)	fprintf (stderr, " libname=%s", XSTR (libname, 0));      putc ('\n', stderr);    }}/* 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.  */intd30v_function_arg_boundary (mode, type)     enum machine_mode mode;     tree type;{  int size = ((mode == BLKmode && type)	      ? int_size_in_bytes (type)	      : (int) GET_MODE_SIZE (mode));  return (size > UNITS_PER_WORD) ? 2*UNITS_PER_WORD : UNITS_PER_WORD;}/* A C expression that controls whether a function argument is passed in a   register, and which register.   The arguments are CUM, which summarizes all the previous arguments; MODE,   the machine mode of the argument; TYPE, the data type of the argument as a   tree node or 0 if that is not known (which happens for C support library   functions); and NAMED, which is 1 for an ordinary argument and 0 for   nameless arguments that correspond to `...' in the called function's   prototype.   The value of the expression should either be a `reg' RTX for the hard   register in which to pass the argument, or zero to pass the argument on the   stack.   For machines like the VAX and 68000, where normally all arguments are   pushed, zero suffices as a definition.   The usual way to make the ANSI library `stdarg.h' work on a machine where   some arguments are usually passed in registers, is to cause nameless   arguments to be passed on the stack instead.  This is done by making   `FUNCTION_ARG' return 0 whenever NAMED is 0.   You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of   this macro to determine if this argument is of a type that must be passed in   the stack.  If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'   returns nonzero for such an argument, the compiler will abort.  If   `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the   stack and then loaded into a register.  */rtxd30v_function_arg (cum, mode, type, named, incoming)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;     int incoming ATTRIBUTE_UNUSED;{  int size = ((mode == BLKmode && type)	      ? int_size_in_bytes (type)	      : (int) GET_MODE_SIZE (mode));  int adjust = (size > UNITS_PER_WORD && (*cum & 1) != 0);  rtx ret;  /* Return a marker for use in the call instruction.  */  if (mode == VOIDmode)    ret = const0_rtx;  else if (*cum + adjust <= GPR_ARG_LAST)    ret = gen_rtx (REG, mode, *cum + adjust);  else    ret = NULL_RTX;  if (TARGET_DEBUG_ARG)    fprintf (stderr,	     "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, adjust = %1d, arg = %s\n",	     *cum, GET_MODE_NAME (mode), named, size, adjust,	     (ret) ? ((ret == const0_rtx) ? "<0>" : reg_names[ REGNO (ret) ]) : "memory");  return ret;}/* A C expression for the number of words, at the beginning of an argument,   must be put in registers.  The value must be zero for arguments that are   passed entirely in registers or that are entirely pushed on the stack.   On some machines, certain arguments must be passed partially in registers   and partially in memory.  On these machines, typically the first N words of   arguments are passed in registers, and the rest on the stack.  If a   multi-word argument (a `double' or a structure) crosses that boundary, its   first few words must be passed in registers and the rest must be pushed.   This macro tells the compiler when this occurs, and how many of the words   should go in registers.   `FUNCTION_ARG' for these arguments should return the first register to be   used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for   the called function.  */intd30v_function_arg_partial_nregs (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named ATTRIBUTE_UNUSED;{  int bytes = ((mode == BLKmode)	       ? int_size_in_bytes (type)	       : (int) GET_MODE_SIZE (mode));  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;

⌨️ 快捷键说明

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