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

📄 mips.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
{  const char *ret = 0;  rtx op0 = operands[0];  rtx op1 = operands[1];  enum rtx_code code0 = GET_CODE (operands[0]);  enum rtx_code code1 = GET_CODE (operands[1]);  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);    }  if (code1 == SIGN_EXTEND)    {      op1 = XEXP (op1, 0);      code1 = GET_CODE (op1);    }  while (code1 == SUBREG)    {      subreg_word1 += SUBREG_WORD (op1);      op1 = SUBREG_REG (op1);      code1 = GET_CODE (op1);    }        /* Sanity check.  */  if (GET_CODE (operands[1]) == SIGN_EXTEND      && code1 != REG      && code1 != CONST_INT      /* The following three can happen as the result of a questionable	 cast.  */      && code1 != LABEL_REF      && code1 != SYMBOL_REF      && code1 != CONST)    abort ();  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 (FP_REG_P (regno0))	    {	      if (FP_REG_P (regno1))		ret = "mov.d\t%0,%1";	      else		{		  delay = DELAY_LOAD;		  if (TARGET_FLOAT64)		    {		      if (!TARGET_64BIT)			abort_with_insn (insn, "Bad move");#ifdef TARGET_FP_CALL_32		      if (FP_CALL_GP_REG_P (regno1))			ret = "dsll\t%1,32\n\tor\t%1,%D1\n\tdmtc1\t%1,%0";		      else#endif			ret = "dmtc1\t%1,%0";		    }		  else		    ret = "mtc1\t%L1,%0\n\tmtc1\t%M1,%D0";		}	    }	  else if (FP_REG_P (regno1))	    {	      delay = DELAY_LOAD;	      if (TARGET_FLOAT64)		{		  if (!TARGET_64BIT)		    abort_with_insn (insn, "Bad move");#ifdef TARGET_FP_CALL_32		  if (FP_CALL_GP_REG_P (regno0))		    ret = "dmfc1\t%0,%1\n\tmfc1\t%D0,%1\n\tdsrl\t%0,32";		  else#endif		    ret = "dmfc1\t%0,%1";		}	      else		ret = "mfc1\t%L0,%1\n\tmfc1\t%M0,%D1";	    }	  else if (MD_REG_P (regno0) && GP_REG_P (regno1) && !TARGET_MIPS16)	    {	      delay = DELAY_HILO;	      if (TARGET_64BIT)		{		  if (regno0 != HILO_REGNUM)		    ret = "mt%0\t%1";		  else if (regno1 == 0)		    ret = "mtlo\t%.\n\tmthi\t%.";		}	      else		ret = "mthi\t%M1\n\tmtlo\t%L1";	    }	  else if (GP_REG_P (regno0) && MD_REG_P (regno1))	    {	      delay = DELAY_HILO;	      if (TARGET_64BIT)		{		  if (regno1 != HILO_REGNUM)		    ret = "mf%1\t%0";		}	      else		ret = "mfhi\t%M0\n\tmflo\t%L0";	    }	  else if (TARGET_64BIT)	    ret = "move\t%0,%1";	  else if (regno0 != (regno1+1))	    ret = "move\t%0,%1\n\tmove\t%D0,%D1";	  else	    ret = "move\t%D0,%D1\n\tmove\t%0,%1";	}      else if (code1 == CONST_DOUBLE)	{	  /* Move zero from $0 unless !TARGET_64BIT and recipient	     is 64-bit fp reg, in which case generate a constant.  */	  if (op1 != CONST0_RTX (GET_MODE (op1))	      || (TARGET_FLOAT64 && !TARGET_64BIT && FP_REG_P (regno0)))	    {	      if (GET_MODE (op1) == DFmode)		{		  delay = DELAY_LOAD;#ifdef TARGET_FP_CALL_32		  if (FP_CALL_GP_REG_P (regno0))		    {		      if (TARGET_FLOAT64 && !TARGET_64BIT)			{			  split_double (op1, operands + 2, operands + 3);			  ret = "li\t%0,%2\n\tli\t%D0,%3";			}		      else			ret = "li.d\t%0,%1\n\tdsll\t%D0,%0,32\n\tdsrl\t%D0,32\n\tdsrl\t%0,32";		    }		  else#endif		    ret = "li.d\t%0,%1";		}	      else if (TARGET_64BIT)		{		  if (! TARGET_MIPS16)		    ret = "dli\t%0,%1";		}	      else		{		  split_double (op1, operands + 2, operands + 3);		  ret = "li\t%0,%2\n\tli\t%D0,%3";		}	    }	  else	    {	      if (GP_REG_P (regno0))		ret = (TARGET_64BIT#ifdef TARGET_FP_CALL_32		       && ! FP_CALL_GP_REG_P (regno0)#endif		       ? "move\t%0,%."		       : "move\t%0,%.\n\tmove\t%D0,%.");	      else if (FP_REG_P (regno0))		{		  delay = DELAY_LOAD;		  ret = (TARGET_64BIT			 ? "dmtc1\t%.,%0"			 : "mtc1\t%.,%0\n\tmtc1\t%.,%D0");		}	    }	}      else if (code1 == CONST_INT && INTVAL (op1) == 0 && ! TARGET_MIPS16)	{	  if (GP_REG_P (regno0))	    ret = (TARGET_64BIT		   ? "move\t%0,%."		   : "move\t%0,%.\n\tmove\t%D0,%.");	  else if (FP_REG_P (regno0))	    {	      delay = DELAY_LOAD;	      ret = (TARGET_64BIT		     ? "dmtc1\t%.,%0"		     : (TARGET_FLOAT64			? "li.d\t%0,%1"			: "mtc1\t%.,%0\n\tmtc1\t%.,%D0"));	    }	  else if (MD_REG_P (regno0))	    {	      delay = DELAY_HILO;	      ret =  (regno0 == HILO_REGNUM		      ? "mtlo\t%.\n\tmthi\t%."		      : "mt%0\t%.\n");	    }	}	      else if (code1 == CONST_INT && GET_MODE (op0) == DImode	       && GP_REG_P (regno0))	{	  if (TARGET_64BIT)	    {	      if (TARGET_MIPS16)		{		  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 (GET_CODE (operands[1]) == SIGN_EXTEND)		ret = "li\t%0,%1\t\t# %X1";	      else if (HOST_BITS_PER_WIDE_INT < 64)		/* We can't use 'X' for negative numbers, because then we won't		   get the right value for the upper 32 bits.  */		ret = (INTVAL (op1) < 0		       ? "dli\t%0,%1\t\t\t# %X1"		       : "dli\t%0,%X1\t\t# %1");	      else		/* We must use 'X', because otherwise LONG_MIN will print as		   a number that the assembler won't accept.  */		ret = "dli\t%0,%X1\t\t# %1";	    }	  else if (HOST_BITS_PER_WIDE_INT < 64)	    {	      operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1);	      if (TARGET_MIPS16)		{		  if (INTVAL (op1) >= 0 && INTVAL (op1) <= 0xffff)		    ret = "li\t%M0,%2\n\tli\t%L0,%1";		  else if (INTVAL (op1) < 0 && INTVAL (op1) >= -0xffff)		    {		      operands[2] = GEN_INT (1);		      ret = "li\t%M0,%2\n\tneg\t%M0\n\tli\t%L0,%n1\n\tneg\t%L0";		    }		}	      else		ret = "li\t%M0,%2\n\tli\t%L0,%1";	    }	  else	    {	      /* We use multiple shifts here, to avoid warnings about out		 of range shifts on 32 bit hosts.  */	      operands[2] = GEN_INT (INTVAL (operands[1]) >> 16 >> 16);	      operands[1]		= GEN_INT (INTVAL (operands[1]) << 16 << 16 >> 16 >> 16);	      ret = "li\t%M0,%2\n\tli\t%L0,%1";	    }	}      else if (code1 == MEM)	{	  delay = DELAY_LOAD;	  if (TARGET_STATS)	    mips_count_memory_refs (op1, 2);	  if (FP_REG_P (regno0))	    ret = "l.d\t%0,%1";	  else if (TARGET_64BIT)	    {#ifdef TARGET_FP_CALL_32	      if (FP_CALL_GP_REG_P (regno0))		ret = (double_memory_operand (op1, GET_MODE (op1))		       ? "lwu\t%0,%1\n\tlwu\t%D0,4+%1"		       : "ld\t%0,%1\n\tdsll\t%D0,%0,32\n\tdsrl\t%D0,32\n\tdsrl\t%0,32");	      else#endif		ret = "ld\t%0,%1";	    }	  else if (double_memory_operand (op1, GET_MODE (op1)))	    {	      operands[2] = adj_offsettable_operand (op1, 4);	      ret = (reg_mentioned_p (op0, op1)		     ? "lw\t%D0,%2\n\tlw\t%0,%1"		     : "lw\t%0,%1\n\tlw\t%D0,%2");	    }	  if (ret != 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 == LABEL_REF)	{	  if (TARGET_STATS)	    mips_count_memory_refs (op1, 2);	  if (GET_CODE (operands[1]) == SIGN_EXTEND)	    /* We deliberately remove the 'a' from '%1', so that we don't	       have to add SIGN_EXTEND support to print_operand_address.	       print_operand will just call print_operand_address in this	       case, so there is no problem.  */	    ret = "la\t%0,%1";	  else	    ret = "dla\t%0,%a1";	}      else if (code1 == SYMBOL_REF || code1 == CONST)	{	  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, 2);	      if (GET_CODE (operands[1]) == SIGN_EXTEND)		/* We deliberately remove the 'a' from '%1', so that we don't		   have to add SIGN_EXTEND support to print_operand_address.		   print_operand will just call print_operand_address in this		   case, so there is no problem.  */		ret = "la\t%0,%1";	      else		ret = "dla\t%0,%a1";	    }	}    }  else if (code0 == MEM)    {      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_word1;	  if (FP_REG_P (regno1))	    ret = "s.d\t%1,%0";	  else if (TARGET_64BIT)	    {#ifdef TARGET_FP_CALL_32	      if (FP_CALL_GP_REG_P (regno1))		ret = "dsll\t%1,32\n\tor\t%1,%D1\n\tsd\t%1,%0";	      else#endif		ret = "sd\t%1,%0";	    }	  else if (double_memory_operand (op0, GET_MODE (op0)))	    {	      operands[2] = adj_offsettable_operand (op0, 4);	      ret = "sw\t%1,%0\n\tsw\t%D1,%2";	    }	}      else if (((code1 == CONST_INT && INTVAL (op1) == 0)		|| (code1 == CONST_DOUBLE		    && op1 == CONST0_RTX (GET_MODE (op1))))	       && (TARGET_64BIT		   || double_memory_operand (op0, GET_MODE (op0))))	{	  if (TARGET_64BIT)	    ret = "sd\t%.,%0";	  else	    {	      operands[2] = adj_offsettable_operand (op0, 4);	      ret = "sw\t%.,%0\n\tsw\t%.,%2";	    }	}      if (TARGET_STATS)	mips_count_memory_refs (op0, 2);      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;}/* Provide the costs of an addressing mode that contains ADDR.   If ADDR is not a valid address, its cost is irrelevant.  */intmips_address_cost (addr)     rtx addr;{  switch (GET_CODE (addr))    {    case LO_SUM:      return 1;    case LABEL_REF:      return 2;    case CONST:      {	rtx offset = const0_rtx;	addr = eliminate_constant_term (XEXP (addr, 0), &offset);	if (GET_CODE (addr) == LABEL_REF)	  return 2;	if (GET_CODE (addr) != SYMBOL_REF)	  return 4;	if (! SMALL_INT (offset))	  return 2;      }      /* ... fall through ... */    case SYMBOL_REF:      return SYMBOL_REF_FLAG (addr) ? 1 : 2;    case PLUS:      {	register rtx plus0 = XEXP (addr, 0);	register rtx plus1 = XEXP (addr, 1);	if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)	  plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);	if (GET_CODE (plus0) != REG)	  break;	switch (GET_CODE (plus1))	  {	  case CONST_INT:	    return SMALL_INT (plus1) ? 1 : 2;	  case CONST:	  case SYMBOL_REF:	  case LABEL_REF:	  case HIGH:	  case LO_SUM:	    return mips_address_cost (plus1) + 1;	  default:	    break;	  }      }    default:      break;    }  return 4;}/* Return nonzero if X is an address which needs a temporary register when    reloaded while generating PIC code.  */

⌨️ 快捷键说明

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