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

📄 m32r.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* Size in words to "pretend" allocate.  */      int size = M32R_MAX_PARM_REGS - first_reg_offset;      rtx regblock;      regblock = gen_rtx_MEM (BLKmode,			      plus_constant (arg_pointer_rtx,					     FIRST_PARM_OFFSET (0)));      set_mem_alias_set (regblock, get_varargs_alias_set ());      move_block_from_reg (first_reg_offset, regblock, size);      *pretend_size = (size * UNITS_PER_WORD);    }}/* Return true if INSN is real instruction bearing insn.  */static intm32r_is_insn (rtx insn){  return (INSN_P (insn)	  && GET_CODE (PATTERN (insn)) != USE	  && GET_CODE (PATTERN (insn)) != CLOBBER	  && GET_CODE (PATTERN (insn)) != ADDR_VEC);}/* Increase the priority of long instructions so that the   short instructions are scheduled ahead of the long ones.  */static intm32r_adjust_priority (rtx insn, int priority){  if (m32r_is_insn (insn)      && get_attr_insn_size (insn) != INSN_SIZE_SHORT)    priority <<= 3;  return priority;}/* Indicate how many instructions can be issued at the same time.   This is sort of a lie.  The m32r can issue only 1 long insn at   once, but it can issue 2 short insns.  The default therefore is   set at 2, but this can be overridden by the command line option   -missue-rate=1.  */static intm32r_issue_rate (void){  return ((TARGET_LOW_ISSUE_RATE) ? 1 : 2);}/* Cost functions.  */static boolm32r_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total){  switch (code)    {      /* Small integers are as cheap as registers.  4 byte values can be         fetched as immediate constants - let's give that the cost of an         extra insn.  */    case CONST_INT:      if (INT16_P (INTVAL (x)))	{	  *total = 0;	  return true;	}      /* FALLTHRU */    case CONST:    case LABEL_REF:    case SYMBOL_REF:      *total = COSTS_N_INSNS (1);      return true;    case CONST_DOUBLE:      {	rtx high, low;	split_double (x, &high, &low);	*total = COSTS_N_INSNS (!INT16_P (INTVAL (high))			        + !INT16_P (INTVAL (low)));	return true;      }    case MULT:      *total = COSTS_N_INSNS (3);      return true;    case DIV:    case UDIV:    case MOD:    case UMOD:      *total = COSTS_N_INSNS (10);      return true;    default:      return false;    }}/* Type of function DECL.   The result is cached.  To reset the cache at the end of a function,   call with DECL = NULL_TREE.  */enum m32r_function_typem32r_compute_function_type (tree decl){  /* Cached value.  */  static enum m32r_function_type fn_type = M32R_FUNCTION_UNKNOWN;  /* Last function we were called for.  */  static tree last_fn = NULL_TREE;  /* Resetting the cached value?  */  if (decl == NULL_TREE)    {      fn_type = M32R_FUNCTION_UNKNOWN;      last_fn = NULL_TREE;      return fn_type;    }  if (decl == last_fn && fn_type != M32R_FUNCTION_UNKNOWN)    return fn_type;  /* Compute function type.  */  fn_type = (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE	     ? M32R_FUNCTION_INTERRUPT	     : M32R_FUNCTION_NORMAL);  last_fn = decl;  return fn_type;}/* Function prologue/epilogue handlers.  *//* M32R 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+0->+-----------------------+       +-----------------------+                                        |  reg parm save area,  |                                        |  only created for     |                                            |  variable argument    |                                            |  functions            |    					+-----------------------+                                        |   previous frame ptr  |                                        +-----------------------+                                            |                       |                                            |  register save area   |                                            |                       |    					+-----------------------+                                        |    return address     |                                            +-----------------------+                                            |                       |                                            |  local variables      |                                            |                       |                                            +-----------------------+                                            |                       |                                            |  alloca allocations   |                                            |                       |                                            +-----------------------+                                            |                       |       low                                  |  arguments on stack   |       memory                               |                       |                                      SP+0->+-----------------------+    Notes:1) The "reg parm save area" does not exist for non variable argument fns.2) The "reg parm save area" can be eliminated completely if we saved regs   containing anonymous args separately but that complicates things too   much (so it's not done).3) The return address is saved after the register save area so as to have as   many insns as possible between the restoration of `lr' and the `jmp lr'.  *//* Structure to be filled in by m32r_compute_frame_size with register   save masks, and offsets for the current function.  */struct m32r_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 gmask;		/* Mask of saved gp registers.  */  unsigned int save_fp;		/* Nonzero if fp must be saved.  */  unsigned int save_lr;		/* Nonzero if lr (return addr) must be saved.  */  int          initialized;	/* Nonzero if frame size already calculated.  */};/* Current frame information calculated by m32r_compute_frame_size.  */static struct m32r_frame_info current_frame_info;/* Zero structure to initialize current_frame_info.  */static struct m32r_frame_info zero_frame_info;#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_really_used_regs[regno] || interrupt_p)))#define MUST_SAVE_FRAME_POINTER (regs_ever_live[FRAME_POINTER_REGNUM])#define MUST_SAVE_RETURN_ADDR   (regs_ever_live[RETURN_ADDR_REGNUM] || current_function_profile)#define SHORT_INSN_SIZE 2	/* Size of small instructions.  */#define LONG_INSN_SIZE 4	/* Size of long instructions.  *//* Return the bytes needed to compute the frame pointer from the current   stack pointer.   SIZE is the size needed for local variables.  */unsigned intm32r_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, frame_size;  unsigned int gmask;  enum m32r_function_type fn_type;  int interrupt_p;  int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table);  var_size	= M32R_STACK_ALIGN (size);  args_size	= M32R_STACK_ALIGN (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_size	= 0;  gmask		= 0;  /* See if this is an interrupt handler.  Call used registers must be saved     for them too.  */  fn_type = m32r_compute_function_type (current_function_decl);  interrupt_p = M32R_INTERRUPT_P (fn_type);  /* Calculate space needed for registers.  */  for (regno = 0; regno < M32R_MAX_INT_REGS; regno++)    {      if (MUST_SAVE_REGISTER (regno, interrupt_p)          || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))	{	  reg_size += UNITS_PER_WORD;	  gmask |= 1 << regno;	}    }  current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;  current_frame_info.save_lr = MUST_SAVE_RETURN_ADDR || pic_reg_used;  reg_size += ((current_frame_info.save_fp + current_frame_info.save_lr)	       * UNITS_PER_WORD);  total_size += reg_size;  /* ??? Not sure this is necessary, and I don't think the epilogue     handler will do the right thing if this changes total_size.  */  total_size = M32R_STACK_ALIGN (total_size);  frame_size = total_size - (pretend_size + reg_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.gmask	  = gmask;  current_frame_info.initialized  = reload_completed;  /* Ok, we're done.  */  return total_size;}/* The table we use to reference PIC data.  */static rtx global_offset_table;                                                                                static voidm32r_reload_lr (rtx sp, int size){  rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);  if (size == 0)    emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, sp)));  else if (size <= 32768)    emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode,					   gen_rtx_PLUS (Pmode, sp,							 GEN_INT (size)))));  else    {         rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);      emit_insn (gen_movsi (tmp, GEN_INT (size)));      emit_insn (gen_addsi3 (tmp, tmp, sp));      emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, tmp)));    }  emit_insn (gen_rtx_USE (VOIDmode, lr));}voidm32r_load_pic_register (void){  global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");  emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,                         GEN_INT (TARGET_MODEL_SMALL)));                                                                                  /* Need to emit this whether or not we obey regdecls,     since setjmp/longjmp can cause life info to screw up.  */  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));}/* Expand the m32r prologue as a series of insns.  */voidm32r_expand_prologue (void){  int regno;  int frame_size;  unsigned int gmask;  int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table);  if (! current_frame_info.initialized)    m32r_compute_frame_size (get_frame_size ());  gmask = current_frame_info.gmask;  /* These cases shouldn't happen.  Catch them now.  */  if (current_frame_info.total_size == 0 && gmask)    abort ();  /* Allocate space for register arguments if this is a variadic function.  */  if (current_frame_info.pretend_size != 0)    {      /* Use a HOST_WIDE_INT temporary, since negating an unsigned int gives	 the wrong result on a 64-bit host.  */      HOST_WIDE_INT pretend_size = current_frame_info.pretend_size;      emit_insn (gen_addsi3 (stack_pointer_rtx,			     stack_pointer_rtx,			     GEN_INT (-pretend_size)));    }  /* Save any registers we need to and set up fp.  */  if (current_frame_info.save_fp)    emit_insn (gen_movsi_push (stack_pointer_rtx, frame_pointer_rtx));  gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);  /* Save any needed call-saved regs (and call-used if this is an     interrupt handler).  */  for (regno = 0; regno <= M32R_MAX_INT_REGS; ++regno)    {      if ((gmask & (1 << regno)) != 0)	emit_insn (gen_movsi_push (stack_pointer_rtx,				   gen_rtx_REG (Pmode, regno)));    }  if (current_frame_info.save_lr)    emit_insn (gen_movsi_push (stack_pointer_rtx,			       gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));  /* Allocate the stack frame.  */  frame_size = (current_frame_info.total_size		- (current_frame_info.pretend_size		   + current_frame_info.reg_size));  if (frame_size == 0)    ; /* Nothing to do.  */  else if (frame_size <= 32768)    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,			   GEN_INT (-frame_size)));  else    {      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);      emit_insn (gen_movsi (tmp, GEN_INT (frame_size)));      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));    }  if (frame_pointer_needed)    emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));  if (current_function_profile)    /* Push lr for mcount (form_pc, x).  */    emit_insn (gen_movsi_push (stack_pointer_rtx,                               gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));                                                                                  if (pic_reg_used)    {      m32r_load_pic_register ();      m32r_reload_lr (stack_pointer_rtx,                      (current_function_profile ? 0 : frame_size));    }  if (current_function_profile && !pic_reg_used)    emit_insn (gen_blockage ());}/* Set up the stack and frame pointer (if desired) for the function.   Note, if this is changed, you need to mirror the changes in   m32r_compute_frame_size which calculates the prolog size.  */static voidm32r_output_function_prologue (FILE * file, HOST_WIDE_INT size){  enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);  /* If this is an interrupt handler, mark it as such.  */  if (M32R_INTERRUPT_P (fn_type))    fprintf (file, "\t%s interrupt handler\n", ASM_COMMENT_START);  if (! current_frame_info.initialized)    m32r_compute_frame_size (size);  /* This is only for the human reader.  */  fprintf (file,	   "\t%s PROLOGUE, vars= %d, regs= %d, args= %d, extra= %d\n",	   ASM_COMMENT_START,	   current_frame_info.var_size,	   current_frame_info.reg_size / 4,	   current_frame_info.args_size,	   current_frame_info.extra_size);}/* Do any necessary cleanup after a function to restore stack, frame,   and regs.  */static voidm32r_output_function_epilogue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED){  int regno;  int noepilogue = FALSE;  int total_size;  enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);  /* This is only for the human reader.  */  fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);  if (!current_frame_info.initialized)    abort ();  total_size = current_frame_info.total_size;  if (total_size == 0)    {      rtx insn = get_last_insn ();

⌨️ 快捷键说明

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