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

📄 m32r.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* 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]);    }  /* 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 (void){  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.  */intm32r_legitimate_pic_operand_p (rtx x){  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)    return 0;                                                                                  if (GET_CODE (x) == CONST      && GET_CODE (XEXP (x, 0)) == PLUS      && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF          || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)      && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))    return 0;                                                                                  return 1;}rtxm32r_legitimize_pic_address (rtx orig, rtx reg){#ifdef DEBUG_PIC  printf("m32r_legitimize_pic_address()\n");#endif  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)    {      rtx pic_ref, address;      rtx insn;      int subregs = 0;      if (reg == 0)        {          if (reload_in_progress || reload_completed)            abort ();          else            reg = gen_reg_rtx (Pmode);          subregs = 1;        }      if (subregs)        address = gen_reg_rtx (Pmode);      else        address = reg;      current_function_uses_pic_offset_table = 1;      if (GET_CODE (orig) == LABEL_REF          || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig)))        {          emit_insn (gen_gotoff_load_addr (reg, orig));          emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));          return reg;        }      emit_insn (gen_pic_load_addr (address, orig));      emit_insn (gen_addsi3 (address, address, pic_offset_table_rtx));      pic_ref = gen_const_mem (Pmode, address);      insn = emit_move_insn (reg, pic_ref);#if 0      /* Put a REG_EQUAL note on this insn, so that it can be optimized         by loop.  */      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,                  REG_NOTES (insn));#endif      return reg;    }  else if (GET_CODE (orig) == CONST)    {      rtx base, offset;      if (GET_CODE (XEXP (orig, 0)) == PLUS          && XEXP (XEXP (orig, 0), 1) == pic_offset_table_rtx)        return orig;      if (reg == 0)        {          if (reload_in_progress || reload_completed)            abort ();          else            reg = gen_reg_rtx (Pmode);        }      if (GET_CODE (XEXP (orig, 0)) == PLUS)        {          base = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);          if (base == reg)            offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), NULL_RTX);          else            offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), reg);        }      else        return orig;      if (GET_CODE (offset) == CONST_INT)        {          if (INT16_P (INTVAL (offset)))            return plus_constant (base, INTVAL (offset));          else if (! reload_in_progress && ! reload_completed)            offset = force_reg (Pmode, offset);          else            /* If we reach here, then something is seriously wrong.  */            abort ();        }      return gen_rtx_PLUS (Pmode, base, offset);    }  return orig;}/* Emit special PIC prologues and epilogues.  */voidm32r_finalize_pic (void){  current_function_uses_pic_offset_table |= current_function_profile;}/* 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 (rtx tramp ATTRIBUTE_UNUSED,			    rtx fnaddr ATTRIBUTE_UNUSED,			    rtx cxt ATTRIBUTE_UNUSED){}static voidm32r_file_start (void){  default_file_start ();  if (flag_verbose_asm)    fprintf (asm_out_file,	     "%s M32R/D special options: -G " HOST_WIDE_INT_PRINT_UNSIGNED "\n",	     ASM_COMMENT_START, g_switch_value);  if (TARGET_LITTLE_ENDIAN)    fprintf (asm_out_file, "\t.little\n");}/* 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 * 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, HOST_WIDE_INT_PRINT_HEX,		     (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_operand_lossage ("invalid operand to %%U code");      return;    case 'N' :      /* Print a constant value negated.  */      if (GET_CODE (x) == CONST_INT)	output_addr_const (file, GEN_INT (- INTVAL (x)));      else	output_operand_lossage ("invalid operand to %%N code");      return;    case 'X' :      /* Print a const_int in hex.  Used in comments.  */      if (GET_CODE (x) == CONST_INT)	fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));      return;    case '#' :      fputs (IMMEDIATE_PREFIX, file);      return;    case 0 :      /* Do nothing special.  */      break;    default :      /* Unknown flag.  */      output_operand_lossage ("invalid operand output code");    }  switch (GET_CODE (x))    {    case REG :      fputs (reg_names[REGNO (x)], file);      break;    case MEM :      addr = XEXP (x, 0);      if (GET_CODE (addr) == PRE_INC)	{	  if (GET_CODE (XEXP (addr, 0)) != REG)	    fatal_insn ("pre-increment address is not a register", x);	  fprintf (file, "@+%s", reg_names[REGNO (XEXP (addr, 0))]);	}      else if (GET_CODE (addr) == PRE_DEC)	{	  if (GET_CODE (XEXP (addr, 0)) != REG)	    fatal_insn ("pre-decrement address is not a register", x);	  fprintf (file, "@-%s", reg_names[REGNO (XEXP (addr, 0))]);	}      else if (GET_CODE (addr) == POST_INC)	{	  if (GET_CODE (XEXP (addr, 0)) != REG)	    fatal_insn ("post-increment address is not a register", x);	  fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);	}      else	{	  fputs ("@(", file);	  output_address (XEXP (x, 0));	  fputc (')', file);	}      break;    case CONST_DOUBLE :      /* We handle

⌨️ 快捷键说明

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