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

📄 sh.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{  int value = INTVAL (operands[2]);  int max, i;  /* Truncate the shift count in case it is out of bounds.  */  value = value & 0x1f;   if (value == 31)    {      if (code == LSHIFTRT)	{	  emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));	  emit_insn (gen_movt (operands[0]));	  return;	}      else if (code == ASHIFT)	{	  /* There is a two instruction sequence for 31 bit left shifts,	     but it requires r0.  */	  if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0)	    {	      emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx));	      emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));	      return;	    }	}    }  else if (value == 0)    {      /* This can happen when not optimizing.  We must output something here	 to prevent the compiler from aborting in final.c after the try_split	 call.  */      emit_insn (gen_nop ());      return;    }  max = shift_insns[value];  for (i = 0; i < max; i++)    gen_ashift (code, shift_amounts[value][i], operands[0]);}   /* Same as above, but optimized for values where the topmost bits don't   matter.  */intgen_shifty_hi_op (code, operands)     int code;     rtx *operands;{  int value = INTVAL (operands[2]);  int max, i;  void (*gen_fun)();  /* This operation is used by and_shl for SImode values with a few     high bits known to be cleared.  */  value &= 31;  if (value == 0)    {      emit_insn (gen_nop ());      return;    }  gen_fun = GET_MODE (operands[0]) == HImode ? gen_ashift_hi : gen_ashift;  if (code == ASHIFT)    {      max = ext_shift_insns[value];      for (i = 0; i < max; i++)	gen_fun (code, ext_shift_amounts[value][i], operands[0]);    }  else    /* When shifting right, emit the shifts in reverse order, so that       solitary negative values come first.  */    for (i = ext_shift_insns[value] - 1; i >= 0; i--)      gen_fun (code, ext_shift_amounts[value][i], operands[0]);}/* Output RTL for an arithmetic right shift.  *//* ??? Rewrite to use super-optimizer sequences.  */intexpand_ashiftrt (operands)     rtx *operands;{  rtx wrk;  char func[18];  tree func_name;  int value;  if (TARGET_SH3)    {      if (GET_CODE (operands[2]) != CONST_INT)	{	  rtx count = copy_to_mode_reg (SImode, operands[2]);	  emit_insn (gen_negsi2 (count, count));	  emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));	  return 1;	}      else if (ashiftrt_insns[INTVAL (operands[2]) & 31]	       > 1 + SH_DYNAMIC_SHIFT_COST)	{	  rtx count	    = force_reg (SImode, GEN_INT (- (INTVAL (operands[2]) & 31)));	  emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));	  return 1;	}    }  if (GET_CODE (operands[2]) != CONST_INT)    return 0;  value = INTVAL (operands[2]) & 31;  if (value == 31)    {      emit_insn (gen_ashrsi2_31 (operands[0], operands[1]));      return 1;    }  else if (value >= 16 && value <= 19)    {      wrk = gen_reg_rtx (SImode);      emit_insn (gen_ashrsi2_16 (wrk, operands[1]));      value -= 16;      while (value--)	gen_ashift (ASHIFTRT, 1, wrk);      emit_move_insn (operands[0], wrk);      return 1;    }  /* Expand a short sequence inline, longer call a magic routine.  */  else if (value <= 5)    {      wrk = gen_reg_rtx (SImode);      emit_move_insn (wrk, operands[1]);      while (value--)	gen_ashift (ASHIFTRT, 1, wrk);      emit_move_insn (operands[0], wrk);      return 1;    }  wrk = gen_reg_rtx (Pmode);  /* Load the value into an arg reg and call a helper.  */  emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]);  sprintf (func, "__ashiftrt_r4_%d", value);  func_name = get_identifier (func);  emit_move_insn (wrk, gen_rtx (SYMBOL_REF, Pmode,				IDENTIFIER_POINTER (func_name)));  emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk));  emit_move_insn (operands[0], gen_rtx (REG, SImode, 4));  return 1;}int sh_dynamicalize_shift_p (count)     rtx count;{  return shift_insns[INTVAL (count)] > 1 + SH_DYNAMIC_SHIFT_COST;}/* Try to find a good way to implement the combiner pattern  [(set (match_operand:SI 0 "register_operand" "r")        (and: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"))) .  LEFT_RTX is operand 2 in the above pattern, and MASK_RTX is operand 3.  return 0 for simple right / left or left/right shift combination.  return 1 for a combination of shifts with zero_extend.  return 2 for a combination of shifts with an AND that needs r0.  return 3 for a combination of shifts with an AND that needs an extra    scratch register, when the three highmost bits of the AND mask are clear.  return 4 for a combination of shifts with an AND that needs an extra    scratch register, when any of the three highmost bits of the AND mask    is set.  If ATTRP is set, store an initial right shift width in ATTRP[0],  and the instruction length in ATTRP[1] .  These values are not valid  when returning 0.  When ATTRP is set and returning 1, ATTRP[2] gets set to the index into  shift_amounts for the last shift value that is to be used before the  sign extend.  */intshl_and_kind (left_rtx, mask_rtx, attrp)     rtx left_rtx, mask_rtx;     int *attrp;{  unsigned HOST_WIDE_INT mask, lsb, mask2, lsb2;  int left = INTVAL (left_rtx), right;  int best = 0;  int cost, best_cost = 10000;  int best_right = 0, best_len = 0;  int i;  int can_ext;  if (left < 0 || left > 31)    return 0;  if (GET_CODE (mask_rtx) == CONST_INT)    mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> left;  else    mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (SImode) >> left;  /* Can this be expressed as a right shift / left shift pair ? */  lsb = ((mask ^ (mask - 1)) >> 1) + 1;  right = exact_log2 (lsb);  mask2 = ~(mask + lsb - 1);  lsb2 = ((mask2 ^ (mask2 - 1)) >> 1) + 1;  /* mask has no zeroes but trailing zeroes <==> ! mask2 */  if (! mask2)    best_cost = shift_insns[right] + shift_insns[right + left];  /* mask has no trailing zeroes <==> ! right */  else if (! right && mask2 == ~(lsb2 - 1))    {      int late_right = exact_log2 (lsb2);      best_cost = shift_insns[left + late_right] + shift_insns[late_right];    }  /* Try to use zero extend */  if (mask2 == ~(lsb2 - 1))    {      int width, first;      for (width = 8; width <= 16; width += 8)	{	  /* Can we zero-extend right away? */	  if (lsb2 == (HOST_WIDE_INT)1 << width)	    {	      cost		= 1 + ext_shift_insns[right] + ext_shift_insns[left + right];	      if (cost < best_cost)		{		  best = 1;		  best_cost = cost;		  best_right = right;		  best_len = cost;		  if (attrp)		    attrp[2] = -1;		}	      continue;	    }	  /* ??? Could try to put zero extend into initial right shift,	     or even shift a bit left before the right shift. */	  /* Determine value of first part of left shift, to get to the	     zero extend cut-off point.  */	  first = width - exact_log2 (lsb2) + right;	  if (first >= 0 && right + left - first >= 0)	    {	      cost = ext_shift_insns[right] + ext_shift_insns[first] + 1		+ ext_shift_insns[right + left - first];	      if (cost < best_cost)		{		  best = 1;		  best_cost = cost;		  best_right = right;		  best_len = cost;		  if (attrp)		    attrp[2] = first;		  }	    }	}    }  /* Try to use r0 AND pattern */  for (i = 0; i <= 2; i++)    {      if (i > right)	break;      if (! CONST_OK_FOR_L (mask >> i))	continue;      cost = (i != 0) + 2 + ext_shift_insns[left + i];      if (cost < best_cost)	{	  best = 2;	  best_cost = cost;	  best_right = i;	  best_len = cost - 1;	}    }  /* Try to use a scratch register to hold the AND operand.  */  can_ext = ((mask << left) & 0xe0000000) == 0;  for (i = 0; i <= 2; i++)    {      if (i > right)	break;      cost = (i != 0) + (CONST_OK_FOR_I (mask >> i) ? 2 : 3)	+ (can_ext ? ext_shift_insns : shift_insns)[left + i];      if (cost < best_cost)	{	  best = 4 - can_ext;	  best_cost = cost;	  best_right = i;	  best_len = cost - 1 - ! CONST_OK_FOR_I (mask >> i);	}    }  if (attrp)    {      attrp[0] = best_right;      attrp[1] = best_len;    }  return best;}/* This is used in length attributes of the unnamed instructions   corresponding to shl_and_kind return values of 1 and 2.  */intshl_and_length (insn)     rtx insn;{  rtx set_src, left_rtx, mask_rtx;  int attributes[3];  set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));  left_rtx = XEXP (XEXP (set_src, 0), 1);  mask_rtx = XEXP (set_src, 1);  shl_and_kind (left_rtx, mask_rtx, attributes);  return attributes[1];}/* This is used in length attribute of the and_shl_scratch instruction.  */intshl_and_scr_length (insn)     rtx insn;{  rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));  int len = shift_insns[INTVAL (XEXP (set_src, 1))];  rtx op = XEXP (set_src, 0);  len += shift_insns[INTVAL (XEXP (op, 1))] + 1;  op = XEXP (XEXP (op, 0), 0);  return len + shift_insns[INTVAL (XEXP (op, 1))];}/* Generating rtl? */extern int rtx_equal_function_value_matters;/* Generate rtl for instructions for which shl_and_kind advised a particular   method of generating them, i.e. returned zero.  */intgen_shl_and (dest, left_rtx, mask_rtx, source)     rtx dest, left_rtx, mask_rtx, source;{  int attributes[3];  unsigned HOST_WIDE_INT mask;  int kind = shl_and_kind (left_rtx, mask_rtx, attributes);  int right, total_shift;  int (*shift_gen_fun) PROTO((int, rtx*)) = gen_shifty_hi_op;  right = attributes[0];  total_shift = INTVAL (left_rtx) + right;  mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> total_shift;  switch (kind)    {    default:      return -1;    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 2:    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);      /* 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];  	  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 18))]  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;

⌨️ 快捷键说明

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