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

📄 iq2000.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
	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;}/* Abort after printing out a specific insn.  */static voidabort_with_insn (rtx insn, const char * reason){  error (reason);  debug_rtx (insn);  fancy_abort (__FILE__, __LINE__, __FUNCTION__);}/* Return the appropriate instructions to move one operand to another.  */const char *iq2000_move_1word (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_offset0 = 0;  int subreg_offset1 = 0;  enum delay_type delay = DELAY_NONE;  while (code0 == SUBREG)    {      subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),					     GET_MODE (SUBREG_REG (op0)),					     SUBREG_BYTE (op0),					     GET_MODE (op0));      op0 = SUBREG_REG (op0);      code0 = GET_CODE (op0);    }  while (code1 == SUBREG)    {      subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),					     GET_MODE (SUBREG_REG (op1)),					     SUBREG_BYTE (op1),					     GET_MODE (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_offset0;      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_offset1;	  /* Do not do anything for assigning a register to itself */	  if (regno0 == regno1)	    ret = "";	  else if (GP_REG_P (regno0))	    {	      if (GP_REG_P (regno1))		ret = "or\t%0,%%0,%1";	    }	}      else if (code1 == MEM)	{	  delay = DELAY_LOAD;	  if (TARGET_STATS)	    iq2000_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 = "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 (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)	    {	      if (GP_REG_P (regno0))		ret = "or\t%0,%%0,%z1";	    }	 else if (GP_REG_P (regno0))	    {	      if (SMALL_INT_UNSIGNED (op1))		ret = "ori\t%0,%%0,%x1\t\t\t# %1";	      else if (SMALL_INT (op1))		ret = "addiu\t%0,%%0,%1\t\t\t# %1";	      else		ret = "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";	    }	}      else if (code1 == CONST_DOUBLE && mode == SFmode)	{	  if (op1 == CONST0_RTX (SFmode))	    {	      if (GP_REG_P (regno0))		ret = "or\t%0,%%0,%.";	    }	  else	    {	      delay = DELAY_LOAD;	      ret = "li.s\t%0,%1";	    }	}      else if (code1 == LABEL_REF)	{	  if (TARGET_STATS)	    iq2000_count_memory_refs (op1, 1);	  ret = "la\t%0,%a1";	}      else if (code1 == SYMBOL_REF || code1 == CONST)	{	  if (TARGET_STATS)	    iq2000_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)	iq2000_count_memory_refs (op0, 1);      if (code1 == REG)	{	  int regno1 = REGNO (op1) + subreg_offset1;	  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 (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)    {      abort_with_insn (insn, "Bad move");      return 0;    }  if (delay != DELAY_NONE)    return iq2000_fill_delay_slot (ret, delay, operands, insn);  return ret;}/* Provide the costs of an addressing mode that contains ADDR.  */static intiq2000_address_cost (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:      {	rtx plus0 = XEXP (addr, 0);	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 iq2000_address_cost (plus1) + 1;	  default:	    break;	  }      }    default:      break;    }  return 4;}/* Make normal rtx_code into something we can index from an array.  */static enum internal_testmap_test_to_internal_test (enum rtx_code test_code){  enum internal_test test = ITEST_MAX;  switch (test_code)    {    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;    default:			break;    }  return test;}/* Generate the code to do a TEST_CODE comparison on two integer values CMP0   and CMP1.  P_INVERT is NULL or ptr if branch needs to reverse its test.   The return value RESULT is:   (reg:SI xx)		The pseudo register the comparison is in   0		       	No register, generate a simple branch.  */rtxgen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,		    int *p_invert){  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;  int eqne_p;  int invert;  rtx reg;  rtx reg2;  test = map_test_to_internal_test (test_code);  gcc_assert (test != ITEST_MAX);  p_info = &info[(int) test];  eqne_p = (p_info->test_code == XOR);  mode = GET_MODE (cmp0);  if (mode == VOIDmode)    mode = GET_MODE (cmp1);  /* Eliminate simple branches.  */  branch_p = (result == 0);  if (branch_p)    {      if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)	{	  /* Comparisons against zero are simple branches.  */	  if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)	    return 0;	  /* Test for beq/bne.  */	  if (eqne_p)	    return 0;	}      /* Allocate a pseudo to calculate the value in.  */      result = gen_reg_rtx (mode);    }  /* Make sure we can handle any constants given to us.  */  if (GET_CODE (cmp0) == CONST_INT)    cmp0 = force_reg (mode, cmp0);  if (GET_CODE (cmp1) == CONST_INT)    {      HOST_WIDE_INT value = INTVAL (cmp1);      if (value < p_info->const_low	  || value > p_info->const_high)	cmp1 = force_reg (mode, cmp1);    }  /* See if we need to invert the result.  */  invert = (GET_CODE (cmp1) == CONST_INT	    ? p_info->invert_const : p_info->invert_reg);  if (p_invert != (int *)0)    {      *p_invert = invert;      invert = 0;    }  /* Comparison to constants, may involve adding 1 to change a LT into LE.     Comparison between two registers, may involve switching operands.  */  if (GET_CODE (cmp1) == CONST_INT)    {      if (p_info->const_add != 0)	{	  HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;	  /* If modification of cmp1 caused overflow,	     we would get the wrong answer if we follow the usual path;	     thus, x > 0xffffffffU would turn into x > 0U.  */	  if ((p_info->unsignedp	       ? (unsigned HOST_WIDE_INT) new >	       (unsigned HOST_WIDE_INT) INTVAL (cmp1)	       : new > INTVAL (cmp1))	      != (p_info->const_add > 0))	    {	      /* This test is always true, but if INVERT is true then		 the result of the test needs to be inverted so 0 should		 be returned instead.  */	      emit_move_insn (result, invert ? const0_rtx : const_true_rtx);	      return result;	    }	  else	    cmp1 = GEN_INT (new);

⌨️ 快捷键说明

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