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

📄 expr.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
    through protect_from_queue before calling.   ALIGN (in bytes) is maximum alignment we can assume.  */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;  data.to_struct = MEM_IN_STRUCT_P (to);  data.from_struct = MEM_IN_STRUCT_P (from);  /* 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 (! 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 (! 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)));      MEM_IN_STRUCT_P (to1) = data->to_struct;      from1 =	(data->autinc_from	 ? gen_rtx (MEM, mode, data->from_addr)	 : change_address (data->from, mode,			   plus_constant (data->from_addr, data->offset)));      MEM_IN_STRUCT_P (from1) = data->from_struct;#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 definitely be less than the		 actual mode mask.  */	      && ((GET_CODE (size) == CONST_INT		   && ((unsigned HOST_WIDE_INT) INTVAL (size)		       <= GET_MODE_MASK (mode)))		  || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)	      && (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 (TYPE_MODE (sizetype), size,					  TREE_UNSIGNED (sizetype)),			 TYPE_MODE (sizetype));#else      emit_library_call (bcopy_libfunc, 0,			 VOIDmode, 3, XEXP (y, 0), Pmode,			 XEXP (x, 0), Pmode,			 convert_to_mode (TYPE_MODE (sizetype), size,					  TREE_UNSIGNED (sizetype)),			 TYPE_MODE (sizetype));#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 (nregs == 0)    return;  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  if (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.  SIZE indicates the number   of bytes in the object X.  */voidmove_block_from_reg (regno, x, nregs, size)     int regno;     rtx x;     int nregs;     int size;{  int i;  rtx pat, last;  /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned     to the left before storing to memory.  */  if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)    {      rtx tem = operand_subword (x, 0, 1, BLKmode);      rtx shift;      if (tem == 0)	abort ();      shift = expand_shift (LSHIFT_EXPR, word_mode,			    gen_rtx (REG, word_mode, regno),			    build_int_2 ((UNITS_PER_WORD - size)					 * BITS_PER_UNIT, 0), NULL_RTX, 0);      emit_move_insn (tem, shift);      return;    }  /* See if the machine can do this with a store multiple insn.  */#ifdef HAVE_store_multiple  if (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));    }}/* Add a USE expression for REG to the (possibly empty) list pointed   to by CALL_FUSAGE.  REG must denote a hard register.  */voiduse_reg (call_fusage, reg)     rtx *call_fusage, reg;{  if (GET_CODE (reg) != REG      || REGNO (reg) >= FIRST_PSEUDO_REGISTER)    abort();  *call_fusage    = gen_rtx (EXPR_LIST, VOIDmode,	       gen_rtx (USE, VOIDmode, reg), *call_fusage);}/* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs,   starting at REGNO.  All of these registers must be hard registers.  */voiduse_regs (call_fusage, regno, nregs)     rtx *call_fusage;     int regno;     int nregs;{  int i;  if (regno + nregs > FIRST_PSEUDO_REGISTER)    abort ();  for (i = 0; i < nregs; i++)    use_reg (call_fusage, gen_rtx (REG, reg_raw_mode[regno + i], regno + i));}/* Write zeros through the storage of OBJECT.   If OBJECT has BLKmode, SIZE is its length in bytes.  */voidclear_storage (object, size)     rtx object;     rtx size;{  if (GET_MODE (object) == BLKmode)    {#ifdef TARGET_MEM_FUNCTIONS      emit_library_call (memset_libfunc, 0,			 VOIDmode, 3,			 XEXP (object, 0), Pmode, const0_rtx, ptr_mode,			 convert_to_mode (TYPE_MODE (sizetype),					  size, TREE_UNSIGNED (sizetype)),			 TYPE_MODE (sizetype));#else

⌨️ 快捷键说明

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