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

📄 mips.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      && 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))	    {	      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)		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)	{	  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;	      if (regno0 != HILO_REGNUM)		ret = "mt%0\t%.\n";	      else		ret = "mtlo\t%.\n\tmthi\t%.";	    }	}	      else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0))	{	  if (TARGET_64BIT)	    {	      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);	      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))		{                  if (offsettable_address_p (FALSE, SImode, op1))                    ret = "lwu\t%0,%1\n\tlwu\t%D0,4+%1";                  else                    ret = "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 (offsettable_address_p (1, DFmode, XEXP (op1, 0)))	    {	      operands[2] = adj_offsettable_operand (op1, 4);	      if (reg_mentioned_p (op0, op1))		ret = "lw\t%D0,%2\n\tlw\t%0,%1";	      else		ret = "lw\t%0,%1\n\tlw\t%D0,%2";	    }	  if (ret != (char *)0 && MEM_VOLATILE_P (op1))	    {	      int i = strlen (ret);	      if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))		abort ();	      sprintf (volatile_buffer, "%%{%s%%}", ret);	      ret = volatile_buffer;	    }	}      else if (code1 == LABEL_REF	       || code1 == SYMBOL_REF	       || code1 == CONST)	{	  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 (offsettable_address_p (1, DFmode, XEXP (op0, 0)))	    {	      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		   || offsettable_address_p (1, DFmode, XEXP (op0, 0))))	{	  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 != (char *)0 && MEM_VOLATILE_P (op0))	{	  int i = strlen (ret);	  if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))	    abort ();	  	  sprintf (volatile_buffer, "%%{%s%%}", ret);	  ret = volatile_buffer;	}    }  if (ret == (char *)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))    {    default:      break;    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))	  {	  default:	    break;	  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;	  }      }    }  return 4;}/* Return true if X is an address which needs a temporary register when    reloaded while generating PIC code.  */intpic_address_needs_scratch (x)     rtx x;{  /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */  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), 1)) == CONST_INT      && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))    return 1;  return 0;}/* Make normal rtx_code into something we can index from an array */static enum internal_testmap_test_to_internal_test (test_code)     enum rtx_code test_code;{  enum internal_test test = ITEST_MAX;  switch (test_code)    {    default:			break;    case EQ:  test = ITEST_EQ;  break;    case NE:  test = ITEST_NE;  break;    case GT:  test = ITEST_GT;  break;    case GE:  test = ITEST_GE;  break;    case LT:  test = ITEST_LT;  break;    case LE:  test = ITEST_LE;  break;    case GTU: test = ITEST_GTU; break;    case GEU: test = ITEST_GEU; break;    case LTU: test = ITEST_LTU; break;    case LEU: test = ITEST_LEU; break;    }  return test;}/* Generate the code to compare two integer values.  The return value is:   (reg:SI xx)		The pseudo register the comparison is in   (rtx)0	       	No register, generate a simple branch.   ??? This is called with result nonzero by the Scond patterns in   mips.md.  These patterns are called with a target in the mode of   the Scond instruction pattern.  Since this must be a constant, we   must use SImode.  This means that if RESULT is non-zero, it will   always be an SImode register, even if TARGET_64BIT is true.  We   cope with this by calling convert_move rather than emit_move_insn.   This will sometimes lead to an unnecessary extension of the result;   for example:   long long   foo (long long i)   {     return i < 5;   }   */rtxgen_int_relational (test_code, result, cmp0, cmp1, p_invert)     enum rtx_code test_code;	/* relational test (EQ, etc) */     rtx result;		/* result to store comp. or 0 if branch */     rtx cmp0;			/* first operand to compare */     rtx cmp1;			/* second operand to compare */     int *p_invert;		/* NULL or ptr to hold whether branch needs */				/* to reverse its test */{  struct cmp_info {    enum rtx_code test_code;	/* code to use in instruction (LT vs. LTU) */    int const_low;		/* low bound of constant we can accept */    int const_high;		/* high bound of constant we can accept */    int const_add;		/* constant to add (convert LE -> LT) */    int reverse_regs;		/* reverse registers in test */    int invert_const;		/* != 0 if invert value if cmp1 is constant */    int invert_reg;		/* != 0 if invert value if cmp1 is register */    int unsignedp;		/* != 0 for unsigned comparisons.  */  };  static struct cmp_info info[ (int)ITEST_MAX ] = {    { XOR,	 0,  65535,  0,	 0,  0,	 0, 0 },	/* EQ  */    { XOR,	 0,  65535,  0,	 0,  1,	 1, 0 },	/* NE  */    { LT,   -32769,  32766,  1,	 1,  1,	 0, 0 },	/* GT  */    { LT,   -32768,  32767,  0,	 0,  1,	 1, 0 },	/* GE  */    { LT,   -32768,  32767,  0,	 0,  0,	 0, 0 },	/* LT  */    { LT,   -32769,  32766,  1,	 1,  0,	 1, 0 },	/* LE  */    { LTU,  -32769,  32766,  1,	 1,  1,	 0, 1 },	/* GTU */    { LTU,  -32768,  32767,  0,	 0,  1,	 1, 1 },	/* GEU */    { LTU,  -32768,  32767,  0,	 0,  0,	 0, 1 },	/* LTU */    { LTU,  -32769,  32766,  1,	 1,  0,	 1, 1 },	/* LEU */  };  enum internal_test test;  enum machine_mode mode;  struct cmp_info *p_info;  int branch_p;

⌨️ 快捷键说明

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