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

📄 mips.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
  if ((value & 0x0000ffff) == 0)    return 0;  return 1;}/* Return truth value of whether OP is a register or the constant 0.   In mips16 mode, we only accept a register, since the mips16 does   not have $0.  */intreg_or_0_operand (op, mode)     rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    case CONST_INT:      if (TARGET_MIPS16)	return 0;      return INTVAL (op) == 0;    case CONST_DOUBLE:      if (TARGET_MIPS16)	return 0;      return op == CONST0_RTX (mode);    case REG:    case SUBREG:      return register_operand (op, mode);    default:      break;    }  return 0;}/* Return truth value of whether OP is a register or the constant 0,   even in mips16 mode. */inttrue_reg_or_0_operand (op, mode)     rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    case CONST_INT:      return INTVAL (op) == 0;    case CONST_DOUBLE:      return op == CONST0_RTX (mode);    case REG:    case SUBREG:      return register_operand (op, mode);    default:      break;    }  return 0;}/* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant.  */intmips_const_double_ok (op, mode)     rtx op;     enum machine_mode mode;{  REAL_VALUE_TYPE d;  if (GET_CODE (op) != CONST_DOUBLE)    return 0;  if (mode == VOIDmode)    return 1;  if (mode != SFmode && mode != DFmode)    return 0;  if (op == CONST0_RTX (mode))    return 1;  /* ??? li.s does not work right with SGI's Irix 6 assembler.  */  if (mips_abi != ABI_32 && mips_abi != ABI_O64 && mips_abi != ABI_EABI)    return 0;  REAL_VALUE_FROM_CONST_DOUBLE (d, op);  if (REAL_VALUE_ISNAN (d))    return FALSE;  if (REAL_VALUE_NEGATIVE (d))    d = REAL_VALUE_NEGATE (d);  if (mode == DFmode)    {      if (REAL_VALUES_LESS (d, dfhigh)	  && REAL_VALUES_LESS (dflow, d))	return 1;    }  else    {      if (REAL_VALUES_LESS (d, sfhigh)	  && REAL_VALUES_LESS (sflow, d))	return 1;    }  return 0;}/* Accept the floating point constant 1 in the appropriate mode.  */intconst_float_1_operand (op, mode)     rtx op;     enum machine_mode mode;{  REAL_VALUE_TYPE d;  static REAL_VALUE_TYPE onedf;  static REAL_VALUE_TYPE onesf;  static int one_initialized;  if (GET_CODE (op) != CONST_DOUBLE      || mode != GET_MODE (op)      || (mode != DFmode && mode != SFmode))    return 0;  REAL_VALUE_FROM_CONST_DOUBLE (d, op);  /* We only initialize these values if we need them, since we will     never get called unless mips_isa >= 4.  */  if (! one_initialized)    {      onedf = REAL_VALUE_ATOF ("1.0", DFmode);      onesf = REAL_VALUE_ATOF ("1.0", SFmode);      one_initialized = 1;    }  if (mode == DFmode)    return REAL_VALUES_EQUAL (d, onedf);  else    return REAL_VALUES_EQUAL (d, onesf);}/* Return true if a memory load or store of REG plus OFFSET in MODE   can be represented in a single word on the mips16.  */static intmips16_simple_memory_operand (reg, offset, mode)     rtx reg;     rtx offset;     enum machine_mode mode;{  int size, off;  if (mode == BLKmode)    {      /* We can't tell, because we don't know how the value will         eventually be accessed.  Returning 0 here does no great         harm; it just prevents some possible instruction scheduling.  */      return 0;    }  size = GET_MODE_SIZE (mode);  if (INTVAL (offset) % size != 0)    return 0;  if (REGNO (reg) == STACK_POINTER_REGNUM && GET_MODE_SIZE (mode) == 4)    off = 0x100;  else    off = 0x20;  if (INTVAL (offset) >= 0 && INTVAL (offset) < off * size)    return 1;  return 0;}/* Return truth value if a memory operand fits in a single instruction   (ie, register + small offset).  */intsimple_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  rtx addr, plus0, plus1;  /* Eliminate non-memory operations */  if (GET_CODE (op) != MEM)    return 0;  /* dword operations really put out 2 instructions, so eliminate them.  */  /* ??? This isn't strictly correct.  It is OK to accept multiword modes     here, since the length attributes are being set correctly, but only     if the address is offsettable.  LO_SUM is not offsettable.  */  if (GET_MODE_SIZE (GET_MODE (op)) > UNITS_PER_WORD)    return 0;  /* Decode the address now.  */  addr = XEXP (op, 0);  switch (GET_CODE (addr))    {    case REG:    case LO_SUM:      return 1;    case CONST_INT:      if (TARGET_MIPS16)	return 0;      return SMALL_INT (op);    case PLUS:      plus0 = XEXP (addr, 0);      plus1 = XEXP (addr, 1);      if (GET_CODE (plus0) == REG	  && GET_CODE (plus1) == CONST_INT && SMALL_INT (plus1)	  && (! TARGET_MIPS16	      || mips16_simple_memory_operand (plus0, plus1, mode)))	return 1;      else if (GET_CODE (plus1) == REG	       && GET_CODE (plus0) == CONST_INT && SMALL_INT (plus0)	       && (! TARGET_MIPS16		   || mips16_simple_memory_operand (plus1, plus0, mode)))	return 1;      else	return 0;#if 0      /* We used to allow small symbol refs here (ie, stuff in .sdata	 or .sbss), but this causes some bugs in G++.  Also, it won't	 interfere if the MIPS linker rewrites the store instruction	 because the function is PIC.  */    case LABEL_REF:		/* never gp relative */      break;    case CONST:      /* If -G 0, we can never have a GP relative memory operation.	 Also, save some time if not optimizing.  */      if (!TARGET_GP_OPT)	return 0;      {	rtx offset = const0_rtx;	addr = eliminate_constant_term (XEXP (addr, 0), &offset);	if (GET_CODE (op) != SYMBOL_REF)	  return 0;	/* let's be paranoid.... */	if (! SMALL_INT (offset))	  return 0;      }      /* fall through */    case SYMBOL_REF:      return SYMBOL_REF_FLAG (addr);#endif      /* This SYMBOL_REF case is for the mips16.  If the above case is         reenabled, this one should be merged in.  */    case SYMBOL_REF:      /* References to the constant pool on the mips16 use a small         offset if the function is small.  The only time we care about         getting this right is during delayed branch scheduling, so         don't need to check until then.  The machine_dependent_reorg         function will set the total length of the instructions used         in the function in current_frame_info.  If that is small         enough, we know for sure that this is a small offset.  It         would be better if we could take into account the location of         the instruction within the function, but we can't, because we         don't know where we are.  */      if (TARGET_MIPS16	  && CONSTANT_POOL_ADDRESS_P (addr)	  && current_frame_info.insns_len > 0)	{	  long size;	  size = current_frame_info.insns_len + get_pool_size ();	  if (GET_MODE_SIZE (mode) == 4)	    return size < 4 * 0x100;	  else if (GET_MODE_SIZE (mode) == 8)	    return size < 8 * 0x20;	  else	    return 0;	}      return 0;    default:      break;    }  return 0;}/* Return nonzero for a memory address that can be used to load or store   a doubleword.  */intdouble_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  rtx addr;  if (GET_CODE (op) != MEM      || ! memory_operand (op, mode))    {      /* During reload, we accept a pseudo register if it has an	 appropriate memory address.  If we don't do this, we will	 wind up reloading into a register, and then reloading that	 register from memory, when we could just reload directly from	 memory.  */      if (reload_in_progress	  && GET_CODE (op) == REG	  && REGNO (op) >= FIRST_PSEUDO_REGISTER	  && reg_renumber[REGNO (op)] < 0	  && reg_equiv_mem[REGNO (op)] != 0	  && double_memory_operand (reg_equiv_mem[REGNO (op)], mode))	return 1;      /* All reloaded addresses are valid in TARGET_64BIT mode.  This is	 the same test performed for 'm' in find_reloads.  */      if (reload_in_progress	  && TARGET_64BIT	  && (GET_CODE (op) == MEM	      || (GET_CODE (op) == REG		  && REGNO (op) >= FIRST_PSEUDO_REGISTER		  && reg_renumber[REGNO (op)] < 0)))	return 1;      if (reload_in_progress	  && TARGET_MIPS16	  && GET_CODE (op) == MEM)	{	  rtx addr;	  addr = XEXP (op, 0);	  /* During reload on the mips16, we accept a large offset	     from the frame pointer or the stack pointer.  This large	     address will get reloaded anyhow.  */	  if (GET_CODE (addr) == PLUS	      && GET_CODE (XEXP (addr, 0)) == REG	      && (REGNO (XEXP (addr, 0)) == HARD_FRAME_POINTER_REGNUM		  || REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)	      && ((GET_CODE (XEXP (addr, 1)) == CONST_INT		   && ! SMALL_INT (XEXP (addr, 1)))		  || (GET_CODE (XEXP (addr, 1)) == SYMBOL_REF		      && CONSTANT_POOL_ADDRESS_P (XEXP (addr, 1)))))	    return 1;	  /* Similarly, we accept a case where the memory address is             itself on the stack, and will be reloaded. */	  if (GET_CODE (addr) == MEM)	    {	      rtx maddr;	      maddr = XEXP (addr, 0);	      if (GET_CODE (maddr) == PLUS		  && GET_CODE (XEXP (maddr, 0)) == REG		  && (REGNO (XEXP (maddr, 0)) == HARD_FRAME_POINTER_REGNUM		      || REGNO (XEXP (maddr, 0)) == STACK_POINTER_REGNUM)		  && ((GET_CODE (XEXP (maddr, 1)) == CONST_INT		       && ! SMALL_INT (XEXP (maddr, 1)))		      || (GET_CODE (XEXP (maddr, 1)) == SYMBOL_REF			  && CONSTANT_POOL_ADDRESS_P (XEXP (maddr, 1)))))		return 1;	    }	  /* We also accept the same case when we have a 16 bit signed	     offset mixed in as well.  The large address will get	     reloaded, and the 16 bit offset will be OK.  */	  if (GET_CODE (addr) == PLUS	      && GET_CODE (XEXP (addr, 0)) == MEM	      && GET_CODE (XEXP (addr, 1)) == CONST_INT	      && SMALL_INT (XEXP (addr, 1)))	    {	      addr = XEXP (XEXP (addr, 0), 0);	      if (GET_CODE (addr) == PLUS		  && GET_CODE (XEXP (addr, 0)) == REG		  && (REGNO (XEXP (addr, 0)) == HARD_FRAME_POINTER_REGNUM		      || REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)		  && ((GET_CODE (XEXP (addr, 1)) == CONST_INT		       && ! SMALL_INT (XEXP (addr, 1)))		      || (GET_CODE (XEXP (addr, 1)) == SYMBOL_REF			  && CONSTANT_POOL_ADDRESS_P (XEXP (addr, 1)))))		return 1;	    }	}      return 0;    }  if (TARGET_64BIT)    {      /* In this case we can use an instruction like sd.  */      return 1;    }  /* Make sure that 4 added to the address is a valid memory address.     This essentially just checks for overflow in an added constant.  */  addr = XEXP (op, 0);  if (CONSTANT_ADDRESS_P (addr))    return 1;  return memory_address_p ((GET_MODE_CLASS (mode) == MODE_INT			    ? SImode			    : SFmode),			   plus_constant_for_output (addr, 4));}/* Return nonzero if the code of this rtx pattern is EQ or NE.  */intequality_op (op, mode)     rtx op;     enum machine_mode mode;{  if (mode != GET_MODE (op))    return 0;  return GET_CODE (op) == EQ || GET_CODE (op) == NE;}/* Return nonzero if the code is a relational operations (EQ, LE, etc.) */intcmp_op (op, mode)     rtx op;     enum machine_mode mode;{  if (mode != GET_MODE (op))    return 0;  return GET_RTX_CLASS (GET_CODE (op)) == '<';}/* Return nonzero if the operand is either the PC or a label_ref.  */intpc_or_label_operand (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (op == pc_rtx)    return 1;  if (GET_CODE (op) == LABEL_REF)    return 1;  return 0;}/* Test for a valid operand for a call instruction.   Don't allow the arg pointer register or virtual regs   since they may change into reg + const, which the patterns   can't handle yet.  */intcall_insn_operand (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return (CONSTANT_ADDRESS_P (op)	  || (GET_CODE (op) == REG && op != arg_pointer_rtx	      && ! (REGNO (op) >= FIRST_PSEUDO_REGISTER		    && REGNO (op) <= LAST_VIRTUAL_REGISTER)));}/* Return nonzero if OPERAND is valid as a source operand for a move   instruction.  */intmove_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* Accept any general operand after reload has started; doing so     avoids losing if reload does an in-place replacement of a register     with a SYMBOL_REF or CONST.  */  return (general_operand (op, mode)	  && (! (mips_split_addresses && mips_check_split (op, mode))	      || reload_in_progress || reload_completed)	  && ! (TARGET_MIPS16		&& GET_CODE (op) == SYMBOL_REF		&& ! mips16_constant (op, mode, 1, 0)));}/* Return nonzero if OPERAND is valid as a source operand for movdi.   This accepts not only general_operand, but also sign extended   constants and registers.  We need to accept sign extended constants   in case a sign extended register which is used in an expression,   and is equivalent to a constant, is spilled.  */intmovdi_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (TARGET_64BIT      && mode == DImode      && GET_CODE (op) == SIGN_EXTEND      && GET_MODE (op) == DImode      && (GET_MODE (XEXP (op, 0)) == SImode

⌨️ 快捷键说明

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