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

📄 sparc.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Return true if OP is suitable as second operand for add/sub in DImode */intarith_double_add_operand (op, mode)     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 (op, mode)     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 (op, mode)     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 a integer which fits the   range constraining immediate operands in most three-address insns,   which have a 13 bit immediate field.  */intsmall_int (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return (GET_CODE (op) == CONST_INT && SMALL_INT (op));}intsmall_int_or_double (op, mode)     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 (op, mode)     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) < 0x100000000)));#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 (op, mode)     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 (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);}/* Return 1 if OP is const0_rtx, used for TARGET_LIVE_G0 insns.  */intzero_operand (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return op == const0_rtx;}/* Return 1 if OP is a valid operand for the source of a move insn.  */intinput_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* If both modes are non-void they must be the same.  */  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))    return 0;  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */  if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == CONSTANT_P_RTX)    return 1;  /* 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))		&& (! TARGET_ARCH64		    || (INTVAL (op) >= 0)		    || mode == SImode))	       || 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)))#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;  /* 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)    {      rtx inside = XEXP (op, 0);      if (GET_CODE (inside) == LO_SUM)	{	  /* We can't allow these because all of the splits	     (eventually as they trickle down into DFmode	     splits) require offsettable memory references.  */	  if (! TARGET_V9	      && GET_MODE (op) == TFmode)	    return 0;	  return (register_operand (XEXP (inside, 0), Pmode)		  && CONSTANT_P (XEXP (inside, 1)));	}      return memory_address_p (mode, inside);    }  return 0;}/* We know it can't be done in one insn when we get here,   the movsi expander guarentees this.  */voidsparc_emit_set_const32 (op0, op1)     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)	  || 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,				  gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,							INTVAL (op1) & 0xfffffc00, 0)));	}      else	{	  emit_insn (gen_rtx_SET (VOIDmode,				  temp,				  GEN_INT (INTVAL (op1) & 0xfffffc00)));	}      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)));    }}/* Sparc-v9 code-model support. */voidsparc_emit_set_symbolic_const64 (op0, op1, temp1)     rtx op0;     rtx op1;     rtx temp1;{  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), %temp	 or	%temp, %lo(symbol), %reg  */      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  */      emit_insn (gen_seth44 (op0, op1));      emit_insn (gen_setm44 (op0, op0, op1));      emit_insn (gen_rtx_SET (VOIDmode, temp1,			      gen_rtx_ASHIFT (DImode, op0, GEN_INT (12))));      emit_insn (gen_setl44 (op0, temp1, 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	 or	%temp2, %lo(symbol), %temp4	 sllx	%temp3, 32, %temp5	 or	%temp4, %temp5, %reg  */      /* Getting this right wrt. reloading is really tricky.	 We _MUST_ have a seperate temporary at this point,	 if we don't barf immediately instead of generating	 incorrect code.  */      if (temp1 == op0)	abort ();      emit_insn (gen_sethh (op0, op1));      emit_insn (gen_setlm (temp1, op1));      emit_insn (gen_sethm (op0, op0, op1));      emit_insn (gen_rtx_SET (VOIDmode, op0,			      gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));      emit_insn (gen_rtx_SET (VOIDmode, op0,			      gen_rtx_PLUS (DImode, op0, temp1)));      emit_insn (gen_setlo (op0, op0, op1));      break;    case CM_EMBMEDANY:      /* Old old old backwards compatibility kruft here.	 Essentially it is MEDLOW with a fixed 64-bit	 virtual base added to all data segment addresses.	 Text-segment stuff is computed like MEDANY, we can't	 reuse the code above because the relocation knobs	 look different.	 Data segment:	sethi	%hi(symbol), %temp1			or	%temp1, %lo(symbol), %temp2			add	%temp2, EMBMEDANY_BASE_REG, %reg	 Text segment:	sethi	%uhi(symbol), %temp1			sethi	%hi(symbol), %temp2			or	%temp1, %ulo(symbol), %temp3			or	%temp2, %lo(symbol), %temp4			sllx	%temp3, 32, %temp5			or	%temp4, %temp5, %reg  */      if (data_segment_operand (op1, GET_MODE (op1)))	{	  emit_insn (gen_embmedany_sethi (temp1, op1));	  emit_insn (gen_embmedany_brsum (op0, temp1));	  emit_insn (gen_embmedany_losum (op0, op0, op1));	}      else	{	  /* Getting this right wrt. reloading is really tricky.	     We _MUST_ have a seperate temporary at this point,	     so we barf immediately instead of generating	     incorrect code.  */	  if (temp1 == op0)	    abort ();	  emit_insn (gen_embmedany_textuhi (op0, op1));	  emit_insn (gen_embmedany_texthi  (temp1, op1));	  emit_insn (gen_embmedany_textulo (op0, op0, op1));	  emit_insn (gen_rtx_SET (VOIDmode, op0,				  gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));	  emit_insn (gen_rtx_SET (VOIDmode, op0,				  gen_rtx_PLUS (DImode, op0, temp1)));	  emit_insn (gen_embmedany_textlo  (op0, op0, op1));	}      break;    default:      abort();    }}/* These avoid problems when cross compiling.  If we do not   go through all this hair then the optimizer will see   invalid REG_EQUAL notes or in some cases none at all.  */static void sparc_emit_set_safe_HIGH64 PROTO ((rtx, HOST_WIDE_INT));static rtx gen_safe_SET64 PROTO ((rtx, HOST_WIDE_INT));static rtx gen_safe_OR64 PROTO ((rtx, HOST_WIDE_INT));static rtx gen_safe_XOR64 PROTO ((rtx, HOST_WIDE_INT));#if HOST_BITS_PER_WIDE_INT == 64#define GEN_HIGHINT64(__x)		GEN_INT ((__x) & 0xfffffc00)#define GEN_INT64(__x)			GEN_INT (__x)#else#define GEN_HIGHINT64(__x) \	gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx, \			      (__x) & 0xfffffc00, 0)#define GEN_INT64(__x) \	gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx, \			      (__x) & 0xffffffff, \			      ((__x) & 0x80000000 \			       ? 0xffffffff : 0))#endif/* The optimizer is not to assume anything about exactly   which bits are set for a HIGH, they are unspecified.   Unfortunately this leads to many missed optimizations   during CSE.  We mask out the non-HIGH bits, and matches   a plain movdi, to alleviate this problem.  */static voidsparc_emit_set_safe_HIGH64 (dest, val)     rtx dest;     HOST_WIDE_INT val;{  emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));}static rtxgen_safe_SET64 (dest, val)     rtx dest;     HOST_WIDE_INT val;{  return gen_rtx_SET (VOIDmode, dest, GEN_INT64 (val));}static rtxgen_safe_OR64 (src, val)     rtx src;     HOST_WIDE_INT val;{  return gen_rtx_IOR (DImode, src, GEN_INT64 (val));}static rtxgen_safe_XOR64 (src, val)     rtx src;     HOST_WIDE_INT val;{  return gen_rtx_XOR (DImode, src, GEN_INT64 (val));}/* Worker routines for 64-bit constant formation on arch64.   One of the key things to be doing in these emissions is   to create as many temp REGs as possible.  This makes it   possible for half-built constants to be used later when   such values are similar to something required later on.   Without doing this, the optimizer cannot see such   opportunities.  */static void sparc_emit_set_const64_quick1	PROTO((rtx, rtx, unsigned HOST_WIDE_INT, int));

⌨️ 快捷键说明

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