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

📄 arm.c

📁 这是一个linux 嵌入式系统中很重要的GCC编译器程序
💻 C
📖 第 1 页 / 共 5 页
字号:
				 : target);		  insns = arm_gen_constant (code, mode, temp2, new_src,					    source, subtargets, generate);		  source = new_src;		  if (generate)		    emit_insn (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, temp1, new_src,					    source, subtargets, generate);		  source = new_src;		  if (generate)		    emit_insn		      (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_insn (gen_rtx_SET (VOIDmode, sub, GEN_INT (val)));		  emit_insn (gen_rtx_SET (VOIDmode, target, 					  gen_rtx (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_insn (gen_rtx_SET (VOIDmode, sub,				      gen_rtx_NOT (mode, 						   gen_rtx_ASHIFT (mode,								   source, 								   shift))));	      emit_insn (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_insn (gen_rtx_SET (VOIDmode, sub,				      gen_rtx_NOT (mode,						   gen_rtx_LSHIFTRT (mode,								     source,								     shift))));	      emit_insn (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_insn (gen_rtx_SET (VOIDmode, sub,				      gen_rtx_NOT (mode, source)));	      source = sub;	      if (subtargets)		sub = gen_reg_rtx (mode);	      emit_insn (gen_rtx_SET (VOIDmode, sub,				      gen_rtx_AND (mode, source, 						   GEN_INT (temp1))));	      emit_insn (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, remainder | shift_mask,					    new_src, source, subtargets, 1);		  source = new_src;		}	      else		{		  rtx targ = subtargets ? NULL_RTX : target;		  insns = arm_gen_constant (AND, mode, 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, remainder | shift_mask,					    new_src, source, subtargets, 1);		  source = new_src;		}	      else		{		  rtx targ = subtargets ? NULL_RTX : target;		  insns = arm_gen_constant (AND, mode, 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 aligned on     a 2-bit boundary, we then fill up the temps, wrapping around to the     top of the word when we drop off the bottom.     In the worst case this code should produce no more than four insns. */  {    int best_start = 0;    int best_consecutive_zeros = 0;    for (i = 0; i < 32; i += 2)      {	int consecutive_zeros = 0;	if (! (remainder & (3 << i)))	  {	    while ((i < 32) && ! (remainder & (3 << i)))	      {		consecutive_zeros += 2;		i += 2;	      }	    if (consecutive_zeros > best_consecutive_zeros)	      {		best_consecutive_zeros = consecutive_zeros;		best_start = i - consecutive_zeros;	      }	    i -= 2;	  }      }    /* Now start emitting the insns, starting with the one with the highest       bit set: we do this so that the smallest number will be emitted last;       this is more likely to be combinable with addressing insns. */    i = best_start;    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;	    if (generate)	      {		rtx new_src;		if (code == SET)		  emit_insn (gen_rtx_SET (VOIDmode,					  new_src = (subtargets						     ? gen_reg_rtx (mode)						     : target),					  GEN_INT (can_invert						   ? ~temp1 : temp1)));		else if (code == MINUS)		  emit_insn (gen_rtx_SET (VOIDmode,					  new_src = (subtargets						     ? gen_reg_rtx (mode)						     : target),					  gen_rtx (code, mode, GEN_INT (temp1),						   source)));		else		  emit_insn (gen_rtx_SET (VOIDmode,					  new_src = (remainder						     ? (subtargets							? gen_reg_rtx (mode)							: target)						     : target),					  gen_rtx (code, mode, source,						   GEN_INT (can_invert ? ~temp1							    : (can_negate							       ? -temp1							       : temp1)))));		source = new_src;	      }	    if (code == SET)	      {		can_invert = 0;		code = PLUS;	      }	    else if (code == MINUS)	      code = PLUS;	    insns++;	    i -= 6;	  }	i -= 2;      } while (remainder);  }  return insns;}/* Canonicalize a comparison so that we are more likely to recognize it.   This can be done for a few constant compares, where we can make the   immediate value easier to load.  */enum rtx_codearm_canonicalize_comparison (code, op1)     enum rtx_code code;     rtx *op1;{  unsigned HOST_WIDE_INT i = INTVAL (*op1);  switch (code)    {    case EQ:    case NE:      return code;    case GT:    case LE:      if (i != ((((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1))		- 1)	  && (const_ok_for_arm (i+1) || const_ok_for_arm (- (i+1))))	{	  *op1 = GEN_INT (i+1);	  return code == GT ? GE : LT;	}      break;    case GE:    case LT:      if (i != (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1))	  && (const_ok_for_arm (i-1) || const_ok_for_arm (- (i-1))))	{	  *op1 = GEN_INT (i-1);	  return code == GE ? GT : LE;	}      break;    case GTU:    case LEU:      if (i != ~((unsigned HOST_WIDE_INT) 0)	  && (const_ok_for_arm (i+1) || const_ok_for_arm (- (i+1))))	{	  *op1 = GEN_INT (i + 1);	  return code == GTU ? GEU : LTU;	}      break;    case GEU:    case LTU:      if (i != 0	  && (const_ok_for_arm (i - 1) || const_ok_for_arm (- (i - 1))))	{	  *op1 = GEN_INT (i - 1);	  return code == GEU ? GTU : LEU;	}      break;    default:      abort ();    }  return code;}/* Decide whether a type should be returned in memory (true)   or in a register (false).  This is called by the macro   RETURN_IN_MEMORY.  */intarm_return_in_memory (type)     tree type;{  if (! AGGREGATE_TYPE_P (type))    {      /* All simple types are returned in registers. */      return 0;    }  else if (int_size_in_bytes (type) > 4)    {      /* All structures/unions bigger than one word are returned in memory. */      return 1;    }  else if (TREE_CODE (type) == RECORD_TYPE)    {      tree field;      /* For a struct the APCS says that we must return in a register if	 every addressable element has an offset of zero.  For practical	 purposes this means that the structure can have at most one non	 bit-field element and that this element must be the first one in	 the structure.  */      /* Find the first field, ignoring non FIELD_DECL things which will	 have been created by C++.  */      for (field = TYPE_FIELDS (type);	   field && TREE_CODE (field) != FIELD_DECL;	   field = TREE_CHAIN (field))	continue;            if (field == NULL)	return 0; /* An empty structure.  Allowed by an extension to ANSI C. */      /* Now check the remaining fields, if any. */      for (field = TREE_CHAIN (field);	   field;	   field = TREE_CHAIN (field))	{	  if (TREE_CODE (field) != FIELD_DECL)	    continue;	  	  if (! DECL_BIT_FIELD_TYPE (field))	    return 1;	}      return 0;    }  else if (TREE_CODE (type) == UNION_TYPE)    {      tree field;      /* Unions can be returned in registers if every element is	 integral, or can be returned in an integer register.  */      for (field = TYPE_FIELDS (type);	   field;	   field = TREE_CHAIN (field))	{	  if (TREE_CODE (field) != FIELD_DECL)	    continue;	  if (FLOAT_TYPE_P (TREE_TYPE (field)))	    return 1;	  	  if (RETURN_IN_MEMORY (TREE_TYPE (field)))	    return 1;	}            return 0;    }    /* XXX Not sure what should be done for other aggregates, so put them in     memory. */  return 1;}intlegitimate_pic_operand_p (x)     rtx x;{  if (CONSTANT_P (x) && flag_pic      && (GET_CODE (x) == SYMBOL_REF	  || (GET_CODE (x) == CONST	      && GET_CODE (XEXP (x, 0)) == PLUS	      && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)))    return 0;  return 1;}

⌨️ 快捷键说明

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