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

📄 sparc.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	  && ((high_bits >> (32 - i - 1)) & 1))	highest_bit_set = (64 - i - 1);    }  while (++i < 32	 && ((highest_bit_set == -1)	     || (lowest_bit_set == -1)));  if (i == 32)    {      i = 0;      do	{	  if ((lowest_bit_set == -1)	      && ((high_bits >> i) & 1))	    lowest_bit_set = i + 32;	  if ((highest_bit_set == -1)	      && ((low_bits >> (32 - i - 1)) & 1))	    highest_bit_set = 32 - i - 1;	}      while (++i < 32	     && ((highest_bit_set == -1)		 || (lowest_bit_set == -1)));    }  /* If there are no bits set this should have gone out     as one instruction!  */  if (lowest_bit_set == -1      || highest_bit_set == -1)    abort ();  all_bits_between_are_set = 1;  for (i = lowest_bit_set; i <= highest_bit_set; i++)    {      if (i < 32)	{	  if ((low_bits & (1 << i)) != 0)	    continue;	}      else	{	  if ((high_bits & (1 << (i - 32))) != 0)	    continue;	}      all_bits_between_are_set = 0;      break;    }  *hbsp = highest_bit_set;  *lbsp = lowest_bit_set;  *abbasp = all_bits_between_are_set;}static int const64_is_2insns	PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));static intconst64_is_2insns (high_bits, low_bits)     unsigned HOST_WIDE_INT high_bits, low_bits;{  int highest_bit_set, lowest_bit_set, all_bits_between_are_set;  if (high_bits == 0      || high_bits == 0xffffffff)    return 1;  analyze_64bit_constant (high_bits, low_bits,			  &highest_bit_set, &lowest_bit_set,			  &all_bits_between_are_set);  if ((highest_bit_set == 63       || lowest_bit_set == 0)      && all_bits_between_are_set != 0)    return 1;  if ((highest_bit_set - lowest_bit_set) < 21)    return 1;  return 0;}static unsigned HOST_WIDE_INT create_simple_focus_bits	PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,	       int, int));static unsigned HOST_WIDE_INTcreate_simple_focus_bits (high_bits, low_bits, lowest_bit_set, shift)     unsigned HOST_WIDE_INT high_bits, low_bits;     int lowest_bit_set, shift;{  HOST_WIDE_INT hi, lo;  if (lowest_bit_set < 32)    {      lo = (low_bits >> lowest_bit_set) << shift;      hi = ((high_bits << (32 - lowest_bit_set)) << shift);    }  else    {      lo = 0;      hi = ((high_bits >> (lowest_bit_set - 32)) << shift);    }  if (hi & lo)    abort ();  return (hi | lo);}/* Here we are sure to be arch64 and this is an integer constant   being loaded into a register.  Emit the most efficient   insn sequence possible.  Detection of all the 1-insn cases   has been done already.  */voidsparc_emit_set_const64 (op0, op1)     rtx op0;     rtx op1;{  unsigned HOST_WIDE_INT high_bits, low_bits;  int lowest_bit_set, highest_bit_set;  int all_bits_between_are_set;  rtx temp;  /* Sanity check that we know what we are working with.  */  if (! TARGET_ARCH64)    abort ();  if (GET_CODE (op0) != SUBREG)    {      if (GET_CODE (op0) != REG	  || (REGNO (op0) >= SPARC_FIRST_FP_REG	      && REGNO (op0) <= SPARC_LAST_V9_FP_REG))	abort ();    }  if (reload_in_progress || reload_completed)    temp = op0;  else    temp = gen_reg_rtx (DImode);  if (GET_CODE (op1) != CONST_DOUBLE      && GET_CODE (op1) != CONST_INT)    {      sparc_emit_set_symbolic_const64 (op0, op1, temp);      return;    }  if (GET_CODE (op1) == CONST_DOUBLE)    {#if HOST_BITS_PER_WIDE_INT == 64      high_bits = (CONST_DOUBLE_LOW (op1) >> 32) & 0xffffffff;      low_bits  = CONST_DOUBLE_LOW (op1) & 0xffffffff;#else      high_bits = CONST_DOUBLE_HIGH (op1);      low_bits = CONST_DOUBLE_LOW (op1);#endif    }  else    {#if HOST_BITS_PER_WIDE_INT == 64      high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);      low_bits = (INTVAL (op1) & 0xffffffff);#else      high_bits = ((INTVAL (op1) < 0) ?		   0xffffffff :		   0x00000000);      low_bits = INTVAL (op1);#endif    }  /* low_bits	bits 0  --> 31     high_bits	bits 32 --> 63  */  analyze_64bit_constant (high_bits, low_bits,			  &highest_bit_set, &lowest_bit_set,			  &all_bits_between_are_set);  /* First try for a 2-insn sequence.  */  /* These situations are preferred because the optimizer can   * do more things with them:   * 1) mov	-1, %reg   *    sllx	%reg, shift, %reg   * 2) mov	-1, %reg   *    srlx	%reg, shift, %reg   * 3) mov	some_small_const, %reg   *    sllx	%reg, shift, %reg   */  if (((highest_bit_set == 63	|| lowest_bit_set == 0)       && all_bits_between_are_set != 0)      || ((highest_bit_set - lowest_bit_set) < 12))    {      HOST_WIDE_INT the_const = -1;      int shift = lowest_bit_set;      if ((highest_bit_set != 63	   && lowest_bit_set != 0)	  || all_bits_between_are_set == 0)	{	  the_const =	    create_simple_focus_bits (high_bits, low_bits,				      lowest_bit_set, 0);	}      else if (lowest_bit_set == 0)	shift = -(63 - highest_bit_set);      if (! SPARC_SIMM13_P (the_const))	abort ();      emit_insn (gen_safe_SET64 (temp, the_const));      if (shift > 0)	emit_insn (gen_rtx_SET (VOIDmode,				op0,				gen_rtx_ASHIFT (DImode,						temp,						GEN_INT (shift))));      else if (shift < 0)	emit_insn (gen_rtx_SET (VOIDmode,				op0,				gen_rtx_LSHIFTRT (DImode,						  temp,						  GEN_INT (-shift))));      else	abort ();      return;    }  /* Now a range of 22 or less bits set somewhere.   * 1) sethi	%hi(focus_bits), %reg   *    sllx	%reg, shift, %reg   * 2) sethi	%hi(focus_bits), %reg   *    srlx	%reg, shift, %reg   */  if ((highest_bit_set - lowest_bit_set) < 21)    {      unsigned HOST_WIDE_INT focus_bits =	create_simple_focus_bits (high_bits, low_bits,				  lowest_bit_set, 10);      if (! SPARC_SETHI_P (focus_bits))	 abort ();      sparc_emit_set_safe_HIGH64 (temp, focus_bits);      /* If lowest_bit_set == 10 then a sethi alone could have done it.  */      if (lowest_bit_set < 10)	emit_insn (gen_rtx_SET (VOIDmode,				op0,				gen_rtx_LSHIFTRT (DImode, temp,						  GEN_INT (10 - lowest_bit_set))));      else if (lowest_bit_set > 10)	emit_insn (gen_rtx_SET (VOIDmode,				op0,				gen_rtx_ASHIFT (DImode, temp,						GEN_INT (lowest_bit_set - 10))));      else	abort ();      return;    }  /* 1) sethi	%hi(low_bits), %reg   *    or	%reg, %lo(low_bits), %reg   * 2) sethi	%hi(~low_bits), %reg   *	xor	%reg, %lo(-0x400 | (low_bits & 0x3ff)), %reg   */  if (high_bits == 0      || high_bits == 0xffffffff)    {      sparc_emit_set_const64_quick1 (op0, temp, low_bits,				     (high_bits == 0xffffffff));      return;    }  /* Now, try 3-insn sequences.  */  /* 1) sethi	%hi(high_bits), %reg   *    or	%reg, %lo(high_bits), %reg   *    sllx	%reg, 32, %reg   */  if (low_bits == 0)    {      sparc_emit_set_const64_quick2 (op0, temp, high_bits, 0, 32);      return;    }  /* We may be able to do something quick     when the constant is negated, so try that.  */  if (const64_is_2insns ((~high_bits) & 0xffffffff,			 (~low_bits) & 0xfffffc00))    {      /* NOTE: The trailing bits get XOR'd so we need the	 non-negated bits, not the negated ones.  */      unsigned HOST_WIDE_INT trailing_bits = low_bits & 0x3ff;      if ((((~high_bits) & 0xffffffff) == 0	   && ((~low_bits) & 0x80000000) == 0)	  || (((~high_bits) & 0xffffffff) == 0xffffffff	      && ((~low_bits) & 0x80000000) != 0))	{	  int fast_int = (~low_bits & 0xffffffff);	  if ((SPARC_SETHI_P (fast_int)	       && (~high_bits & 0xffffffff) == 0)	      || SPARC_SIMM13_P (fast_int))	    emit_insn (gen_safe_SET64 (temp, fast_int));	  else	    sparc_emit_set_const64 (temp, GEN_INT64 (fast_int));	}      else	{	  rtx negated_const;#if HOST_BITS_PER_WIDE_INT == 64	  negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |				   (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));#else	  negated_const = immed_double_const ((~low_bits) & 0xfffffc00,					      (~high_bits) & 0xffffffff,					      DImode);#endif	  sparc_emit_set_const64 (temp, negated_const);	}      /* If we are XOR'ing with -1, then we should emit a one's complement	 instead.  This way the combiner will notice logical operations	 such as ANDN later on and substitute.  */      if (trailing_bits == 0x3ff)	{	  emit_insn (gen_rtx_SET (VOIDmode, op0,				  gen_rtx_NOT (DImode, temp)));	}      else	{	  emit_insn (gen_rtx_SET (VOIDmode,				  op0,				  gen_safe_XOR64 (temp,						  (-0x400 | trailing_bits))));	}      return;    }  /* 1) sethi	%hi(xxx), %reg   *    or	%reg, %lo(xxx), %reg   *	sllx	%reg, yyy, %reg   *   * ??? This is just a generalized version of the low_bits==0   * thing above, FIXME...   */  if ((highest_bit_set - lowest_bit_set) < 32)    {      unsigned HOST_WIDE_INT focus_bits =	create_simple_focus_bits (high_bits, low_bits,				  lowest_bit_set, 0);      /* We can't get here in this state.  */      if (highest_bit_set < 32	  || lowest_bit_set >= 32)	abort ();      /* So what we know is that the set bits straddle the	 middle of the 64-bit word.  */      sparc_emit_set_const64_quick2 (op0, temp,				     focus_bits, 0,				     lowest_bit_set);      return;    }  /* 1) sethi	%hi(high_bits), %reg   *    or	%reg, %lo(high_bits), %reg   *    sllx	%reg, 32, %reg   *	or	%reg, low_bits, %reg   */  if (SPARC_SIMM13_P(low_bits)      && ((int)low_bits > 0))    {      sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_bits, 32);      return;    }  /* The easiest way when all else fails, is full decomposition.  */#if 0  printf ("sparc_emit_set_const64: Hard constant [%08lx%08lx] neg[%08lx%08lx]\n",	  high_bits, low_bits, ~high_bits, ~low_bits);#endif  sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);}/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,   return the mode to be used for the comparison.  For floating-point,   CCFP[E]mode is used.  CC_NOOVmode should be used when the first operand   is a PLUS, MINUS, NEG, or ASHIFT.  CCmode should be used when no special   processing is needed.  */enum machine_modeselect_cc_mode (op, x, y)     enum rtx_code op;     rtx x;     rtx y ATTRIBUTE_UNUSED;{  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)    {      switch (op)	{	case EQ:	case NE:	case UNORDERED:	case ORDERED:	case UNLT:	case UNLE:	case UNGT:	case UNGE:	case UNEQ:	case LTGT:	  return CCFPmode;	case LT:	case LE:	case GT:	case GE:	  return CCFPEmode;	default:	  abort ();	}    }  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS	   || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)    {      if (TARGET_ARCH64 && GET_MODE (x) == DImode)	return CCX_NOOVmode;      else	return CC_NOOVmode;    }  else    {      if (TARGET_ARCH64 && GET_MODE (x) == DImode)	return CCXmode;      else	return CCmode;    }}/* X and Y are two things to compare using CODE.  Emit the compare insn and   return the rtx for the cc reg in the proper mode.  */rtxgen_compare_reg (code, x, y)     enum rtx_code code;     rtx x, y;{  enum machine_mode mode = SELECT_CC_MODE (code, x, y);  rtx cc_reg;  /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the     fcc regs (cse can't tell they're really call clobbered regs and will     remove a duplicate comparison even if there is an intervening function     call - it will then try to reload the cc reg via an int reg which is why     we need the movcc patterns).  It is possible to provide the movcc     patterns by using the ldxfsr/stxfsr v9 insns.  I tried it: you need two     registers (say %g1,%g5) and it takes about 6 insns.  A better fix would be     to tell cse that CCFPE mode registers (even pseudos) are call     clobbered.  */  /* ??? This is an experiment.  Rather than making changes to cse which may     or may not be easy/clean, we do our own cse.  This is possible because     we will generate hard registers.  Cse knows they're call clobbered (it     doesn't know the same thing about pseudos). If we guess wrong, no big     deal, but if we win, great!  */  if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)#if 1 /* experiment */    {      int reg;      /* We cycle through the registers to 

⌨️ 快捷键说明

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