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

📄 sh.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    case 1:      {	int first = attributes[2];	rtx operands[3];	if (first < 0)	  {	    emit_insn ((mask << right) <= 0xff		       ? gen_zero_extendqisi2(dest,					      gen_lowpart (QImode, source))		       : gen_zero_extendhisi2(dest,					      gen_lowpart (HImode, source)));	    source = dest;	  }	if (source != dest)	  emit_insn (gen_movsi (dest, source));	operands[0] = dest;	if (right)	  {	    operands[2] = GEN_INT (right);	    gen_shifty_hi_op (LSHIFTRT, operands);	  }	if (first > 0)	  {	    operands[2] = GEN_INT (first);	    gen_shifty_hi_op (ASHIFT, operands);	    total_shift -= first;	    mask <<= first;	  }	if (first >= 0)	  emit_insn (mask <= 0xff		     ? gen_zero_extendqisi2(dest, gen_lowpart (QImode, dest))		     : gen_zero_extendhisi2(dest, gen_lowpart (HImode, dest)));	if (total_shift > 0)	  {	    operands[2] = GEN_INT (total_shift);	    gen_shifty_hi_op (ASHIFT, operands);	  }	break;      }    case 4:      shift_gen_fun = gen_shifty_op;    case 3:      /* If the topmost bit that matters is set, set the topmost bits	 that don't matter.  This way, we might be able to get a shorter	 signed constant.  */      if (mask & ((HOST_WIDE_INT)1 << (31 - total_shift)))	mask |= (HOST_WIDE_INT)~0 << (31 - total_shift);    case 2:      /* Don't expand fine-grained when combining, because that will         make the pattern fail.  */      if (rtx_equal_function_value_matters	  || reload_in_progress || reload_completed)	{	  rtx operands[3];  	  /* Cases 3 and 4 should be handled by this split	     only while combining  */	  if (kind > 2)	    abort ();	  if (right)	    {	      emit_insn (gen_lshrsi3 (dest, source, GEN_INT (right)));	      source = dest;	    }	  emit_insn (gen_andsi3 (dest, source, GEN_INT (mask)));	  if (total_shift)	    {	      operands[0] = dest;	      operands[1] = dest;	      operands[2] = GEN_INT (total_shift);	      shift_gen_fun (ASHIFT, operands);	    }	  break;	}      else	{	  int neg = 0;	  if (kind != 4 && total_shift < 16)	    {	      neg = -ext_shift_amounts[total_shift][1];	      if (neg > 0)		neg -= ext_shift_amounts[total_shift][2];	      else		neg = 0;	    }	  emit_insn (gen_and_shl_scratch (dest, source,					  GEN_INT (right),					  GEN_INT (mask),					  GEN_INT (total_shift + neg),					  GEN_INT (neg)));	  emit_insn (gen_movsi (dest, dest));	  break;	}    }  return 0;}/* Try to find a good way to implement the combiner pattern  [(set (match_operand:SI 0 "register_operand" "=r")        (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")                                    (match_operand:SI 2 "const_int_operand" "n")                         (match_operand:SI 3 "const_int_operand" "n")                         (const_int 0)))   (clobber (reg:SI T_REG))]  LEFT_RTX is operand 2 in the above pattern, and SIZE_RTX is operand 3.  return 0 for simple left / right shift combination.  return 1 for left shift / 8 bit sign extend / left shift.  return 2 for left shift / 16 bit sign extend / left shift.  return 3 for left shift / 8 bit sign extend / shift / sign extend.  return 4 for left shift / 16 bit sign extend / shift / sign extend.  return 5 for left shift / 16 bit sign extend / right shift  return 6 for < 8 bit sign extend / left shift.  return 7 for < 8 bit sign extend / left shift / single right shift.  If COSTP is nonzero, assign the calculated cost to *COSTP.  */intshl_sext_kind (left_rtx, size_rtx, costp)     rtx left_rtx, size_rtx;     int *costp;{  int left, size, insize, ext;  int cost, best_cost;  int kind;  left = INTVAL (left_rtx);  size = INTVAL (size_rtx);  insize = size - left;  if (insize <= 0)    abort ();  /* Default to left / right shift.  */  kind = 0;  best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size];  if (size <= 16)    {      /* 16 bit shift / sign extend / 16 bit shift */      cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size];      /* If ashiftrt_insns[16 - size] is 8, this choice will be overridden	 below, by alternative 3 or something even better.  */      if (cost < best_cost)	{	  kind = 5;	  best_cost = cost;	}    }  /* Try a plain sign extend between two shifts.  */  for (ext = 16; ext >= insize; ext -= 8)    {      if (ext <= size)	{	  cost = ext_shift_insns[ext - insize] + 1 + shift_insns[size - ext];	  if (cost < best_cost)	    {	      kind = ext / (unsigned) 8;	      best_cost = cost;	    }	}      /* Check if we can do a sloppy shift with a final signed shift	 restoring the sign.  */      if (EXT_SHIFT_SIGNED (size - ext))	cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1;      /* If not, maybe it's still cheaper to do the second shift sloppy,	 and do a final sign extend?  */      else if (size <= 16)	cost = ext_shift_insns[ext - insize] + 1	  + ext_shift_insns[size > ext ? size - ext : ext - size] + 1;      else	continue;      if (cost < best_cost)	{	  kind = ext / (unsigned) 8 + 2;	  best_cost = cost;	}    }  /* Check if we can sign extend in r0 */  if (insize < 8)    {      cost = 3 + shift_insns[left];      if (cost < best_cost)	{	  kind = 6;	  best_cost = cost;	}      /* Try the same with a final signed shift.  */      if (left < 31)	{	  cost = 3 + ext_shift_insns[left + 1] + 1;	  if (cost < best_cost)	    {	      kind = 7;	      best_cost = cost;	    }	}    }  if (TARGET_SH3)    {      /* Try to use a dynamic shift.  */      cost = shift_insns[32 - insize] + 1 + SH_DYNAMIC_SHIFT_COST;      if (cost < best_cost)	{	  kind = 0;	  best_cost = cost;	}    }  if (costp)    *costp = cost;  return kind;}/* Function to be used in the length attribute of the instructions   implementing this pattern.  */intshl_sext_length (insn)     rtx insn;{  rtx set_src, left_rtx, size_rtx;  int cost;  set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));  left_rtx = XEXP (XEXP (set_src, 0), 1);  size_rtx = XEXP (set_src, 1);  shl_sext_kind (left_rtx, size_rtx, &cost);  return cost;}/* Generate rtl for this pattern */intgen_shl_sext (dest, left_rtx, size_rtx, source)     rtx dest, left_rtx, size_rtx, source;{  int kind;  int left, size, insize, cost;  rtx operands[3];  kind = shl_sext_kind (left_rtx, size_rtx, &cost);  left = INTVAL (left_rtx);  size = INTVAL (size_rtx);  insize = size - left;  switch (kind)    {    case 1:    case 2:    case 3:    case 4:      {	int ext = kind & 1 ? 8 : 16;	int shift2 = size - ext;	/* Don't expand fine-grained when combining, because that will	   make the pattern fail.  */	if (! rtx_equal_function_value_matters	    && ! reload_in_progress && ! reload_completed)	  {	    emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));	    emit_insn (gen_movsi (dest, source));	    break;	  }	if (dest != source)	  emit_insn (gen_movsi (dest, source));	operands[0] = dest;	if (ext - insize)	  {	    operands[2] = GEN_INT (ext - insize);	    gen_shifty_hi_op (ASHIFT, operands);	  }	emit_insn (kind & 1		   ? gen_extendqisi2(dest, gen_lowpart (QImode, dest))		   : gen_extendhisi2(dest, gen_lowpart (HImode, dest)));	if (kind <= 2)	  {	    if (shift2)	      {		operands[2] = GEN_INT (shift2);		gen_shifty_op (ASHIFT, operands);	      }	  }	else	  {	    if (shift2 > 0)	      {		if (EXT_SHIFT_SIGNED (shift2))		  {		    operands[2] = GEN_INT (shift2 + 1);		    gen_shifty_op (ASHIFT, operands);		    operands[2] = GEN_INT (1);		    gen_shifty_op (ASHIFTRT, operands);		    break;		  }		operands[2] = GEN_INT (shift2);		gen_shifty_hi_op (ASHIFT, operands);	      }	    else if (shift2)	      {		operands[2] = GEN_INT (-shift2);		gen_shifty_hi_op (LSHIFTRT, operands);	      }	    emit_insn (size <= 8		       ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest))		       : gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));	  }	break;      }    case 5:      {	int i = 16 - size;	if (! rtx_equal_function_value_matters	    && ! reload_in_progress && ! reload_completed)	  emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));	else	  {	    operands[0] = dest;	    operands[2] = GEN_INT (16 - insize);	    gen_shifty_hi_op (ASHIFT, operands);	    emit_insn (gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));	  }	/* Don't use gen_ashrsi3 because it generates new pseudos.  */	while (--i >= 0)	  gen_ashift (ASHIFTRT, 1, dest);	break;      }    case 6:    case 7:      /* Don't expand fine-grained when combining, because that will	 make the pattern fail.  */      if (! rtx_equal_function_value_matters	  && ! reload_in_progress && ! reload_completed)	{	  emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));	  emit_insn (gen_movsi (dest, source));	  break;	}      emit_insn (gen_andsi3 (dest, source, GEN_INT ((1 << insize) - 1)));      emit_insn (gen_xorsi3 (dest, dest, GEN_INT (1 << (insize - 1))));      emit_insn (gen_addsi3 (dest, dest, GEN_INT (-1 << (insize - 1))));      operands[0] = dest;      operands[2] = kind == 7 ? GEN_INT (left + 1) : left_rtx;      gen_shifty_op (ASHIFT, operands);      if (kind == 7)	emit_insn (gen_ashrsi3_k (dest, dest, GEN_INT (1)));      break;    default:      return -1;    }  return 0;}/* Prefix a symbol_ref name with "datalabel".  */rtxgen_datalabel_ref (sym)     rtx sym;{  if (GET_CODE (sym) == LABEL_REF)    return gen_rtx_CONST (GET_MODE (sym),			  gen_rtx_UNSPEC (GET_MODE (sym),					  gen_rtvec (1, sym),					  UNSPEC_DATALABEL));      if (GET_CODE (sym) != SYMBOL_REF)    abort ();  XSTR (sym, 0) = concat (SH_DATALABEL_ENCODING, XSTR (sym, 0), NULL);  return sym;}/* The SH cannot load a large constant into a register, constants have to   come from a pc relative load.  The reference of a pc relative load   instruction must be less than 1k infront of the instruction.  This   means that we often have to dump a constant inside a function, and   generate code to branch around it.   It is important to minimize this, since the branches will slow things   down and make things bigger.   Worst case code looks like:   mov.l L1,rn   bra   L2   nop   align   L1:   .long value   L2:   ..   mov.l L3,rn   bra   L4   nop   align   L3:   .long value   L4:   ..   We fix this by performing a scan before scheduling, which notices which   instructions need to have their operands fetched from the constant table   and builds the table.   The algorithm is:   scan, find an instruction which needs a pcrel move.  Look forward, find the   last barrier which is within MAX_COUNT bytes of the requirement.   If there isn't one, make one.  Process all the instructions between   the find and the barrier.   In the above example, we can tell that L3 is within 1k of L1, so   the first move can be shrunk from the 3 insn+constant sequence into   just 1 insn, and the constant moved to L3 to make:   mov.l        L1,rn   ..   mov.l        L3,rn   bra          L4   nop   align   L3:.long value   L4:.long value   Then the second move becomes the target for the shortening process.  */typedef struct{  rtx value;			/* Value in table.  */  rtx label;			/* Label of value.  */  rtx wend;			/* End of window.  */  enum machine_mode mode;	/* Mode of value.  */  /* True if this constant is accessed as part of a post-increment     sequence.  Note that HImode constants are never accessed in this way.  */  bool part_of_sequence_p;} pool_node;/* The maximum number of constants that can fit into one pool, since   the pc relative range is 0...1020 bytes and constants are at least 4   bytes long.  */#define MAX_POOL_SIZE (1020/4)static pool_node pool_vector[MAX_POOL_SIZE];static int pool_size;static rtx pool_window_label;static int pool_window_last;/* ??? If we need a constant in HImode which is the truncated value of a   constant we need in SImode, we could combine the two entries thus saving   two bytes.  Is this common enough to be worth the effort of implementing   it?  *//* ??? This stuff should be done at the same time that we shorten branches.   As

⌨️ 快捷键说明

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