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

📄 sparc.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  return ((GET_CODE (op) == CONST_INT	   && SPARC_SIMM13_P (INTVAL (op)))#if HOST_BITS_PER_WIDE_INT != 64	  || (GET_CODE (op) == CONST_DOUBLE	      && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))	      && (CONST_DOUBLE_HIGH (op) ==		  ((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ?		   (HOST_WIDE_INT)-1 : 0)))#endif	  );}/* The same, but only for sethi instructions.  */intconst64_high_operand (rtx op, enum machine_mode mode){  return ((GET_CODE (op) == CONST_INT	   && (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0	   && SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))	   )	  || (GET_CODE (op) == CONST_DOUBLE	      && CONST_DOUBLE_HIGH (op) == 0	      && (CONST_DOUBLE_LOW (op) & ~(HOST_WIDE_INT)0x3ff) != 0	      && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));}/* Return true if OP is a register, or is a CONST_INT that can fit in a   signed 11 bit immediate field.  This is an acceptable SImode operand for   the movcc instructions.  */intarith11_operand (rtx op, enum machine_mode mode){  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));}/* Return true if OP is a register, or is a CONST_INT that can fit in a   signed 10 bit immediate field.  This is an acceptable SImode operand for   the movrcc instructions.  */intarith10_operand (rtx op, enum machine_mode mode){  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));}/* Return true if OP is a register, is a CONST_INT that fits in a 13 bit   immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit   immediate field.   ARCH64: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that   can fit in a 13 bit immediate field.  This is an acceptable DImode operand   for most 3 address instructions.  */intarith_double_operand (rtx op, enum machine_mode mode){  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && SMALL_INT (op))	  || (! TARGET_ARCH64	      && GET_CODE (op) == CONST_DOUBLE	      && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000	      && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000)	  || (TARGET_ARCH64	      && GET_CODE (op) == CONST_DOUBLE	      && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000	      && ((CONST_DOUBLE_HIGH (op) == -1		   && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)		  || (CONST_DOUBLE_HIGH (op) == 0		      && (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));}/* Return true if OP is a constant 4096 for DImode on ARCH64 */intarith_double_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return (TARGET_ARCH64 &&  	  ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||  	   (GET_CODE (op) == CONST_DOUBLE &&  	    CONST_DOUBLE_LOW (op) == 4096 &&  	    CONST_DOUBLE_HIGH (op) == 0)));}/* Return true if OP is suitable as second operand for add/sub in DImode */intarith_double_add_operand (rtx op, enum machine_mode mode){  return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);}/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that   can fit in an 11 bit immediate field.  This is an acceptable DImode   operand for the movcc instructions.  *//* ??? Replace with arith11_operand?  */intarith11_double_operand (rtx op, enum machine_mode mode){  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_DOUBLE	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800	      && ((CONST_DOUBLE_HIGH (op) == -1		   && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400)		  || (CONST_DOUBLE_HIGH (op) == 0		      && (CONST_DOUBLE_LOW (op) & 0x400) == 0)))	  || (GET_CODE (op) == CONST_INT	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800));}/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that   can fit in an 10 bit immediate field.  This is an acceptable DImode   operand for the movrcc instructions.  *//* ??? Replace with arith10_operand?  */intarith10_double_operand (rtx op, enum machine_mode mode){  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_DOUBLE	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400	      && ((CONST_DOUBLE_HIGH (op) == -1		   && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200)		  || (CONST_DOUBLE_HIGH (op) == 0		      && (CONST_DOUBLE_LOW (op) & 0x200) == 0)))	  || (GET_CODE (op) == CONST_INT	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));}/* Return truth value of whether OP is an integer which fits the   range constraining immediate operands in most three-address insns,   which have a 13 bit immediate field.  */intsmall_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (op) == CONST_INT && SMALL_INT (op));}intsmall_int_or_double (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))	  || (GET_CODE (op) == CONST_DOUBLE	      && CONST_DOUBLE_HIGH (op) == 0	      && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))));}/* Recognize operand values for the umul instruction.  That instruction sign   extends immediate values just like all other sparc instructions, but   interprets the extended result as an unsigned number.  */intuns_small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){#if HOST_BITS_PER_WIDE_INT > 32  /* All allowed constants will fit a CONST_INT.  */  return (GET_CODE (op) == CONST_INT	  && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)	      || (INTVAL (op) >= 0xFFFFF000                  && INTVAL (op) <= 0xFFFFFFFF)));#else  return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)	  || (GET_CODE (op) == CONST_DOUBLE	      && CONST_DOUBLE_HIGH (op) == 0	      && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));#endif}intuns_arith_operand (rtx op, enum machine_mode mode){  return register_operand (op, mode) || uns_small_int (op, mode);}/* Return truth value of statement that OP is a call-clobbered register.  */intclobbered_register (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);}/* Return 1 if OP is a valid operand for the source of a move insn.  */intinput_operand (rtx op, enum machine_mode mode){  enum mode_class mclass;  /* If both modes are non-void they must be the same.  */  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))    return 0;  /* Allow any one instruction integer constant, and all CONST_INT     variants when we are working in DImode and !arch64.  */  if (GET_MODE_CLASS (mode) == MODE_INT      && ((GET_CODE (op) == CONST_INT	   && (SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))	       || SPARC_SIMM13_P (INTVAL (op))	       || (mode == DImode		   && ! TARGET_ARCH64)))	  || (TARGET_ARCH64	      && GET_CODE (op) == CONST_DOUBLE	      && ((CONST_DOUBLE_HIGH (op) == 0		   && SPARC_SETHI_P (CONST_DOUBLE_LOW (op)))		  ||#if HOST_BITS_PER_WIDE_INT == 64		  (CONST_DOUBLE_HIGH (op) == 0		   && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))#else		  (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))		   && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0			&& CONST_DOUBLE_HIGH (op) == 0)		       || (CONST_DOUBLE_HIGH (op) == -1			   && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))#endif		  ))))    return 1;  /* If !arch64 and this is a DImode const, allow it so that     the splits can be generated.  */  if (! TARGET_ARCH64      && mode == DImode      && GET_CODE (op) == CONST_DOUBLE)    return 1;  if (register_operand (op, mode))    return 1;  mclass = GET_MODE_CLASS (mode);  if ((mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)      || (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR))    return 1;  /* If this is a SUBREG, look inside so that we handle     paradoxical ones.  */  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  /* Check for valid MEM forms.  */  if (GET_CODE (op) == MEM)    return memory_address_p (mode, XEXP (op, 0));  return 0;}/* Return 1 if OP is valid for the lhs of a compare insn.  */intcompare_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == ZERO_EXTRACT)    return (register_operand (XEXP (op, 0), mode)	    && small_int_or_double (XEXP (op, 1), mode)	    && small_int_or_double (XEXP (op, 2), mode)	    /* This matches cmp_zero_extract.  */	    && ((mode == SImode		 && ((GET_CODE (XEXP (op, 2)) == CONST_INT		      && INTVAL (XEXP (op, 2)) > 19)		     || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE			 && CONST_DOUBLE_LOW (XEXP (op, 2)) > 19)))		/* This matches cmp_zero_extract_sp64.  */		|| (mode == DImode		    && TARGET_ARCH64		    && ((GET_CODE (XEXP (op, 2)) == CONST_INT			 && INTVAL (XEXP (op, 2)) > 51)			|| (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE			    && CONST_DOUBLE_LOW (XEXP (op, 2)) > 51)))));  else    return register_operand (op, mode);}/* We know it can't be done in one insn when we get here,   the movsi expander guarantees this.  */voidsparc_emit_set_const32 (rtx op0, rtx op1){  enum machine_mode mode = GET_MODE (op0);  rtx temp;  if (GET_CODE (op1) == CONST_INT)    {      HOST_WIDE_INT value = INTVAL (op1);      if (SPARC_SETHI_P (value & GET_MODE_MASK (mode))	  || SPARC_SIMM13_P (value))	abort ();    }  /* Full 2-insn decomposition is needed.  */  if (reload_in_progress || reload_completed)    temp = op0;  else    temp = gen_reg_rtx (mode);  if (GET_CODE (op1) == CONST_INT)    {      /* Emit them as real moves instead of a HIGH/LO_SUM,	 this way CSE can see everything and reuse intermediate	 values if it wants.  */      if (TARGET_ARCH64	  && HOST_BITS_PER_WIDE_INT != 64	  && (INTVAL (op1) & 0x80000000) != 0)	emit_insn (gen_rtx_SET		   (VOIDmode, temp,		    immed_double_const (INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,					0, DImode)));      else	emit_insn (gen_rtx_SET (VOIDmode, temp,				GEN_INT (INTVAL (op1)					 & ~(HOST_WIDE_INT)0x3ff)));      emit_insn (gen_rtx_SET (VOIDmode,			      op0,			      gen_rtx_IOR (mode, temp,					   GEN_INT (INTVAL (op1) & 0x3ff))));    }  else    {      /* A symbol, emit in the traditional way.  */      emit_insn (gen_rtx_SET (VOIDmode, temp,			      gen_rtx_HIGH (mode, op1)));      emit_insn (gen_rtx_SET (VOIDmode,			      op0, gen_rtx_LO_SUM (mode, temp, op1)));    }}/* Load OP1, a symbolic 64-bit constant, into OP0, a DImode register.   If TEMP is nonzero, we are forbidden to use any other scratch   registers.  Otherwise, we are allowed to generate them as needed.   Note that TEMP may have TImode if the code model is TARGET_CM_MEDANY   or TARGET_CM_EMBMEDANY (see the reload_indi and reload_outdi patterns).  */voidsparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp){  rtx temp1, temp2, temp3, temp4, temp5;  rtx ti_temp = 0;  if (temp && GET_MODE (temp) == TImode)    {      ti_temp = temp;      temp = gen_rtx_REG (DImode, REGNO (temp));    }  /* SPARC-V9 code-model support.  */  switch (sparc_cmodel)    {    case CM_MEDLOW:      /* The range spanned by all instructions in the object is less	 than 2^31 bytes (2GB) and the distance from any instruction	 to the location of the label _GLOBAL_OFFSET_TABLE_ is less	 than 2^31 bytes (2GB).	 The executable must be in the low 4TB of the virtual address	 space.	 sethi	%hi(symbol), %temp1	 or	%temp1, %lo(symbol), %reg  */      if (temp)	temp1 = temp;  /* op0 is allowed.  */      else	temp1 = gen_reg_rtx (DImode);      emit_insn (gen_rtx_SET (VOIDmode, temp1, gen_rtx_HIGH (DImode, op1)));      emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LO_SUM (DImode, temp1, op1)));      break;    case CM_MEDMID:      /* The range spanned by all instructions in the object is less	 than 2^31 bytes (2GB) and the distance from any instruction	 to the location of the label _GLOBAL_OFFSET_TABLE_ is less	 than 2^31 bytes (2GB).	 The executable must be in the low 16TB of the virtual address	 space.	 sethi	%h44(symbol), %temp1	 or	%temp1, %m44(symbol), %temp2	 sllx	%temp2, 12, %temp3	 or	%temp3, %l44(symbol), %reg  */      if (temp)	{	  temp1 = op0;	  temp2 = op0;	  temp3 = temp;  /* op0 is allowed.  */	}      else	{	  temp1 = gen_reg_rtx (DImode);	  temp2 = gen_reg_rtx (DImode);	  temp3 = gen_reg_rtx (DImode);	}      emit_insn (gen_seth44 (temp1, op1));      emit_insn (gen_setm44 (temp2, temp1, op1));      emit_insn (gen_rtx_SET (VOIDmode, temp3,			      gen_rtx_ASHIFT (DImode, temp2, GEN_INT (12))));      emit_insn (gen_setl44 (op0, temp3, op1));      break;    case CM_MEDANY:      /* The range spanned by all instructions in the object is less	 than 2^31 bytes (2GB) and the distance from any instruction	 to the location of the label _GLOBAL_OFFSET_TABLE_ is less	 than 2^31 bytes (2GB).	 The executable can be placed anywhere in the virtual address	 space.	 sethi	%hh(symbol), %temp1	 sethi	%lm(symbol), %temp2	 or	%temp1, %hm(symbol), %temp3	 sllx	%temp3, 32, %temp4	 or	%temp4, %temp2, %temp5	 or	%temp5, %lo(symbol), %reg  */      if (temp)	{	  /* It is possible that one of the registers we got for operands[2]	     might coincide with that of operands[0] (which is why we made	     it TImode).  Pick the other one to use as our scratch.  */	  if (rtx_equal_p (temp, op0))	    {	      if (ti_temp)		temp = gen_rtx_REG (DImode, REGNO (temp) + 1);	      else		abort();	    }	  temp1 = op0;	  temp2 = temp;  /* op0 is _not_ allowed, see above.  */	  temp3 = op0;	  temp4 = op0;	  temp5 = op0;	}      else	{	  temp1 = gen_reg_rtx (DImode);

⌨️ 快捷键说明

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