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

📄 arc.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 (decl)     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 (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, base_reg, offset, gmask, op)     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 (x, size, aligned_p)     rtx x;     unsigned int size;     int aligned_p;{  if (size == UNITS_PER_WORD && aligned_p      && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (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, size)     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,%d\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, size)     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;      const char *sp_str = reg_names[STACK_POINTER_REGNUM];      const char *fp_str = reg_names[FRAME_POINTER_REGNUM];      /* ??? There are lots of optimizations that can be done here.	 EG: Use fp to restore regs if it's closer.	 Maybe in time we'll do them all.  For now, always restore regs from	 sp, but don't restore sp if we don't have to.  */      if (!can_trust_sp_p)	{	  if (!frame_pointer_needed)	    abort ();	  fprintf (file,"\tsub %s,%s,%d\t\t%s sp not trusted here\n",		   sp_str, fp_str, frame_size, ASM_COMMENT_START);	}      /* Restore any saved registers.  */      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.  */			current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),			"ld");      if (MUST_SAVE_RETURN_ADDR)	fprintf (file, "\tld %s,[%s,%d]\n",		 reg_names[RETURN_ADDR_REGNUM],		 frame_pointer_needed ? fp_str : sp_str,		 UNITS_PER_WORD + (frame_pointer_needed ? 0 : frame_size));      /* Keep track of how much of the stack pointer we've restored.	 It makes the following a lot more readable.  */      restored = 0;      fp_restored_p = 0;      /* We try to emit the epilogue delay slot insn right after the load	 of the return address register so that it can execute with the	 stack intact.  Secondly, loads are delayed.  */      /* ??? If stack intactness is important, always emit now.  */      if (MUST_SAVE_RETURN_ADDR && epilogue_delay != NULL_RTX)	{	  final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);	  epilogue_delay = NULL_RTX;	}      if (frame_pointer_needed)	{	  /* Try to restore the frame pointer in the delay slot.  We can't,	     however, if any of these is true.  */	  if (epilogue_delay != NULL_RTX	      || !SMALL_INT (frame_size)	      || pretend_size	      || ARC_INTERRUPT_P (fn_type))	    {	      /* Note that we restore fp and sp here!  */	      fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);	      restored += frame_size;	      fp_restored_p = 1;	    }	}      else if (!SMALL_INT (size /* frame_size + pretend_size */)	       || ARC_INTERRUPT_P (fn_type))	{	  fprintf (file, "\tadd %s,%s,%d\n", sp_str, sp_str, frame_size);	  restored += frame_size;	}      /* These must be done before the return insn because the delay slot	 does the final stack restore.  */      if (ARC_INTERRUPT_P (fn_type))	{

⌨️ 快捷键说明

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