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

📄 mips.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
	  if (code0 == REG)	    {	      additional++;	      addr = plus1;	      looping = 1;	      continue;	    }	  if (code0 == CONST_INT)	    {	      addr = plus1;	      looping = 1;	      continue;	    }	  if (code1 == REG)	    {	      additional++;	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code1 == CONST_INT)	    {	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)	    {	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)	    {	      addr = plus1;	      looping = 1;	      continue;	    }	  break;	case LABEL_REF:	  n_words = 2;		/* always 2 words */	  break;	case CONST:	  addr = XEXP (addr, 0);	  looping = 1;	  continue;	case SYMBOL_REF:	  n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;	  break;	default:	  break;	}    }  while (looping);  if (n_words == 0)    return;  n_words += additional;  if (n_words > 3)    n_words = 3;  num_refs[n_words-1] += num;}/* Return RTL for the offset from the current function to the argument.   ??? Which argument is this?  */rtxembedded_pic_offset (x)     rtx x;{  if (embedded_pic_fnaddr_rtx == NULL)    {      rtx seq;      embedded_pic_fnaddr_rtx = gen_reg_rtx (Pmode);            /* Output code at function start to initialize the pseudo-reg.  */      /* ??? We used to do this in FINALIZE_PIC, but that does not work for	 inline functions, because it is called after RTL for the function	 has been copied.  The pseudo-reg in embedded_pic_fnaddr_rtx however	 does not get copied, and ends up not matching the rest of the RTL.	 This solution works, but means that we get unnecessary code to	 initialize this value every time a function is inlined into another	 function.  */      start_sequence ();      emit_insn (gen_get_fnaddr (embedded_pic_fnaddr_rtx,				 XEXP (DECL_RTL (current_function_decl), 0)));      seq = gen_sequence ();      end_sequence ();      push_topmost_sequence ();      emit_insn_after (seq, get_insns ());      pop_topmost_sequence ();    }  return gen_rtx (CONST, Pmode,		  gen_rtx (MINUS, Pmode, x,			   XEXP (DECL_RTL (current_function_decl), 0)));}/* Return the appropriate instructions to move one operand to another.  */const char *mips_move_1word (operands, insn, unsignedp)     rtx operands[];     rtx insn;     int unsignedp;{  const char *ret = 0;  rtx op0 = operands[0];  rtx op1 = operands[1];  enum rtx_code code0 = GET_CODE (op0);  enum rtx_code code1 = GET_CODE (op1);  enum machine_mode mode = GET_MODE (op0);  int subreg_word0 = 0;  int subreg_word1 = 0;  enum delay_type delay = DELAY_NONE;  while (code0 == SUBREG)    {      subreg_word0 += SUBREG_WORD (op0);      op0 = SUBREG_REG (op0);      code0 = GET_CODE (op0);    }  while (code1 == SUBREG)    {      subreg_word1 += SUBREG_WORD (op1);      op1 = SUBREG_REG (op1);      code1 = GET_CODE (op1);    }  /* For our purposes, a condition code mode is the same as SImode.  */  if (mode == CCmode)    mode = SImode;  if (code0 == REG)    {      int regno0 = REGNO (op0) + subreg_word0;      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_word1;	  /* Just in case, don't do anything for assigning a register	     to itself, unless we are filling a delay slot.  */	  if (regno0 == regno1 && set_nomacro == 0)	    ret = "";	  else if (GP_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		ret = "move\t%0,%1";	      else if (MD_REG_P (regno1))		{		  delay = DELAY_HILO;		  if (regno1 != HILO_REGNUM)		    ret = "mf%1\t%0";		  else		    ret = "mflo\t%0";		}	      else if (ST_REG_P (regno1) && mips_isa >= 4)		ret = "li\t%0,1\n\tmovf\t%0,%.,%1";	      else		{		  delay = DELAY_LOAD;		  if (FP_REG_P (regno1))		    ret = "mfc1\t%0,%1";		  else if (regno1 == FPSW_REGNUM && mips_isa < 4)		    ret = "cfc1\t%0,$31";		}	    }	  else if (FP_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		{		  delay = DELAY_LOAD;		  ret = "mtc1\t%1,%0";		}	      if (FP_REG_P (regno1))		ret = "mov.s\t%0,%1";	    }	  else if (MD_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		{		  delay = DELAY_HILO;		  if (regno0 != HILO_REGNUM && ! TARGET_MIPS16)		    ret = "mt%0\t%1";		}	    }	  else if (regno0 == FPSW_REGNUM && mips_isa < 4)	    {	      if (GP_REG_P (regno1))		{		  delay = DELAY_LOAD;		  ret = "ctc1\t%0,$31";		}	    }	}      else if (code1 == MEM)	{	  delay = DELAY_LOAD;	  if (TARGET_STATS)	    mips_count_memory_refs (op1, 1);	  if (GP_REG_P (regno0))	    {	      /* For loads, use the mode of the memory item, instead of the		 target, so zero/sign extend can use this code as well.  */	      switch (GET_MODE (op1))		{		default:		  break;		case SFmode:		  ret = "lw\t%0,%1";		  break;		case SImode:		case CCmode:		  ret = ((unsignedp && TARGET_64BIT)			 ? "lwu\t%0,%1"			 : "lw\t%0,%1");		  break;		case HImode:		  ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";		  break;		case QImode:		  ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";		  break;		}	    }	  else if (FP_REG_P (regno0) && (mode == SImode || mode == SFmode))	    ret = "l.s\t%0,%1";	  if (ret != (char *)0 && MEM_VOLATILE_P (op1))	    {	      size_t i = strlen (ret);	      if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))		abort ();	      sprintf (volatile_buffer, "%%{%s%%}", ret);	      ret = volatile_buffer;	    }	}      else if (code1 == CONST_INT	       || (code1 == CONST_DOUBLE		   && GET_MODE (op1) == VOIDmode))	{	  if (code1 == CONST_DOUBLE)	    {	      /* This can happen when storing constants into long long                 bitfields.  Just store the least significant word of                 the value.  */	      operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1));	    }	  if (INTVAL (op1) == 0 && ! TARGET_MIPS16)	    {	      if (GP_REG_P (regno0))		ret = "move\t%0,%z1";	      else if (FP_REG_P (regno0))		{		  delay = DELAY_LOAD;		  ret = "mtc1\t%z1,%0";		}	      else if (MD_REG_P (regno0))		{		  delay = DELAY_HILO;		  ret = "mt%0\t%.";		}	    }	  else if (GP_REG_P (regno0))	    {	      /* Don't use X format, because that will give out of		 range numbers for 64 bit host and 32 bit target.  */	      if (! TARGET_MIPS16)		ret = "li\t%0,%1\t\t\t# %X1";	      else		{		  if (INTVAL (op1) >= 0 && INTVAL (op1) <= 0xffff)		    ret = "li\t%0,%1";		  else if (INTVAL (op1) < 0 && INTVAL (op1) >= -0xffff)		    ret = "li\t%0,%n1\n\tneg\t%0";		}	    }	}      else if (code1 == CONST_DOUBLE && mode == SFmode)	{	  if (op1 == CONST0_RTX (SFmode))	    {	      if (GP_REG_P (regno0))		ret = "move\t%0,%.";	      else if (FP_REG_P (regno0))		{		  delay = DELAY_LOAD;		  ret = "mtc1\t%.,%0";		}	    }	  else	    {	      delay = DELAY_LOAD;	      ret = "li.s\t%0,%1";	    }	}      else if (code1 == LABEL_REF)	{	  if (TARGET_STATS)	    mips_count_memory_refs (op1, 1);	  ret = "la\t%0,%a1";	}      else if (code1 == SYMBOL_REF || code1 == CONST)	{	  if (HALF_PIC_P () && CONSTANT_P (op1) && HALF_PIC_ADDRESS_P (op1))	    {	      rtx offset = const0_rtx;	      if (GET_CODE (op1) == CONST)		op1 = eliminate_constant_term (XEXP (op1, 0), &offset);	      if (GET_CODE (op1) == SYMBOL_REF)		{		  operands[2] = HALF_PIC_PTR (op1);		  if (TARGET_STATS)		    mips_count_memory_refs (operands[2], 1);		  if (INTVAL (offset) == 0)		    {		      delay = DELAY_LOAD;		      ret = (unsignedp && TARGET_64BIT			     ? "lwu\t%0,%2"			     : "lw\t%0,%2");		    }		  else		    {		      dslots_load_total++;		      operands[3] = offset;		      if (unsignedp && TARGET_64BIT)			ret = (SMALL_INT (offset)			       ? "lwu\t%0,%2%#\n\tadd\t%0,%0,%3"			       : "lwu\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]");		      else			ret = (SMALL_INT (offset)			       ? "lw\t%0,%2%#\n\tadd\t%0,%0,%3"			       : "lw\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]");		    }		}	    }	  else if (TARGET_MIPS16		   && code1 == CONST		   && GET_CODE (XEXP (op1, 0)) == REG		   && REGNO (XEXP (op1, 0)) == GP_REG_FIRST + 28)	    {	      /* This case arises on the mips16; see                 mips16_gp_pseudo_reg.  */	      ret = "move\t%0,%+";	    }	  else if (TARGET_MIPS16		   && code1 == SYMBOL_REF		   && SYMBOL_REF_FLAG (op1)		   && (XSTR (op1, 0)[0] != '*'		       || strncmp (XSTR (op1, 0) + 1,				   LOCAL_LABEL_PREFIX,				   sizeof LOCAL_LABEL_PREFIX - 1) != 0))	    {	      /* This can occur when reloading the address of a GP                 relative symbol on the mips16.  */	      ret = "move\t%0,%+\n\taddu\t%0,%%gprel(%a1)";	    }	  else	    {	      if (TARGET_STATS)		mips_count_memory_refs (op1, 1);	      ret = "la\t%0,%a1";	    }	}      else if (code1 == PLUS)	{	  rtx add_op0 = XEXP (op1, 0);	  rtx add_op1 = XEXP (op1, 1);	  if (GET_CODE (XEXP (op1, 1)) == REG	      && GET_CODE (XEXP (op1, 0)) == CONST_INT)	    add_op0 = XEXP (op1, 1), add_op1 = XEXP (op1, 0);	  operands[2] = add_op0;	  operands[3] = add_op1;	  ret = "add%:\t%0,%2,%3";	}      else if (code1 == HIGH)	{	  operands[1] = XEXP (op1, 0);	  ret = "lui\t%0,%%hi(%1)";	}    }  else if (code0 == MEM)    {      if (TARGET_STATS)	mips_count_memory_refs (op0, 1);      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_word1;	  if (GP_REG_P (regno1))	    {	      switch (mode)		{		case SFmode: ret = "sw\t%1,%0"; break;		case SImode: ret = "sw\t%1,%0"; break;		case HImode: ret = "sh\t%1,%0"; break;		case QImode: ret = "sb\t%1,%0"; break;		default: break;		}	    }	  else if (FP_REG_P (regno1) && (mode == SImode || mode == SFmode))	    ret = "s.s\t%1,%0";	}      else if (code1 == CONST_INT && INTVAL (op1) == 0)	{	  switch (mode)	    {	    case SFmode: ret = "sw\t%z1,%0"; break;	    case SImode: ret = "sw\t%z1,%0"; break;	    case HImode: ret = "sh\t%z1,%0"; break;	    case QImode: ret = "sb\t%z1,%0"; break;	    default: break;	    }	}      else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode))	{	  switch (mode)	    {	    case SFmode: ret = "sw\t%.,%0"; break;	    case SImode: ret = "sw\t%.,%0"; break;	    case HImode: ret = "sh\t%.,%0"; break;	    case QImode: ret = "sb\t%.,%0"; break;	    default: break;	    }	}      if (ret != 0 && MEM_VOLATILE_P (op0))	{	  size_t i = strlen (ret);	  if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))	    abort ();	  	  sprintf (volatile_buffer, "%%{%s%%}", ret);	  ret = volatile_buffer;	}    }  if (ret == 0)    {      abort_with_insn (insn, "Bad move");      return 0;    }  if (delay != DELAY_NONE)    return mips_fill_delay_slot (ret, delay, operands, insn);  return ret;}/* Return the appropriate instructions to move 2 words */const char *mips_move_2words (operands, insn)     rtx operands[];     rtx insn;

⌨️ 快捷键说明

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