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

📄 m32r.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* 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;  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)    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, size)     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, size)     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 ();      /* 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 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;      const char * sp_str = reg_names[STACK_POINTER_REGNUM];      const 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);}/* Return nonzero if this function is known to have a null or 1 instruction   epilogue.  */intdirect_return (){  if (!reload_completed)    return FALSE;  if (! current_frame_info.initialized)    m32r_compute_frame_size (get_frame_size ());  return current_frame_info.total_size == 0;}/* 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 ATTRIBUTE_UNUSED;     rtx fnaddr ATTRIBUTE_UNUSED;     rtx cxt ATTRIBUTE_UNUSED;{}/* 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, HOST_WIDE_INT_PRINT_HEX,		   code == 'L' ? INTVAL (first) : INTVAL (second));	}      else	output_operand_lossage ("invalid operand to %%H/%%L code");      return;    case 'A' :      {	char str[30];	if (GET_CODE (x) != CONST_DOUBLE	    || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)	  fatal_insn ("bad insn for 'A'", x);	real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);	fprintf (file, "%s", str);	return;      }    case 'B' : /* Bottom half */    case 'T' : /* Top half */      /* Output the argument to a `seth' insn (sets the Top half-word).	 For constants output arguments to a seth/or3 pair to set Top and	 Bottom halves.  For symbols output arguments to a seth/add3 pair to	 set Top and Bottom halves.  The difference exists because for	 constants seth/or3 is more readable but for symbols we need to use	 the same scheme as `ld' and `st' insns (16 bit addend is signed).  */      switch (GET_CODE (x))	{	case CONST_INT :	case CONST_DOUBLE :	  {	    rtx first, second;	    split_double (x, &first, &second);	    x = WORDS_BIG_ENDIAN ? second : first;	    fprintf (file,#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT		     "0x%x",#else		     "0x%lx",#endif		     (code == 'B'		      ? INTVAL (x) & 0xffff		      : (INTVAL (x) >> 16) & 0xffff));	  }	  return;	case CONST :	case SYMBOL_REF :	  if (code == 'B'	      && small_data_operand (x, VOIDmode))	    {	      fputs ("sda(", file);	      output_addr_const (file, x);	      fputc (')', file);	      return;	    }	  /* fall through */	case LABEL_REF :	  fputs (code == 'T' ? "shigh(" : "low(", file);	  output_addr_const (file, x);	  fputc (')', file);	  return;	default :	  output_operand_lossage ("invalid operand to %%T/%%B code");	  return;	}      break;    case 'U' :      /* ??? wip */      /* Output a load/store with update indicator if appropriate.  */      if (GET_CODE (x) == MEM)	{	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    fputs (".a", file);	}      else	output

⌨️ 快捷键说明

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