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

📄 mips.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
     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)) > (unsigned) 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 (addr);    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 (cfun->machine->insns_len).  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)	  && cfun->machine->insns_len > 0)	{	  long size;	  size = cfun->machine->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;{  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)) == (unsigned) 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)) == (unsigned) 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)) == (unsigned) 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.  */  if (CONSTANT_ADDRESS_P (XEXP (op, 0)))    return 1;  op = adjust_address_nv (op, GET_MODE_CLASS (mode) == MODE_INT			  ? SImode : SFmode, 4);  return memory_address_p (GET_MODE (op), XEXP (op, 0));}/* 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 code is a relational operation suitable for a   conditional trap instructuion (only EQ, NE, LT, LTU, GE, GEU).   We need this in the insn that expands `trap_if' in order to prevent   combine from erroneously altering the condition.  */inttrap_cmp_op (op, mode)     rtx op;     enum machine_mode mode;{  if (mode != GET_MODE (op))    return 0;  switch (GET_CODE (op))    {    case EQ:    case NE:    case LT:    case LTU:    case GE:    case GEU:      return 1;    default:      return 0;    }}/* 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   move_operands.  Note that 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.  We need to accept   sign-extended memory in order to reload registers from stack slots,   and so that we generate efficient code for extendsidi2.  */intmovdi_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (TARGET_64BIT      && mode == DImode      && GET_CODE (op) == SIGN_EXTEND      && GET_MODE (op) == DImode      && move_operand (XEXP (op, 0), SImode))    return 1;  return (general_operand (op, mode)	  && ! (TARGET_MIPS16		&& GET_CODE (op) == SYMBOL_REF		&& ! mips16_constant (op, mode, 1, 0)));}/* Like register_operand, but when in 64 bit mode also accept a sign   extend of a 32 bit register, since the value is known to be already   sign extended.  */intse_register_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      && register_operand (XEXP (op, 0), SImode))    return 1;  return register_operand (op, mode);}/* Like reg_or_0_operand, but when in 64 bit mode also accept a sign   extend of a 32 bit register, since the value is known to be already   sign extended.  */intse_reg_or_0_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      && register_operand (XEXP (op, 0), SImode))    return 1;  return reg_or_0_operand (op, mode);}/* Like uns_arith_operand, but when in 64 bit mode also accept a sign   extend of a 32 bit register, since the value is known to be already   sign extended.  */intse_uns_arith_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      && register_operand (XEXP (op, 0), SImode))    return 1;  return uns_arith_operand (op, mode);}/* Like arith_operand, but when in 64 bit mode also accept a sign   extend of a 32 bit register, since the value is known to be already   sign extended.  */intse_arith_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      && register_operand (XEXP (op, 0), SImode))    return 1;  return arith_operand (op, mode);}/* Like nonmemory_operand, but when in 64 bit mode also accept a sign   extend of a 32 bit register, since the value is known to be already   sign extended.  */intse_nonmemory_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      && register_operand (XEXP (op, 0), SImode))    return 1;  return nonmemory_operand (op, mode);}/* Accept any operand that can appear in a mips16 constant table   instruction.  We can't use any of the standard operand functions   because for these instructions we accept values that are not   accepted by LEGITIMATE_CONSTANT, such as arbitrary SYMBOL_REFs.  */

⌨️ 快捷键说明

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