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

📄 arm.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
	 them in-line, regardless of the cost.  This is only likely to	 be more costly on chips that have load delay slots and we are	 compiling without running the scheduler (so no splitting	 occurred before the final instruction emission).	 Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c      */      if (!after_arm_reorg	  && !cond	  && (arm_gen_constant (code, mode, NULL_RTX, val, target, source,				1, 0)	      > arm_constant_limit + (code != SET)))	{	  if (code == SET)	    {	      /* Currently SET is the only monadic value for CODE, all		 the rest are diadic.  */	      emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (val)));	      return 1;	    }	  else	    {	      rtx temp = subtargets ? gen_reg_rtx (mode) : target;	      emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (val)));	      /* For MINUS, the value is subtracted from, since we never		 have subtraction of a constant.  */	      if (code == MINUS)		emit_insn (gen_rtx_SET (VOIDmode, target,					gen_rtx_MINUS (mode, temp, source)));	      else		emit_insn (gen_rtx_SET (VOIDmode, target,					gen_rtx_fmt_ee (code, mode, source, temp)));	      return 2;	    }	}    }  return arm_gen_constant (code, mode, cond, val, target, source, subtargets,			   1);}static intcount_insns_for_constant (HOST_WIDE_INT remainder, int i){  HOST_WIDE_INT temp1;  int num_insns = 0;  do    {      int end;      if (i <= 0)	i += 32;      if (remainder & (3 << (i - 2)))	{	  end = i - 8;	  if (end < 0)	    end += 32;	  temp1 = remainder & ((0x0ff << end)				    | ((i < end) ? (0xff >> (32 - end)) : 0));	  remainder &= ~temp1;	  num_insns++;	  i -= 6;	}      i -= 2;    } while (remainder);  return num_insns;}/* Emit an instruction with the indicated PATTERN.  If COND is   non-NULL, conditionalize the execution of the instruction on COND   being true.  */static voidemit_constant_insn (rtx cond, rtx pattern){  if (cond)    pattern = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond), pattern);  emit_insn (pattern);}/* As above, but extra parameter GENERATE which, if clear, suppresses   RTL generation.  */static intarm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,		  HOST_WIDE_INT val, rtx target, rtx source, int subtargets,		  int generate){  int can_invert = 0;  int can_negate = 0;  int can_negate_initial = 0;  int can_shift = 0;  int i;  int num_bits_set = 0;  int set_sign_bit_copies = 0;  int clear_sign_bit_copies = 0;  int clear_zero_bit_copies = 0;  int set_zero_bit_copies = 0;  int insns = 0;  unsigned HOST_WIDE_INT temp1, temp2;  unsigned HOST_WIDE_INT remainder = val & 0xffffffff;  /* Find out which operations are safe for a given CODE.  Also do a quick     check for degenerate cases; these can occur when DImode operations     are split.  */  switch (code)    {    case SET:      can_invert = 1;      can_shift = 1;      can_negate = 1;      break;    case PLUS:      can_negate = 1;      can_negate_initial = 1;      break;    case IOR:      if (remainder == 0xffffffff)	{	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target,					     GEN_INT (ARM_SIGN_EXTEND (val))));	  return 1;	}      if (remainder == 0)	{	  if (reload_completed && rtx_equal_p (target, source))	    return 0;	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target, source));	  return 1;	}      break;    case AND:      if (remainder == 0)	{	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target, const0_rtx));	  return 1;	}      if (remainder == 0xffffffff)	{	  if (reload_completed && rtx_equal_p (target, source))	    return 0;	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target, source));	  return 1;	}      can_invert = 1;      break;    case XOR:      if (remainder == 0)	{	  if (reload_completed && rtx_equal_p (target, source))	    return 0;	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target, source));	  return 1;	}      /* We don't know how to handle other cases yet.  */      gcc_assert (remainder == 0xffffffff);      if (generate)	emit_constant_insn (cond,			    gen_rtx_SET (VOIDmode, target,					 gen_rtx_NOT (mode, source)));      return 1;    case MINUS:      /* We treat MINUS as (val - source), since (source - val) is always	 passed as (source + (-val)).  */      if (remainder == 0)	{	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target,					     gen_rtx_NEG (mode, source)));	  return 1;	}      if (const_ok_for_arm (val))	{	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target,					     gen_rtx_MINUS (mode, GEN_INT (val),							    source)));	  return 1;	}      can_negate = 1;      break;    default:      gcc_unreachable ();    }  /* If we can do it in one insn get out quickly.  */  if (const_ok_for_arm (val)      || (can_negate_initial && const_ok_for_arm (-val))      || (can_invert && const_ok_for_arm (~val)))    {      if (generate)	emit_constant_insn (cond,			    gen_rtx_SET (VOIDmode, target,					 (source					  ? gen_rtx_fmt_ee (code, mode, source,							    GEN_INT (val))					  : GEN_INT (val))));      return 1;    }  /* Calculate a few attributes that may be useful for specific     optimizations.  */  for (i = 31; i >= 0; i--)    {      if ((remainder & (1 << i)) == 0)	clear_sign_bit_copies++;      else	break;    }  for (i = 31; i >= 0; i--)    {      if ((remainder & (1 << i)) != 0)	set_sign_bit_copies++;      else	break;    }  for (i = 0; i <= 31; i++)    {      if ((remainder & (1 << i)) == 0)	clear_zero_bit_copies++;      else	break;    }  for (i = 0; i <= 31; i++)    {      if ((remainder & (1 << i)) != 0)	set_zero_bit_copies++;      else	break;    }  switch (code)    {    case SET:      /* See if we can do this by sign_extending a constant that is known	 to be negative.  This is a good, way of doing it, since the shift	 may well merge into a subsequent insn.  */      if (set_sign_bit_copies > 1)	{	  if (const_ok_for_arm	      (temp1 = ARM_SIGN_EXTEND (remainder					<< (set_sign_bit_copies - 1))))	    {	      if (generate)		{		  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;		  emit_constant_insn (cond,				      gen_rtx_SET (VOIDmode, new_src,						   GEN_INT (temp1)));		  emit_constant_insn (cond,				      gen_ashrsi3 (target, new_src,						   GEN_INT (set_sign_bit_copies - 1)));		}	      return 2;	    }	  /* For an inverted constant, we will need to set the low bits,	     these will be shifted out of harm's way.  */	  temp1 |= (1 << (set_sign_bit_copies - 1)) - 1;	  if (const_ok_for_arm (~temp1))	    {	      if (generate)		{		  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;		  emit_constant_insn (cond,				      gen_rtx_SET (VOIDmode, new_src,						   GEN_INT (temp1)));		  emit_constant_insn (cond,				      gen_ashrsi3 (target, new_src,						   GEN_INT (set_sign_bit_copies - 1)));		}	      return 2;	    }	}      /* See if we can calculate the value as the difference between two	 valid immediates.  */      if (clear_sign_bit_copies + clear_zero_bit_copies <= 16)	{	  int topshift = clear_sign_bit_copies & ~1;	  temp1 = ARM_SIGN_EXTEND ((remainder + (0x00800000 >> topshift))				   & (0xff000000 >> topshift));	  /* If temp1 is zero, then that means the 9 most significant	     bits of remainder were 1 and we've caused it to overflow.	     When topshift is 0 we don't need to do anything since we	     can borrow from 'bit 32'.  */	  if (temp1 == 0 && topshift != 0)	    temp1 = 0x80000000 >> (topshift - 1);	  temp2 = ARM_SIGN_EXTEND (temp1 - remainder);	  if (const_ok_for_arm (temp2))	    {	      if (generate)		{		  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;		  emit_constant_insn (cond,				      gen_rtx_SET (VOIDmode, new_src,						   GEN_INT (temp1)));		  emit_constant_insn (cond,				      gen_addsi3 (target, new_src,						  GEN_INT (-temp2)));		}	      return 2;	    }	}      /* See if we can generate this by setting the bottom (or the top)	 16 bits, and then shifting these into the other half of the	 word.  We only look for the simplest cases, to do more would cost	 too much.  Be careful, however, not to generate this when the	 alternative would take fewer insns.  */      if (val & 0xffff0000)	{	  temp1 = remainder & 0xffff0000;	  temp2 = remainder & 0x0000ffff;	  /* Overlaps outside this range are best done using other methods.  */	  for (i = 9; i < 24; i++)	    {	      if ((((temp2 | (temp2 << i)) & 0xffffffff) == remainder)		  && !const_ok_for_arm (temp2))		{		  rtx new_src = (subtargets				 ? (generate ? gen_reg_rtx (mode) : NULL_RTX)				 : target);		  insns = arm_gen_constant (code, mode, cond, temp2, new_src,					    source, subtargets, generate);		  source = new_src;		  if (generate)		    emit_constant_insn		      (cond,		       gen_rtx_SET		       (VOIDmode, target,			gen_rtx_IOR (mode,				     gen_rtx_ASHIFT (mode, source,						     GEN_INT (i)),				     source)));		  return insns + 1;		}	    }	  /* Don't duplicate cases already considered.  */	  for (i = 17; i < 24; i++)	    {	      if (((temp1 | (temp1 >> i)) == remainder)		  && !const_ok_for_arm (temp1))		{		  rtx new_src = (subtargets				 ? (generate ? gen_reg_rtx (mode) : NULL_RTX)				 : target);		  insns = arm_gen_constant (code, mode, cond, temp1, new_src,					    source, subtargets, generate);		  source = new_src;		  if (generate)		    emit_constant_insn		      (cond,		       gen_rtx_SET (VOIDmode, target,				    gen_rtx_IOR				    (mode,				     gen_rtx_LSHIFTRT (mode, source,						       GEN_INT (i)),				     source)));		  return insns + 1;		}	    }	}      break;    case IOR:    case XOR:      /* If we have IOR or XOR, and the constant can be loaded in a	 single instruction, and we can find a temporary to put it in,	 then this can be done in two instructions instead of 3-4.  */      if (subtargets	  /* TARGET can't be NULL if SUBTARGETS is 0 */	  || (reload_completed && !reg_mentioned_p (target, source)))	{	  if (const_ok_for_arm (ARM_SIGN_EXTEND (~val)))	    {	      if (generate)		{		  rtx sub = subtargets ? gen_reg_rtx (mode) : target;		  emit_constant_insn (cond,				      gen_rtx_SET (VOIDmode, sub,						   GEN_INT (val)));		  

⌨️ 快捷键说明

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