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

📄 expr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
   This function *must not* call protect_from_queue   except when putting X into an insn (in which case convert_move does it).  */rtxconvert_to_mode (mode, x, unsignedp)     enum machine_mode mode;     rtx x;     int unsignedp;{  register rtx temp;   /* If FROM is a SUBREG that indicates that we have already done at least     the required extension, strip it.  */  if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)      && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)    x = gen_lowpart (mode, x);  if (mode == GET_MODE (x))    return x;  /* There is one case that we must handle specially: If we are converting     a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and     we are to interpret the constant as unsigned, gen_lowpart will do     the wrong if the constant appears negative.  What we want to do is     make the high-order word of the constant zero, not all ones.  */  if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT      && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT      && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)    return immed_double_const (INTVAL (x), (HOST_WIDE_INT) 0, mode);  /* We can do this with a gen_lowpart if both desired and current modes     are integer, and this is either a constant integer, a register, or a     non-volatile MEM.  Except for the constant case, we must be narrowing     the operand.  */  if (GET_CODE (x) == CONST_INT      || (GET_MODE_CLASS (mode) == MODE_INT	  && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT	  && (GET_CODE (x) == CONST_DOUBLE	      || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x))		  && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x))		      && direct_load[(int) mode]		      || GET_CODE (x) == REG)))))    return gen_lowpart (mode, x);  temp = gen_reg_rtx (mode);  convert_move (temp, x, unsignedp);  return temp;}/* Generate several move instructions to copy LEN bytes   from block FROM to block TO.  (These are MEM rtx's with BLKmode).   The caller must pass FROM and TO    through protect_from_queue before calling.   ALIGN (in bytes) is maximum alignment we can assume.  */struct move_by_pieces{  rtx to;  rtx to_addr;  int autinc_to;  int explicit_inc_to;  rtx from;  rtx from_addr;  int autinc_from;  int explicit_inc_from;  int len;  int offset;  int reverse;};static void move_by_pieces_1 ();static int move_by_pieces_ninsns ();static voidmove_by_pieces (to, from, len, align)     rtx to, from;     int len, align;{  struct move_by_pieces data;  rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);  int max_size = MOVE_MAX + 1;  data.offset = 0;  data.to_addr = to_addr;  data.from_addr = from_addr;  data.to = to;  data.from = from;  data.autinc_to    = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC       || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);  data.autinc_from    = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC       || GET_CODE (from_addr) == POST_INC       || GET_CODE (from_addr) == POST_DEC);  data.explicit_inc_from = 0;  data.explicit_inc_to = 0;  data.reverse    = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);  if (data.reverse) data.offset = len;  data.len = len;  /* If copying requires more than two move insns,     copy addresses to registers (to make displacements shorter)     and use post-increment if available.  */  if (!(data.autinc_from && data.autinc_to)      && move_by_pieces_ninsns (len, align) > 2)    {#ifdef HAVE_PRE_DECREMENT      if (data.reverse && ! data.autinc_from)	{	  data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));	  data.autinc_from = 1;	  data.explicit_inc_from = -1;	}#endif#ifdef HAVE_POST_INCREMENT      if (! data.autinc_from)	{	  data.from_addr = copy_addr_to_reg (from_addr);	  data.autinc_from = 1;	  data.explicit_inc_from = 1;	}#endif      if (!data.autinc_from && CONSTANT_P (from_addr))	data.from_addr = copy_addr_to_reg (from_addr);#ifdef HAVE_PRE_DECREMENT      if (data.reverse && ! data.autinc_to)	{	  data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));	  data.autinc_to = 1;	  data.explicit_inc_to = -1;	}#endif#ifdef HAVE_POST_INCREMENT      if (! data.reverse && ! data.autinc_to)	{	  data.to_addr = copy_addr_to_reg (to_addr);	  data.autinc_to = 1;	  data.explicit_inc_to = 1;	}#endif      if (!data.autinc_to && CONSTANT_P (to_addr))	data.to_addr = copy_addr_to_reg (to_addr);    }  if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS)      || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)    align = MOVE_MAX;  /* First move what we can in the largest integer mode, then go to     successively smaller modes.  */  while (max_size > 1)    {      enum machine_mode mode = VOIDmode, tmode;      enum insn_code icode;      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);	   tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))	if (GET_MODE_SIZE (tmode) < max_size)	  mode = tmode;      if (mode == VOIDmode)	break;      icode = mov_optab->handlers[(int) mode].insn_code;      if (icode != CODE_FOR_nothing	  && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,			   GET_MODE_SIZE (mode)))	move_by_pieces_1 (GEN_FCN (icode), mode, &data);      max_size = GET_MODE_SIZE (mode);    }  /* The code above should have handled everything.  */  if (data.len != 0)    abort ();}/* Return number of insns required to move L bytes by pieces.   ALIGN (in bytes) is maximum alignment we can assume.  */static intmove_by_pieces_ninsns (l, align)     unsigned int l;     int align;{  register int n_insns = 0;  int max_size = MOVE_MAX + 1;  if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS)      || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)    align = MOVE_MAX;  while (max_size > 1)    {      enum machine_mode mode = VOIDmode, tmode;      enum insn_code icode;      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);	   tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))	if (GET_MODE_SIZE (tmode) < max_size)	  mode = tmode;      if (mode == VOIDmode)	break;      icode = mov_optab->handlers[(int) mode].insn_code;      if (icode != CODE_FOR_nothing	  && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,			   GET_MODE_SIZE (mode)))	n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);      max_size = GET_MODE_SIZE (mode);    }  return n_insns;}/* Subroutine of move_by_pieces.  Move as many bytes as appropriate   with move instructions for mode MODE.  GENFUN is the gen_... function   to make a move insn for that mode.  DATA has all the other info.  */static voidmove_by_pieces_1 (genfun, mode, data)     rtx (*genfun) ();     enum machine_mode mode;     struct move_by_pieces *data;{  register int size = GET_MODE_SIZE (mode);  register rtx to1, from1;  while (data->len >= size)    {      if (data->reverse) data->offset -= size;      to1 = (data->autinc_to	     ? gen_rtx (MEM, mode, data->to_addr)	     : change_address (data->to, mode,			       plus_constant (data->to_addr, data->offset)));      from1 =	(data->autinc_from	 ? gen_rtx (MEM, mode, data->from_addr)	 : change_address (data->from, mode,			   plus_constant (data->from_addr, data->offset)));#ifdef HAVE_PRE_DECREMENT      if (data->explicit_inc_to < 0)	emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));      if (data->explicit_inc_from < 0)	emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));#endif      emit_insn ((*genfun) (to1, from1));#ifdef HAVE_POST_INCREMENT      if (data->explicit_inc_to > 0)	emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));      if (data->explicit_inc_from > 0)	emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));#endif      if (! data->reverse) data->offset += size;      data->len -= size;    }}/* Emit code to move a block Y to a block X.   This may be done with string-move instructions,   with multiple scalar move instructions, or with a library call.   Both X and Y must be MEM rtx's (perhaps inside VOLATILE)   with mode BLKmode.   SIZE is an rtx that says how long they are.   ALIGN is the maximum alignment we can assume they have,   measured in bytes.  */voidemit_block_move (x, y, size, align)     rtx x, y;     rtx size;     int align;{  if (GET_MODE (x) != BLKmode)    abort ();  if (GET_MODE (y) != BLKmode)    abort ();  x = protect_from_queue (x, 1);  y = protect_from_queue (y, 0);  size = protect_from_queue (size, 0);  if (GET_CODE (x) != MEM)    abort ();  if (GET_CODE (y) != MEM)    abort ();  if (size == 0)    abort ();  if (GET_CODE (size) == CONST_INT      && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO))    move_by_pieces (x, y, INTVAL (size), align);  else    {      /* Try the most limited insn first, because there's no point	 including more than one in the machine description unless	 the more limited one has some advantage.  */      rtx opalign = GEN_INT (align);      enum machine_mode mode;      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;	   mode = GET_MODE_WIDER_MODE (mode))	{	  enum insn_code code = movstr_optab[(int) mode];	  if (code != CODE_FOR_nothing	      /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT		 here because if SIZE is less than the mode mask, as it is		 returned by the macro, it will definately be less than the		 actual mode mask.  */	      && (unsigned) INTVAL (size) <= GET_MODE_MASK (mode)	      && (insn_operand_predicate[(int) code][0] == 0		  || (*insn_operand_predicate[(int) code][0]) (x, BLKmode))	      && (insn_operand_predicate[(int) code][1] == 0		  || (*insn_operand_predicate[(int) code][1]) (y, BLKmode))	      && (insn_operand_predicate[(int) code][3] == 0		  || (*insn_operand_predicate[(int) code][3]) (opalign,							       VOIDmode)))	    {	      rtx op2;	      rtx last = get_last_insn ();	      rtx pat;	      op2 = convert_to_mode (mode, size, 1);	      if (insn_operand_predicate[(int) code][2] != 0		  && ! (*insn_operand_predicate[(int) code][2]) (op2, mode))		op2 = copy_to_mode_reg (mode, op2);	      pat = GEN_FCN ((int) code) (x, y, op2, opalign);	      if (pat)		{		  emit_insn (pat);		  return;		}	      else		delete_insns_since (last);	    }	}#ifdef TARGET_MEM_FUNCTIONS      emit_library_call (memcpy_libfunc, 0,			 VOIDmode, 3, XEXP (x, 0), Pmode,			 XEXP (y, 0), Pmode,			 convert_to_mode (Pmode, size, 1), Pmode);#else      emit_library_call (bcopy_libfunc, 0,			 VOIDmode, 3, XEXP (y, 0), Pmode,			 XEXP (x, 0), Pmode,			 convert_to_mode (Pmode, size, 1), Pmode);#endif    }}/* Copy all or part of a value X into registers starting at REGNO.   The number of registers to be filled is NREGS.  */voidmove_block_to_reg (regno, x, nregs, mode)     int regno;     rtx x;     int nregs;     enum machine_mode mode;{  int i;  rtx pat, last;  if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))    x = validize_mem (force_const_mem (mode, x));  /* See if the machine can do this with a load multiple insn.  */#ifdef HAVE_load_multiple  last = get_last_insn ();  pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x,			   GEN_INT (nregs));  if (pat)    {      emit_insn (pat);      return;    }  else    delete_insns_since (last);#endif  for (i = 0; i < nregs; i++)    emit_move_insn (gen_rtx (REG, word_mode, regno + i),		    operand_subword_force (x, i, mode));}/* Copy all or part of a BLKmode value X out of registers starting at REGNO.   The number of registers to be filled is NREGS.  */voidmove_block_from_reg (regno, x, nregs)     int regno;     rtx x;     int nregs;{  int i;  rtx pat, last;  /* See if the machine can do this with a store multiple insn.  */#ifdef HAVE_store_multiple  last = get_last_insn ();  pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno),			    GEN_INT (nregs));  if (pat)    {      emit_insn (pat);      return;    }  else    delete_insns_since (last);#endif  for (i = 0; i < nregs; i++)    {      rtx tem = operand_subword (x, i, 1, BLKmode);      if (tem == 0)	abort ();      emit_move_insn (tem, gen_rtx (REG, word_mode, regno + i));    }}/* Mark NREGS consecutive regs, starting at REGNO, as being live now.  */voiduse_regs (regno, nregs)     int regno;     int nregs;{  int i;

⌨️ 快捷键说明

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