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

📄 arm.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      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;	}      if (remainder == 0xffffffff)	{	  if (generate)	    emit_constant_insn (cond,				gen_rtx_SET (VOIDmode, target,					     gen_rtx_NOT (mode, source)));	  return 1;	}      /* We don't know how to handle this yet below.  */      abort ();    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:      abort ();    }  /* 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 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)));		  emit_constant_insn (cond,				      gen_rtx_SET (VOIDmode, target,						   gen_rtx_fmt_ee (code, mode,								   source, sub)));		}	      return 2;	    }	}      if (code == XOR)	break;      if (set_sign_bit_copies > 8	  && (val & (-1 << (32 - set_sign_bit_copies))) == val)	{	  if (generate)	    {	      rtx sub = subtargets ? gen_reg_rtx (mode) : target;	      rtx shift = GEN_INT (set_sign_bit_copies);	      emit_constant_insn		(cond,		 gen_rtx_SET (VOIDmode, sub,			      gen_rtx_NOT (mode,					   gen_rtx_ASHIFT (mode,							   source,							   shift))));	      emit_constant_insn		(cond,		 gen_rtx_SET (VOIDmode, target,			      gen_rtx_NOT (mode,					   gen_rtx_LSHIFTRT (mode, sub,							     shift))));	    }	  return 2;	}      if (set_zero_bit_copies > 8	  && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)	{	  if (generate)	    {	      rtx sub = subtargets ? gen_reg_rtx (mode) : target;	      rtx shift = GEN_INT (set_zero_bit_copies);	      emit_constant_insn		(cond,		 gen_rtx_SET (VOIDmode, sub,			      gen_rtx_NOT (mode,					   gen_rtx_LSHIFTRT (mode,							     source,							     shift))));	      emit_constant_insn		(cond,		 gen_rtx_SET (VOIDmode, target,			      gen_rtx_NOT (mode,					   gen_rtx_ASHIFT (mode, sub,							   shift))));	    }	  return 2;	}      if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val)))	{	  if (generate)	    {	      rtx sub = subtargets ? gen_reg_rtx (mode) : target;	      emit_constant_insn (cond,				  gen_rtx_SET (VOIDmode, sub,					       gen_rtx_NOT (mode, source)));	      source = sub;	      if (subtargets)		sub = gen_reg_rtx (mode);	      emit_constant_insn (cond,				  gen_rtx_SET (VOIDmode, sub,					       gen_rtx_AND (mode, source,							    GEN_INT (temp1))));	      emit_constant_insn (cond,				  gen_rtx_SET (VOIDmode, target,					       gen_rtx_NOT (mode, sub)));	    }	  return 3;	}      break;    case AND:      /* See if two shifts will do 2 or more insn's worth of work.  */      if (clear_sign_bit_copies >= 16 && clear_sign_bit_copies < 24)	{	  HOST_WIDE_INT shift_mask = ((0xffffffff				       << (32 - clear_sign_bit_copies))				      & 0xffffffff);	  if ((remainder | shift_mask) != 0xffffffff)	    {	      if (generate)		{		  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;		  insns = arm_gen_constant (AND, mode, cond,					    remainder | shift_mask,					    new_src, source, subtargets, 1);		  source = new_src;		}	      else		{		  rtx targ = subtargets ? NULL_RTX : target;		  insns = arm_gen_constant (AND, mode, cond,					    remainder | shift_mask,					    targ, source, subtargets, 0);		}	    }	  if (generate)	    {	      rtx new_src = subtargets ? gen_reg_rtx (mode) : target;	      rtx shift = GEN_INT (clear_sign_bit_copies);	      emit_insn (gen_ashlsi3 (new_src, source, shift));	      emit_insn (gen_lshrsi3 (target, new_src, shift));	    }	  return insns + 2;	}      if (clear_zero_bit_copies >= 16 && clear_zero_bit_copies < 24)	{	  HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1;	  if ((remainder | shift_mask) != 0xffffffff)	    {	      if (generate)		{		  rtx new_src = subtargets ? gen_reg_rtx (mode) : target;		  insns = arm_gen_constant (AND, mode, cond,					    remainder | shift_mask,					    new_src, source, subtargets, 1);		  source = new_src;		}	      else		{		  rtx targ = subtargets ? NULL_RTX : target;		  insns = arm_gen_constant (AND, mode, cond,					    remainder | shift_mask,					    targ, source, subtargets, 0);		}	    }	  if (generate)	    {	      rtx new_src = subtargets ? gen_reg_rtx (mode) : target;	      rtx shift = GEN_INT (clear_zero_bit_copies);	      emit_insn (gen_lshrsi3 (new_src, source, shift));	      emit_insn (gen_ashlsi3 (target, new_src, shift));	    }	  return insns + 2;	}      break;    default:      break;    }  for (i = 0; i < 32; i++)    if (remainder & (1 << i))      num_bits_set++;  if (code == AND || (can_invert && num_bits_set > 16))    remainder = (~remainder) & 0xffffffff;  else if (code == PLUS && num_bits_set > 16)    remainder = (-remainder) & 0xffffffff;  else    {      can_invert = 0;      can_negate = 0;    }  /* Now try and find a way of doing the job in either two or three     instructions.     We start by looking for the largest block of zeros that are 

⌨️ 快捷键说明

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