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

📄 mips.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	    ret = (INTVAL (op1) < 0) ? "li\t%0,%1\t\t\t# %X1" : "li\t%0,%X1\t\t# %1";	}      else if (code1 == CONST_DOUBLE && mode == SFmode)	{	  if (CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) == 0)	    {	      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 = "lw\t%0,%2";		    }		  else		    {		      dslots_load_total++;		      operands[3] = offset;		      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_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);		/* reverse operands */	      add_op1 = XEXP (op1, 0);	    }	  operands[2] = add_op0;	  operands[3] = add_op1;	  ret = "add%:\t%0,%2,%3";	}    }  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)		{		default: break;		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;		}	    }	  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)	    {	    default: break;	    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;	    }	}      else if (code1 == CONST_DOUBLE && CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) == 0)	{	  switch (mode)	    {	    default: break;	    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;	    }	}      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;}/* Return the appropriate instructions to move 2 words */char *mips_move_2words (operands, insn)     rtx operands[];     rtx insn;{  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);    }  while (code1 == SUBREG)    {      subreg_word1 += SUBREG_WORD (op1);      op1 = SUBREG_REG (op1);      code1 = GET_CODE (op1);    }        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;		  ret = (TARGET_FLOAT64)				? "dmtc1\t%1,%0"				: "mtc1\t%L1,%0\n\tmtc1\t%M1,%D0";		}	    }	  else if (FP_REG_P (regno1))	    {	      delay = DELAY_LOAD;	      ret = (TARGET_FLOAT64)			? "dmfc1\t%0,%1"			: "mfc1\t%L0,%1\n\tmfc1\t%M0,%D1";	    }	  else if (MD_REG_P (regno0) && GP_REG_P (regno1))	    {	      delay = DELAY_HILO;	      ret = "mthi\t%M1\n\tmtlo\t%L1";	    }	  else if (GP_REG_P (regno0) && MD_REG_P (regno1))	    {	      delay = DELAY_HILO;	      ret = "mfhi\t%M0\n\tmflo\t%L0";	    }	  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)	{	  if (CONST_DOUBLE_HIGH (op1) != 0 || CONST_DOUBLE_LOW (op1) != 0)	    {	      if (GET_MODE (op1) == DFmode)		{		  delay = DELAY_LOAD;		  ret = "li.d\t%0,%1";		}	      else		{		  operands[2] = GEN_INT (CONST_DOUBLE_LOW (op1));		  operands[3] = GEN_INT (CONST_DOUBLE_HIGH (op1));		  ret = "li\t%M0,%3\n\tli\t%L0,%2";		}	    }	  else	    {	      if (GP_REG_P (regno0))		ret = "move\t%0,%.\n\tmove\t%D0,%.";	      else if (FP_REG_P (regno0))		{		  delay = DELAY_LOAD;		  ret = (TARGET_FLOAT64)				? "dmtc1\t%.,%0"				: "mtc1\t%.,%0\n\tmtc1\t%.,%D0";		}	    }	}      else if (code1 == CONST_INT && INTVAL (op1) == 0)	{	  if (GP_REG_P (regno0))	    ret = "move\t%0,%.\n\tmove\t%D0,%.";	  	  else if (FP_REG_P (regno0))	    {	      delay = DELAY_LOAD;	      ret = (TARGET_FLOAT64)				? "dmtc1\t%.,%0"				: "mtc1\t%.,%0\n\tmtc1\t%.,%D0";	    }	}	      else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0))	{	  operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1);	  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 (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 (code0 == MEM)    {      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_word1;	  if (FP_REG_P (regno1))	    ret = "s.d\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_DOUBLE	       && CONST_DOUBLE_HIGH (op1) == 0	       && CONST_DOUBLE_LOW (op1) == 0	       && offsettable_address_p (1, DFmode, XEXP (op0, 0)))	{	  if (TARGET_FLOAT64)	    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:    case HIGH:      return 1;    case LABEL_REF:      return 2;    case CONST:      {	rtx offset = const0_rtx;	addr = eliminate_constant_term (addr, &offset);	if (GET_CODE (addr) == LABEL_REF)	  return 2;	if (GET_CODE (addr) != SYMBOL_REF)	  return 4;	if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)	  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:	    {	      int value = INTVAL (plus1);	      return (value < -32768 || value > 32767) ? 2 : 1;	    }	  case CONST:	  case SYMBOL_REF:	  case LABEL_REF:	  case HIGH:	  case LO_SUM:	    return mips_address_cost (plus1) + 1;	  }      }    }  return 4;}/* 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.  */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  */

⌨️ 快捷键说明

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