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

📄 iq2000.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	xlow0 = SUBREG_REG (xlow0);      if (GET_CODE (xlow0) == REG	  && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict)	  && iq2000_check_split (xlow1, mode))	return 1;    }  if (GET_CODE (xinsn) == PLUS)    {      rtx xplus0 = XEXP (xinsn, 0);      rtx xplus1 = XEXP (xinsn, 1);      enum rtx_code code0;      enum rtx_code code1;      while (GET_CODE (xplus0) == SUBREG)	xplus0 = SUBREG_REG (xplus0);      code0 = GET_CODE (xplus0);      while (GET_CODE (xplus1) == SUBREG)	xplus1 = SUBREG_REG (xplus1);      code1 = GET_CODE (xplus1);      if (code0 == REG	  && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict))	{	  if (code1 == CONST_INT && SMALL_INT (xplus1)	      && SMALL_INT_UNSIGNED (xplus1) /* No negative offsets */)	    return 1;	}    }  if (TARGET_DEBUG_A_MODE)    GO_PRINTF ("Not a legitimate address\n");  /* The address was not legitimate.  */  return 0;}/* Returns an operand string for the given instruction's delay slot,   after updating filled delay slot statistics.   We assume that operands[0] is the target register that is set.   In order to check the next insn, most of this functionality is moved   to FINAL_PRESCAN_INSN, and we just set the global variables that   it needs.  */const char *iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],			rtx cur_insn){  rtx set_reg;  enum machine_mode mode;  rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;  int num_nops;  if (type == DELAY_LOAD || type == DELAY_FCMP)    num_nops = 1;  else    num_nops = 0;  /* Make sure that we don't put nop's after labels.  */  next_insn = NEXT_INSN (cur_insn);  while (next_insn != 0	 && (GET_CODE (next_insn) == NOTE	     || GET_CODE (next_insn) == CODE_LABEL))    next_insn = NEXT_INSN (next_insn);  dslots_load_total += num_nops;  if (TARGET_DEBUG_C_MODE      || type == DELAY_NONE      || operands == 0      || cur_insn == 0      || next_insn == 0      || GET_CODE (next_insn) == CODE_LABEL      || (set_reg = operands[0]) == 0)    {      dslots_number_nops = 0;      iq2000_load_reg  = 0;      iq2000_load_reg2 = 0;      iq2000_load_reg3 = 0;      iq2000_load_reg4 = 0;      return ret;    }  set_reg = operands[0];  if (set_reg == 0)    return ret;  while (GET_CODE (set_reg) == SUBREG)    set_reg = SUBREG_REG (set_reg);  mode = GET_MODE (set_reg);  dslots_number_nops = num_nops;  iq2000_load_reg = set_reg;  if (GET_MODE_SIZE (mode)      > (unsigned) (UNITS_PER_WORD))    iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);  else    iq2000_load_reg2 = 0;  return ret;}/* Determine whether a memory reference takes one (based off of the GP   pointer), two (normal), or three (label + reg) instructions, and bump the   appropriate counter for -mstats.  */static voidiq2000_count_memory_refs (rtx op, int num){  int additional = 0;  int n_words = 0;  rtx addr, plus0, plus1;  enum rtx_code code0, code1;  int looping;  if (TARGET_DEBUG_B_MODE)    {      fprintf (stderr, "\n========== iq2000_count_memory_refs:\n");      debug_rtx (op);    }  /* Skip MEM if passed, otherwise handle movsi of address.  */  addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);  /* Loop, going through the address RTL.  */  do    {      looping = FALSE;      switch (GET_CODE (addr))	{	case REG:	case CONST_INT:	case LO_SUM:	  break;	case PLUS:	  plus0 = XEXP (addr, 0);	  plus1 = XEXP (addr, 1);	  code0 = GET_CODE (plus0);	  code1 = GET_CODE (plus1);	  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;}/* Abort after printing out a specific insn.  */static voidabort_with_insn (rtx insn, const char * reason){  error (reason);  debug_rtx (insn);  abort ();}/* 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:

⌨️ 快捷键说明

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