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

📄 arc.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	*total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))				+ !SMALL_INT (INTVAL (low)));	return true;      }    /* Encourage synth_mult to find a synthetic multiply when reasonable.       If we need more than 12 insns to do a multiply, then go out-of-line,       since the call overhead will be < 10% of the cost of the multiply.  */    case ASHIFT:    case ASHIFTRT:    case LSHIFTRT:      if (TARGET_SHIFTER)        *total = COSTS_N_INSNS (1);      else if (GET_CODE (XEXP (x, 1)) != CONST_INT)        *total = COSTS_N_INSNS (16);      else        *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));      return false;    default:      return false;    }}/* Provide the costs of an addressing mode that contains ADDR.   If ADDR is not a valid address, its cost is irrelevant.  */static intarc_address_cost (rtx addr){  switch (GET_CODE (addr))    {    case REG :      return 1;    case LABEL_REF :    case SYMBOL_REF :    case CONST :      return 2;    case PLUS :      {	register rtx plus0 = XEXP (addr, 0);	register rtx plus1 = XEXP (addr, 1);	if (GET_CODE (plus0) != REG)	  break;	switch (GET_CODE (plus1))	  {	  case CONST_INT :	    return SMALL_INT (plus1) ? 1 : 2;	  case CONST :	  case SYMBOL_REF :	  case LABEL_REF :	    return 2;	  default:	    break;	  }	break;      }    default:      break;    }  return 4;}/* Function prologue/epilogue handlers.  *//* ARC stack frames look like:             Before call                       After call        +-----------------------+       +-----------------------+        |                       |       |                       |   high |  local variables,     |       |  local variables,     |   mem  |  reg save area, etc.  |       |  reg save area, etc.  |        |                       |       |                       |        +-----------------------+       +-----------------------+        |                       |       |                       |        |  arguments on stack.  |       |  arguments on stack.  |        |                       |       |                       | SP+16->+-----------------------+FP+48->+-----------------------+        | 4 word save area for  |       |  reg parm save area,  |        | return addr, prev %fp |       |  only created for     |      SP+0->+-----------------------+       |  variable argument    |                                            |  functions            |                                     FP+16->+-----------------------+                                            | 4 word save area for  |                                            | return addr, prev %fp |                                      FP+0->+-----------------------+                                            |                       |                                            |  local variables      |                                            |                       |                                            +-----------------------+                                            |                       |                                            |  register save area   |                                            |                       |                                            +-----------------------+                                            |                       |                                            |  alloca allocations   |                                            |                       |                                            +-----------------------+                                            |                       |                                            |  arguments on stack   |                                            |                       |                                     SP+16->+-----------------------+   low                                  | 4 word save area for  |       memory                               | return addr, prev %fp |                                      SP+0->+-----------------------+    Notes:1) The "reg parm save area" does not exist for non variable argument fns.   The "reg parm save area" can be eliminated completely if we created our   own va-arc.h, but that has tradeoffs as well (so it's not done).  *//* Structure to be filled in by arc_compute_frame_size with register   save masks, and offsets for the current function.  */struct arc_frame_info{  unsigned int total_size;	/* # bytes that the entire frame takes up.  */  unsigned int extra_size;	/* # bytes of extra stuff.  */  unsigned int pretend_size;	/* # bytes we push and pretend caller did.  */  unsigned int args_size;	/* # bytes that outgoing arguments take up.  */  unsigned int reg_size;	/* # bytes needed to store regs.  */  unsigned int var_size;	/* # bytes that variables take up.  */  unsigned int reg_offset;	/* Offset from new sp to store regs.  */  unsigned int gmask;		/* Mask of saved gp registers.  */  int          initialized;	/* Nonzero if frame size already calculated.  */};/* Current frame information calculated by arc_compute_frame_size.  */static struct arc_frame_info current_frame_info;/* Zero structure to initialize current_frame_info.  */static struct arc_frame_info zero_frame_info;/* Type of function DECL.   The result is cached.  To reset the cache at the end of a function,   call with DECL = NULL_TREE.  */enum arc_function_typearc_compute_function_type (tree decl){  tree a;  /* Cached value.  */  static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN;  /* Last function we were called for.  */  static tree last_fn = NULL_TREE;  /* Resetting the cached value?  */  if (decl == NULL_TREE)    {      fn_type = ARC_FUNCTION_UNKNOWN;      last_fn = NULL_TREE;      return fn_type;    }  if (decl == last_fn && fn_type != ARC_FUNCTION_UNKNOWN)    return fn_type;  /* Assume we have a normal function (not an interrupt handler).  */  fn_type = ARC_FUNCTION_NORMAL;  /* Now see if this is an interrupt handler.  */  for (a = DECL_ATTRIBUTES (current_function_decl);       a;       a = TREE_CHAIN (a))    {      tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);      if (name == get_identifier ("__interrupt__")	  && list_length (args) == 1	  && TREE_CODE (TREE_VALUE (args)) == STRING_CST)	{	  tree value = TREE_VALUE (args);	  if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))	    fn_type = ARC_FUNCTION_ILINK1;	  else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))	    fn_type = ARC_FUNCTION_ILINK2;	  else	    abort ();	  break;	}    }  last_fn = decl;  return fn_type;}#define ILINK1_REGNUM 29#define ILINK2_REGNUM 30#define RETURN_ADDR_REGNUM 31#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))/* Tell prologue and epilogue if register REGNO should be saved / restored.   The return address and frame pointer are treated separately.   Don't consider them here.  */#define MUST_SAVE_REGISTER(regno, interrupt_p) \((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \ && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p)))#define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM])/* Return the bytes needed to compute the frame pointer from the current   stack pointer.   SIZE is the size needed for local variables.  */unsigned intarc_compute_frame_size (int size /* # of var. bytes allocated.  */){  int regno;  unsigned int total_size, var_size, args_size, pretend_size, extra_size;  unsigned int reg_size, reg_offset;  unsigned int gmask;  enum arc_function_type fn_type;  int interrupt_p;  var_size	= size;  args_size	= current_function_outgoing_args_size;  pretend_size	= current_function_pretend_args_size;  extra_size	= FIRST_PARM_OFFSET (0);  total_size	= extra_size + pretend_size + args_size + var_size;  reg_offset	= FIRST_PARM_OFFSET(0) + current_function_outgoing_args_size;  reg_size	= 0;  gmask		= 0;  /* See if this is an interrupt handler.  Call used registers must be saved     for them too.  */  fn_type = arc_compute_function_type (current_function_decl);  interrupt_p = ARC_INTERRUPT_P (fn_type);  /* Calculate space needed for registers.     ??? We ignore the extension registers for now.  */  for (regno = 0; regno <= 31; regno++)    {      if (MUST_SAVE_REGISTER (regno, interrupt_p))	{	  reg_size += UNITS_PER_WORD;	  gmask |= 1 << regno;	}    }  total_size += reg_size;  /* If the only space to allocate is the fp/blink save area this is an     empty frame.  However, if we'll be making a function call we need to     allocate a stack frame for our callee's fp/blink save area.  */  if (total_size == extra_size      && !MUST_SAVE_RETURN_ADDR)    total_size = extra_size = 0;  total_size = ARC_STACK_ALIGN (total_size);  /* Save computed information.  */  current_frame_info.total_size   = total_size;  current_frame_info.extra_size   = extra_size;  current_frame_info.pretend_size = pretend_size;  current_frame_info.var_size     = var_size;  current_frame_info.args_size    = args_size;  current_frame_info.reg_size	  = reg_size;  current_frame_info.reg_offset	  = reg_offset;  current_frame_info.gmask	  = gmask;  current_frame_info.initialized  = reload_completed;  /* Ok, we're done.  */  return total_size;}/* Common code to save/restore registers.  */voidarc_save_restore (FILE *file,                  const char *base_reg,                  unsigned int offset,                  unsigned int gmask,                  const char *op){  int regno;  if (gmask == 0)    return;  for (regno = 0; regno <= 31; regno++)    {      if ((gmask & (1L << regno)) != 0)	{	  fprintf (file, "\t%s %s,[%s,%d]\n",		     op, reg_names[regno], base_reg, offset);	  offset += UNITS_PER_WORD;	}    }}/* Target hook to assemble an integer object.  The ARC version needs to   emit a special directive for references to labels and function   symbols.  */static boolarc_assemble_integer (rtx x, unsigned int size, int aligned_p){  if (size == UNITS_PER_WORD && aligned_p      && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))	  || GET_CODE (x) == LABEL_REF))    {      fputs ("\t.word\t%st(", asm_out_file);      output_addr_const (asm_out_file, x);      fputs (")\n", asm_out_file);      return true;    }  return default_assemble_integer (x, size, aligned_p);}/* Set up the stack and frame pointer (if desired) for the function.  */static voidarc_output_function_prologue (FILE *file, HOST_WIDE_INT size){  const char *sp_str = reg_names[STACK_POINTER_REGNUM];  const char *fp_str = reg_names[FRAME_POINTER_REGNUM];  unsigned int gmask = current_frame_info.gmask;  enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);  /* If this is an interrupt handler, set up our stack frame.     ??? Optimize later.  */  if (ARC_INTERRUPT_P (fn_type))    {      fprintf (file, "\t%s interrupt handler\n",	       ASM_COMMENT_START);      fprintf (file, "\tsub %s,%s,16\n", sp_str, sp_str);    }  /* This is only for the human reader.  */  fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n",	   ASM_COMMENT_START, ASM_COMMENT_START,	   current_frame_info.var_size,	   current_frame_info.reg_size / 4,	   current_frame_info.args_size,	   current_frame_info.extra_size);  size = ARC_STACK_ALIGN (size);  size = (! current_frame_info.initialized	   ? arc_compute_frame_size (size)	   : current_frame_info.total_size);  /* These cases shouldn't happen.  Catch them now.  */  if (size == 0 && gmask)    abort ();  /* Allocate space for register arguments if this is a variadic function.  */  if (current_frame_info.pretend_size != 0)    fprintf (file, "\tsub %s,%s,%d\n",	     sp_str, sp_str, current_frame_info.pretend_size);  /* The home-grown ABI says link register is saved first.  */  if (MUST_SAVE_RETURN_ADDR)    fprintf (file, "\tst %s,[%s,%d]\n",	     reg_names[RETURN_ADDR_REGNUM], sp_str, UNITS_PER_WORD);  /* Set up the previous frame pointer next (if we need to).  */  if (frame_pointer_needed)    {      fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str);      fprintf (file, "\tmov %s,%s\n", fp_str, sp_str);    }  /* ??? We don't handle the case where the saved regs are more than 252     bytes away from sp.  This can be handled by decrementing sp once, saving     the regs, and then decrementing it again.  The epilogue doesn't have this     problem as the `ld' insn takes reg+limm values (though it would be more     efficient to avoid reg+limm).  */  /* Allocate the stack frame.  */  if (size - current_frame_info.pretend_size > 0)    fprintf (file, "\tsub %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",	     sp_str, sp_str, size - current_frame_info.pretend_size);  /* Save any needed call-saved regs (and call-used if this is an     interrupt handler).  */  arc_save_restore (file, sp_str, current_frame_info.reg_offset,		    /* The zeroing of these two bits is unnecessary,		       but leave this in for clarity.  */		    gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),		    "st");  fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START);}/* Do any necessary cleanup after a function to restore stack, frame,   and regs.  */static voidarc_output_function_epilogue (FILE *file, HOST_WIDE_INT size){  rtx epilogue_delay = current_function_epilogue_delay_list;  int noepilogue = FALSE;  enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);  /* This is only for the human reader.  */  fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);  size = ARC_STACK_ALIGN (size);  size = (!current_frame_info.initialized	   ? arc_compute_frame_size (size)	   : current_frame_info.total_size);  if (size == 0 && epilogue_delay == 0)    {      rtx insn = get_last_insn ();      /* If the last insn was a BARRIER, we don't have to write any code	 because a jump (aka return) was put there.  */      if (GET_CODE (insn) == NOTE)	insn = prev_nonnote_insn (insn);      if (insn && GET_CODE (insn) == BARRIER)	noepilogue = TRUE;    }  if (!noepilogue)    {      unsigned int pretend_size = current_frame_info.pretend_size;      unsigned int frame_size = size - pretend_size;      int restored, fp_restored_p;      int can_trust_sp_p = !current_function_calls_alloca;

⌨️ 快捷键说明

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