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

📄 sh.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (TARGET_SH2)    {      /* We have a mul insn, so we can never take more than the mul and the	 read of the mac reg, but count more because of the latency and extra	 reg usage.  */      if (TARGET_SMALLCODE)	return 2;      return 3;    }  /* If we're aiming at small code, then just count the number of     insns in a multiply call sequence.  */  if (TARGET_SMALLCODE)    return 5;  /* Otherwise count all the insns in the routine we'd be calling too.  */  return 20;}/* Code to expand a shift.  */voidgen_ashift (type, n, reg)     int type;     int n;     rtx reg;{  /* Negative values here come from the shift_amounts array.  */  if (n < 0)    {      if (type == ASHIFT)	type = LSHIFTRT;      else	type = ASHIFT;      n = -n;    }  switch (type)    {    case ASHIFTRT:      emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n)));      break;    case LSHIFTRT:      if (n == 1)	emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n)));      else	emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n)));      break;    case ASHIFT:      emit_insn (gen_ashlsi3_std (reg, reg, GEN_INT (n)));      break;    }}/* Same for HImode */voidgen_ashift_hi (type, n, reg)     int type;     int n;     rtx reg;{  /* Negative values here come from the shift_amounts array.  */  if (n < 0)    {      if (type == ASHIFT)	type = LSHIFTRT;      else	type = ASHIFT;      n = -n;    }  switch (type)    {    case ASHIFTRT:    case LSHIFTRT:      /* We don't have HImode right shift operations because using the	 ordinary 32 bit shift instructions for that doesn't generate proper	 zero/sign extension.	 gen_ashift_hi is only called in contexts where we know that the	 sign extension works out correctly.  */      {	int offset = 0;	if (GET_CODE (reg) == SUBREG)	  {	    offset = SUBREG_BYTE (reg);	    reg = SUBREG_REG (reg);	  }	gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, offset));	break;      }    case ASHIFT:      emit_insn (gen_ashlhi3_k (reg, reg, GEN_INT (n)));      break;    }}/* Output RTL to split a constant shift into its component SH constant   shift instructions.  */   voidgen_shifty_op (code, operands)     int code;     rtx *operands;{  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.  */voidgen_shifty_hi_op (code, operands)     int code;     rtx *operands;{  int value = INTVAL (operands[2]);  int max, i;  void (*gen_fun) PARAMS ((int, int, rtx));  /* 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 sym;  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);  sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (func_name));  emit_move_insn (wrk, sym);  emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk));  emit_move_insn (operands[0], gen_rtx_REG (SImode, 4));  return 1;}intsh_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 == (unsigned 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) & ((unsigned HOST_WIDE_INT)3 << 30)) == 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;  void (*shift_gen_fun) PARAMS ((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;

⌨️ 快捷键说明

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