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

📄 m32r.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
                                        |                       |                                            +-----------------------+                                            |                       |                                            |  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_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] || profile_flag)#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 (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;  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))	{	  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;  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;}/* When the `length' insn attribute is used, this macro specifies the   value to be assigned to the address of the first insn in a   function.  If not specified, 0 is used.  */intm32r_first_insn_address (){  if (! current_frame_info.initialized)    m32r_compute_frame_size (get_frame_size ());  return 0;}/* Expand the m32r prologue as a series of insns.  */voidm32r_expand_prologue (){  int regno;  int frame_size;  unsigned int gmask = current_frame_info.gmask;  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 (profile_flag || profile_block_flag)    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.  */voidm32r_output_function_prologue (file, size)     FILE * file;     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. */voidm32r_output_function_epilogue (file, size)     FILE * file;     int    size;{  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 ();      /* 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 = total_size - pretend_size;      unsigned int var_size = current_frame_info.var_size;      unsigned int args_size = current_frame_info.args_size;      unsigned int gmask = current_frame_info.gmask;      int can_trust_sp_p = !current_function_calls_alloca;      char * sp_str = reg_names[STACK_POINTER_REGNUM];      char * fp_str = reg_names[FRAME_POINTER_REGNUM];      /* The first thing to do is point the sp at the bottom of the register	 save area.  */      if (can_trust_sp_p)	{	  unsigned int reg_offset = var_size + args_size;	  if (reg_offset == 0)	    ; /* nothing to do */	  else if (reg_offset < 128)	    fprintf (file, "\taddi %s,%s%d\n",		     sp_str, IMMEDIATE_PREFIX, reg_offset);	  else if (reg_offset < 32768)	    fprintf (file, "\tadd3 %s,%s,%s%d\n",		     sp_str, sp_str, IMMEDIATE_PREFIX, reg_offset);	  else	    fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n",		     reg_names[PROLOGUE_TMP_REGNUM],		     IMMEDIATE_PREFIX, reg_offset,		     sp_str, reg_names[PROLOGUE_TMP_REGNUM]);	}      else if (frame_pointer_needed)	{	  unsigned int reg_offset = var_size + args_size;	  if (reg_offset == 0)	    fprintf (file, "\tmv %s,%s\n", sp_str, fp_str);	  else if (reg_offset < 32768)	    fprintf (file, "\tadd3 %s,%s,%s%d\n",		     sp_str, fp_str, IMMEDIATE_PREFIX, reg_offset);	  else	    fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n",		     reg_names[PROLOGUE_TMP_REGNUM],		     IMMEDIATE_PREFIX, reg_offset,		     sp_str, reg_names[PROLOGUE_TMP_REGNUM]);	}      else	abort ();      if (current_frame_info.save_lr)	fprintf (file, "\tpop %s\n", reg_names[RETURN_ADDR_REGNUM]);      /* Restore any saved registers, in reverse order of course.  */      gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);      for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno)	{	  if ((gmask & (1L << regno)) != 0)	    fprintf (file, "\tpop %s\n", reg_names[regno]);	}      if (current_frame_info.save_fp)	fprintf (file, "\tpop %s\n", fp_str);      /* Remove varargs area if present.  */      if (current_frame_info.pretend_size != 0)	fprintf (file, "\taddi %s,%s%d\n",		 sp_str, IMMEDIATE_PREFIX, current_frame_info.pretend_size);	      /* Emit the return instruction.  */      if (M32R_INTERRUPT_P (fn_type))	fprintf (file, "\trte\n");      else	fprintf (file, "\tjmp %s\n", reg_names[RETURN_ADDR_REGNUM]);    }#if 0 /* no longer needed */  /* Ensure the function cleanly ends on a 32 bit boundary.  */  fprintf (file, "\t.fillinsn\n");#endif  /* Reset state info for each function.  */  current_frame_info = zero_frame_info;  m32r_compute_function_type (NULL_TREE);}/* PIC *//* Emit special PIC prologues and epilogues.  */voidm32r_finalize_pic (){  /* nothing to do */}/* Nested function support.  *//* Emit RTL insns to initialize the variable parts of a trampoline.   FNADDR is an RTX for the address of the function's pure code.   CXT is an RTX for the static chain value for the function.  */voidm32r_initialize_trampoline (tramp, fnaddr, cxt)     rtx tramp, fnaddr, cxt;{}/* Set the cpu type and print out other fancy things,   at the top of the file.  */voidm32r_asm_file_start (file)     FILE * file;{  if (flag_verbose_asm)    fprintf (file, "%s M32R/D special options: -G %d\n",	     ASM_COMMENT_START, g_switch_value);}/* Print operand X (an rtx) in assembler syntax to file FILE.   CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.   For `%' followed by punctuation, CODE is the punctuation and X is null.  */voidm32r_print_operand (file, x, code)     FILE * file;     rtx    x;     int    code;{  rtx addr;  switch (code)    {      /* The 's' and 'p' codes are used by output_block_move() to	 indicate post-increment 's'tores and 'p're-increment loads.  */    case 's':      if (GET_CODE (x) == REG)	fprintf (file, "@+%s", reg_names [REGNO (x)]);      else	output_operand_lossage ("invalid operand to %s code");      return;          case 'p':      if (GET_CODE (x) == REG)	fprintf (file, "@%s+", reg_names [REGNO (x)]);      else	output_operand_lossage ("invalid operand to %p code");      return;    case 'R' :      /* Write second word of DImode or DFmode reference,	 register or memory.  */      if (GET_CODE (x) == REG)	fputs (reg_names[REGNO (x)+1], file);      else if (GET_CODE (x) == MEM)	{	  fprintf (file, "@(");	  /* Handle possible auto-increment.  Since it is pre-increment and	     we have already done it, we can just use an offset of four.  */	  /* ??? This is taken from rs6000.c I think.  I don't think it is	     currently necessary, but keep it around.  */	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));	  else	    output_address (plus_constant (XEXP (x, 0), 4));	  fputc (')', file);	}      else	output_operand_lossage ("invalid operand to %R code");      return;    case 'H' : /* High word */    case 'L' : /* Low word */      if (GET_CODE (x) == REG)	{	  /* L = least significant word, H = most significant word */	  if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))	    fputs (reg_names[REGNO (x)], file);	  else	    fputs (reg_names[REGNO (x)+1], file);	}      else if (GET_CODE (x) == CONST_INT	       || GET_CODE (x) == CONST_DOUBLE)	{	  rtx first, second;	  split_double (x, &first, &second);	  fprintf (file, "0x%08x",		   code == 'L' ? INTVAL (first) : INTVAL (second));	}      else	output_operand_lossage ("invalid operand to %H/%L code");      return;    case 'A' :      {	REAL_VALUE_TYPE d;	char str[30];	if (GET_CODE (x) != CONST_DOUBLE	    || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)

⌨️ 快捷键说明

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